如何在PHP应用程序中正确地嵌入Angular应用程序

8

假设我正在开发一个PHP应用程序。在网站的某个页面上,有一个复杂的交互式应用程序,我想使用Angular来实现。问题是,我仍然希望该页面的页眉和页脚与网站的其他部分相匹配。我很想能够像这样做:

// main-template.php
<html>
    <head>
        <title>My Site-wide Header</title>
        <script src="site-wide-script.js"></script>
        <link href="site-wide-styles.css" rel="stylesheet">
        <?php if ($somevar == true) : ?>
            <?php echo "Yes, it has to be PHP"; ?>
        <?php endif; ?>
    </head>
    <body>
        <header>
            <ul>
                <li><a href="/home">Home</a></li>
                <li><a href="/about">About</a></li>
                <li><a href="/contact">Contact</a></li>
            </ul>
        </header>

        <!-- Drop entire Angular application here -->

    </body>
</html>

对我而言,只需使用PHP include Angular HTML文件就可以实现一定的功能,但这相当不可靠,因为Angular index.html文件已经包含了htmlbody等标签。当然,我可以DOM解析Angular文件并在包含前修复所有这些问题......但我更喜欢一个更好的解决方案。

在我的搜索中,似乎找不到任何官方推荐的方法来实现这一点。实际上,我似乎找不到任何人使用Angular做类似的事情的例子 - 所有我的搜索结果都是关于使用AngularJS 进行类似操作的。是否有任何可靠的方法可以用Angular完成这个任务呢?


1
你可以使用一个 iframe 吗? - user184994
我不喜欢那个解决方案,因为(1)iframe不会尊重内容大小,除非你使用JS,(2)它会隐藏Angular应用程序的URL。 - Pete
在构建 Angular 应用之前,您可以尝试从 index.html 中除了 <app-root> 标签以外的所有内容。看起来构建正常。 - user184994
@user184994,我非常喜欢这个解决方案...但是一旦我从index.html中删除<body>标签,ng build就会将脚本标签放在生成的index.html顶部,导致运行时错误。有没有办法在构建期间自定义插入Angular脚本的位置? - Pete
3个回答

6

您应该能够做您想做的事情。

这是一个基于网络的聊天程序的index.html内容,我在一个作业项目中完成了它(后端更有趣...)。

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>crap chat</title>
        <base href="/">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="bootstrap.min.css" rel="stylesheet" />
    </head>
    <body class="m-a-1">
    <?php print("Hello World ".date("r",time())."<br />\n"); ?>
    <app></app>
<script type="text/javascript" src="inline.bundle.js"></script>
<script type="text/javascript" src="polyfills.bundle.js"></script>
<script type="text/javascript" src="styles.bundle.js"></script>
<script type="text/javascript" src="vendor.bundle.js"></script>
<script type="text/javascript" src="main.bundle.js"></script>
</body>
</html>

只要你保持相同的js文件引用和样式表,样式(在<body>标签上)等等,那么你就可以把它放进去,并在想要的位置添加<app></app>标记集。仅供娱乐,我在我的服务器上将该文件重命名为index.php,并添加了一个打印语句来打印加载页面的日期/时间,没有任何问题。

1
我喜欢你的想法,但问题是如果我运行 ng build --prod,所有源文件的文件名都会像 main.bc90171935f6ba7976ea.js 这样。由于随机字符串的存在,将正确的资源包含在我的 PHP 模板中将变得困难/不可能,除非每次进行 Angular 应用程序的生产构建时都更新 src,这似乎不是理想的情况。 - Pete
4
angular.json 中,您可以将 "outputHashing" 设置为 "none",这将删除后缀并使内容更加易于理解。 - user184994
@user184994 很好!我没有意识到这一点。谢谢你挽救了这个局面! - Pete

2
作为可能仍然遇到此问题的人(如我),我想分享我的解决方案:
由于我们目前正在从纯PHP页面转向Angular方法,因此需要在Angular构建过程的索引文件头中包含一些基本的php内容。因此,我添加了一个“postbuild”步骤,它将在构建步骤之后自动运行。
但是,此步骤运行一个node.js脚本,该脚本只需将我们需要的php include添加到dist文件夹中的index.php中。
const fs = require('fs');
const path = require('path');

const sourceDir = path.join('dist', 'path');
const phpTag = "<?php include_once './some.php' ?>\n";

const file = path.join(sourceDir, 'index.php');
fs.readFile(file, 'utf8', function (err, content) {
    if (err) throw err;

    if (!content.startsWith(phpTag)) {
        content = phpTag + content;

        fs.writeFile(file, content, 'utf8', function (err) {
            if (err) throw err;
        });
    }
});

以下是我package.json的条目:

"scripts": {
    "build": "ng build",
    "postbuild": "node ./addPHPTag.ts",

2
从angular6开始,使用angular元素应该是可行的。
您的代码将会是:
// main-template.php
<html>
  <head>
      <title>My Site-wide Header</title>
      <script src="site-wide-script.js"></script>
      <link href="site-wide-styles" rel="stylesheet">
      <?php if ($somevar == true) : ?>
          echo "Yes, it has to be PHP";
      <?php endif; ?>
  </head>
  <body>
      <header>
          <ul>
              <li><a href="/home">Home</a></li>
              <li><a href="/about">About</a></li>
              <li><a href="/contact">Contact</a></li>
          </ul>
      </header>
      <your-component-name></your-component-name>
  </body>

您可以在https://angular.io/guide/elements找到有关如何创建Angular元素的指南 - 原则上,它并不比创建组件更难


2
除非你打算展示如何去实现,否则这应该是一条注释。 - Patrick Q
我不同意。这个问题非常宽泛,答案也是如此。创建一个Angular元素的方法已经有很好的文档记录了,所以在答案中发布它只会制造混乱。 - Jakub Judas
无论你如何不同意,如果你认为问题过于宽泛无法给出恰当的答案,那么你应该投票或标记关闭它为“过于宽泛”。 - Patrick Q
如果问题简单,简单的答案通常是最好的。 - Jakub Judas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接