Add array value after echoed

227 views Asked by At

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.

7

There are 7 answers

4
Nick On

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>
0
Coopero On

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
1
Sanusi hassan On

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
Robbie On

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();
2
Mohammed Jhosawa On

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 )
2
ash.dev On

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');
0
José Carlos PHP On

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';