Blender Pony Blender Pony - 3 months ago 6
PHP Question

require_once inside of a function

for self exercise and training I am building my own CMS from the ground up. Part of this exercise is to enable custom html, css templates

Security wise, is it better if I open the PHP template file with require_once inside of a function to protect outside variables like the Database Handler and such?

Or should I make this entirely diffrent than this?

Answer

It'd be utterly useless to require_once() an external file that defines variables within a function:

library.php:

<?php

if (!isset($counter)) {
   $counter = 0;
}

$counter++; // increments every time this file is included
echo "Counter is $counter\n";

maincode.php:

<?php

function foo() {
        require_once('library.php');
        echo "foo() has counter = $counter\n";
}

function bar() {
        require_once('library.php');
        echo "bar() has counter = $counter\n";
}

foo();
bar();

Results:

$ php maincode.php
Counter is 1
foo() has counter = 1
PHP Notice:  Undefined variable: counter in maincode.php on line 10
bar() has counter =

Included/required files inherit the scope of the context they're executed in. When you do that include in a function, you get the function's context, and the variables become "local" variables within the function, and are destroyed when the function call returns.

And if you do the _once() variant, your file literally is included only ONCE for the entire lifetime of the script, leading to the warning above. The require_once() call in bar() didn't do anything, because the file had already been included previously within the foo() call. So it's not included, $counter never gets defined within bar(), and now nothing works.

You can, of course, simply use the plain include() and require() variants. But then the same problems hold - any variables defined within the included file are destroyed when the function exits. That means that things like database connections will also be destroyed and cleaned up - making it impossible to hold a transaction open across function calls.

Comments