How to Properly Include an Angular App inside a PHP application

Viewed 4043

Let's say I'm starting with a PHP application. On one of the pages on the site, there's a complex interactive app that I want to use Angular for. The problem is, I still want the header and footer of that page to match the rest of the site. I would love to be able to do something like this:

// 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>

It somewhat works for me to just PHP include the Angular HTML file there, but that's pretty janky because, of course, the Angular index.html file already includes a html, body, etc. tags. Of course I could DOM parse the Angular file and fix all that before including...but I'd prefer a better solution.

In my searching I can't seem to find any officially recommended way of doing this. Actually I can't seem to find any examples of anyone doing this at all–all my searches just turn up people doing something similar with AngularJS, not Angular. Is there any decent way to accomplish this with Angular?

3 Answers

You should be able to do what you want to do.

Here's the content of a index.html for a web based chat program I did as a HW project (the back end was much more fun...).

<!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>

As long as you keep the same js file references and style sheets, styles (on <body> tag) etc. then you should be able to drop that in and toss in the <app></app> tag set just where you want it.

Just for giggles I renamed the file to index.php on my server, added a print statement to print date/time page was loaded, no issues.

As of angular6, this should be possible using angular elements.

Your code would then simply be

// 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>

You can find a guide on how to create angular elements at https://angular.io/guide/elements - in principle, it is no harder than just creating a component

As someone might still come across this issue (like me), I want to share my solution:

As we are currently changing from a pure PHP page to an Angular approach, we need to include some basic php-stuff in the head of the index file of the Angular build process. Therefore, I added a postbuild-Step, which will automatically run after the build-step.

However, this step is running a node.js script which simply adds the php include we need in the index.php of the dist-Folder

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;
        });
    }
});

and these are the entries of my package.json:

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