-1

I'm creating a web app where I want to include JavaScript files with all file sources in an array, but I can't do that.

Header.php

<head>
<?php
  $import_scripts = array(
    'file01.js',
    'file02.js'
  );

  foreach ($import_scripts as $script) {
    echo '<script src="' . $script . '"></script>';
  }
?>
</head>
<body>

Index.php

<?php
  include('header.php');
  array_push($import_scripts,'file03.js')
?>

But this only includes file01.js and file02.js, JavaScript files.

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • Very related: [Add extra scripts to a page with header.php include file?](https://stackoverflow.com/q/27254535/2943403) and [PHP include header and footer with different plugins on some pages](https://stackoverflow.com/q/47157563/2943403) and [How to include CSS in header with PHP?](https://stackoverflow.com/q/22422635/2943403) and [How to add content to PHP include files?](https://stackoverflow.com/q/20589482/2943403) – mickmackusa Nov 15 '22 at 23:15

7 Answers7

4

Your issue is that you've already echo'ed the scripts in headers.php by the time you push the new value into the array in index.php. So you need to add to extra scripts before you include headers.php. Here's one way to do it (using the null coalescing operator to prevent errors when $extra_scripts is not set):

header.php

<?php
  $import_scripts = array_merge(array(
    'file01.js',
    'file02.js'
  ), $extra_scripts ?? []);

?>
<!DOCTYPE html>
  <html>
    <head>
      <!-- Scripts Section -->
<?php
  foreach ($import_scripts as $script) {
    echo '<script src="' . $script . '"></script>' . PHP_EOL;
  }
?><title>Demo</title>
    </head>
    <body>
      <p>Blog</p>

index.php

<?php
  $extra_scripts = ['file03.js'];
  include 'header.php';
?>

Output (demo on 3v4l.org)

<!DOCTYPE html>
  <html>
    <head>
      <!-- Scripts Section -->
<script src="file01.js"></script>
<script src="file02.js"></script>
<script src="file03.js"></script>
<title>Demo</title>
    </head>
    <body>
      <p>Blog</p>
Dharman
  • 30,962
  • 25
  • 85
  • 135
Nick
  • 138,499
  • 22
  • 57
  • 95
  • If I'll use it, my scripts will be imported at the body not the head. You can do by any function, I'm not telling you to do that only with `array_push()`. but I want the scripts to the head not the body –  Sep 28 '22 at 03:45
  • @CodemasterUnited gotcha, that wasn't clear from the question. Please see my edit. – Nick Sep 28 '22 at 03:51
  • I need to include header first and then import script –  Sep 28 '22 at 04:04
  • @CodemasterUnited this code will include the script from index.php *after* the scripts from header.php. Isn't that what you want? – Nick Sep 28 '22 at 04:26
1

header.php

<?php
function scripts()
{
    return [
        'file01.js',
        'file02.js'
    ];
}
function render($scripts)
{
    foreach ($scripts as $script) {
        echo '<script src="' . $script . '"></script>';
    }
}
?>

<head>

index.php:

<?php
include 'header.php';
$extra_scripts = scripts();
$extra_scripts[] = 'script3.js';
render($extra_scripts);
?>
</head>

<body>

0

PHP is processed top down so it will currently be adding file03.js to the array after the foreach has been run.

This means you have two options:

  1. Run the scripts after the header (Not reccomended)
  2. Like Nick suggested, in index.php, specify additional scripts before the header is called
Coopero
  • 296
  • 2
  • 10
0

Other answers have answered why (you output content before adding the item to the array).

The best solution is to do all your processing before your output. Also helps with error trapping, error reporting, debugging, access control, redirect control, handling posts... as well as changes like this.

Solution 1: Use a template engine. This may be more complex than you need, and/or add bloat. I use Twig, have used Smarty (but their site is now filled with Casino ads, so that's a concern), or others built into frameworks. Google "PHP Template engine" for examples.

Solution 2: Create yourself a quick class that does the output. Here's a rough, (untested - you will need to debug it and expand it) example.

class Page
{
    private string $title = 'PageTitle';
    private array $importScripts = [];
    private string $bodyContent = '';
    public setTitle(string $title): void
    {
        $this->title = $title;
    }
    public addImportScript(string $importScript): void
    {
        $this->importScripts[] = $importScript;
    }
    public addContent(string $htmlSafeBodyContent): void
    {
        $this->bodyContent .= $bodyContent;
    }
    public out(): void
    {
         echo '<!DOCTYPE html>
<html>
   <head>
      <!-- Scripts Section -->
              ';
         foreach ($this->importScripts as $script) {
             echo '<script src="' . htmlspecialchars($script) . '"></script>' . PHP_EOL;
         }
         echo '
      <!-- End Scripts Section -->
      <title>' . htmlspecialchars($this->title) . '</title>
   </head>
   <body> . $this->bodyContent . '
   </body>
</html>';

         exit();
    }
}

// Usage
$page = new page();
$page->setTitle('My Page Title');  // Optional
$page->addImportScript('script1');
$page->addImportScript('script2');
$page->addContent('<h1>Welcome</h1>');

// Do your processing here
$page->addContent('<div>Here are the results</div>');
$page->addImportScript('script3');

// Output
$page->out();
Robbie
  • 17,605
  • 4
  • 35
  • 72
0

I'd create a new php file, say functions.php and add the following code into it.

<?php
// script common for all pages.
$pageScripts = [
    'common_1.js',
    'common_2.js',
];

function addScripts(array $scripts = []) {
    global $pageScripts;

    if (!empty ($scripts)) { // if there are new scripts to be added, add it to the array.
        $pageScripts = array_merge($pageScripts, $scripts);
    }
    return;
}

function jsScripts() {
    global $pageScripts;
    $scriptPath = './scripts/'; // assume all scripts are saved in the `scripts` directory. 

    foreach ($pageScripts as $script) {
        // to make sure correct path is used
        if (stripos($script, $scriptPath) !== 0) {
            $script = $scriptPath . ltrim($script, '/');
        }
        echo '<script src="' . $script .'" type="text/javascript">' . PHP_EOL;
    }
    return;
}

Then change your header.php as

<?php
include_once './functions.php';

// REST of your `header.php`

// insert your script files where you needed.
jsScripts();

// REST of your `header.php`

Now, you can use this in different pages like

E.g. page_1.php

<?php
include_once './functions.php';

addScripts([
    'page_1_custom.js', 
    'page_1_custom_2.js',
]);

// include the header
include_once('./header.php');

page_2.php

<?php
include_once './functions.php';

addScripts([
    './scripts/page_2_custom.js',
    './scripts/page_2_custom_2.js',
]);

// include the header
include_once('./header.php');
ash.dev
  • 21
  • 3
  • You don't need to call `!empty ($scripts)` when `$scripts` is guaranteed to be declared. Just do a truthy check without a function call. Nick's answer already recommended `array_merge()`. I don't know that your answer brings anything valuable to this page. – mickmackusa Nov 20 '22 at 23:25
  • @mickmackusa Thanks for your feedback. I just wanted to created a more general setup (like a template) – ash.dev Nov 22 '22 at 19:46
0

You are adding 'file03.js' to $import_scripts after including 'header.php', so echoing scripts it have been done yet. That's why 'file03.js' is not invoked.

So, you need to add 'file03.js' to $import_scripts before echoing scripts, this means before include 'header.php'.

A nice way is to move $import_scripts definition to index.php, and add 'file03.js' before including 'header.php'.

But it seems that you want to invoke certain JS scripts always, and add some more in some pages. In this case, a good idea is to define $import_scripts in a PHP file we can call init.php.

This solution will be as shown:

header.php

<head>
<?php
foreach ($import_scripts as $script) {
    echo '<script src="' . $script . '"></script>';
}
?>
</head>
<body>

init.php

<?php
$import_scripts = array(
    'file01.js',
    'file02.js'
);

index.php

<?php
require 'init.php';

array_push($import_scripts,'file03.js');

include 'header.php';
José Carlos PHP
  • 1,417
  • 1
  • 13
  • 20
-1

header.php

<?php

echo "<head>";

$importScripts = ['file01.js','file02.js'];

foreach ($importScripts as $script) {
    echo '<script src="' . $script . '"></script>';
}

echo "</head>";
echo "<body>";

index.php

<?php

include 'header.php';

array_push($importScripts, 'file03.js');
print_r($importScripts);

Output

Array ( [0] => file01.js [1] => file02.js [2] => file03.js )
  • Of course, this answer makes one of the two mistakes presented in the question. You only push `file03` AFTER `header.php` is executed so that file is never printed in the header. – mickmackusa Nov 17 '22 at 21:41
  • @mickmackusa I got you. not only he want to push the `file03` also load in the HTML head – Mohammed Jhosawa Nov 18 '22 at 04:20