1

If I do something like this (it's just a dummy example, but it will be useful to explain the problem):

variables.php:

<?php
$foo = 'foo';
$bar = 'bar';
?>

SomeClass.php:

<?php
class SomeClass {

    public static function do_something() {
        // XXX Sometimes this works well; but sometimes,
        //     imported variables are null or empty for some
        //     reason within this method's scope
        require_once( dirname(__FILE__) . '/variables.php' );

        echo '<p>foo = '.$foo.'</p>';
        echo '<p>bar = '.$bar.'</p>';
    }
}
?>

Both files are within the same folder; although this class is actually required in scripts that are in other folders.

Most of the time it just prints as expected: foo = foo and bar = bar; but when this class is required by some script that does some heavy operations (filling lots of variables in arrays among other stuff, like calculations), it behaves like the imported variables didn't exist at all (printing foo = and bar =).

Looking at apache's error.log, the require_once doesn't throw any error at all; but it prints something like:

 PHP Notice:  Undefined variable: foo in /path/to/class_and_variables/SomeClass.php at line 10
 PHP Notice:  Undefined variable: bar in /path/to/class_and_variables/SomeClass.php at line 11

Normally, it works as expected and the variables are correctly imported within do_something's scope; but with some specific scripts, it doesn't.

It's like (I guess) PHP ran out of memory and destroyed the imported variables silently? I don't know why PHP's require_once behaves so strangely sometimes...

SebasSBM
  • 860
  • 2
  • 8
  • 32
  • Can you give an example when it fails – executable Oct 24 '19 at 09:03
  • I just didn't know that `require_once` would look at the current file first: I thought it just looks at the available directories in `PATH`. So using `dirname(__FILE__)` looked like a good idea – SebasSBM Oct 24 '19 at 09:03
  • 1
    @trey The path isn't relative to the "current file", it's relative to the *current working directory*, which isn't always the same as the "current file". Using `__FILE__` to make it absolute is a good idea. – deceze Oct 24 '19 at 09:06
  • @deceze: Actually, I used the wrong word: I didn't mean "would look at the current file", but rather "at the current **directory**". Sorry about that – SebasSBM Oct 24 '19 at 09:12
  • @trey If you put them both into some sub directory and execute a file outside that sub directory which does `require 'sub/a.php'`, then the *current working directory*, to which all requires are relative, will not be `sub`. – deceze Oct 24 '19 at 09:12
  • @trey Again: all `require`/`include` paths are relative to the *current working directory*. That's a thing. It's an important concept. The CWD isn't necessarily the directory your file is in. One way this may be is if your file is in a sub directory and the execution started elsewhere. – deceze Oct 24 '19 at 09:26
  • @trey Yeah, it'll work *under some circumstances*, and break *in other circumstances*. To write it robustly so it never breaks you need `__FILE__`. – deceze Oct 24 '19 at 09:29
  • @trey Dude…!? ‍♂️ When. The. CWD. !==. Your. File's. Directory. – deceze Oct 24 '19 at 09:34
  • @deceze can you link to somewhere with code examples etc.? I [tried](https://github.com/tr3ybake/phpthings) but calling class A which in turn requires class B in a different directory seemed to work (but I may be missing some shizzles) – treyBake Oct 24 '19 at 09:43
  • @trey https://stackoverflow.com/a/54897164/476, https://stackoverflow.com/q/2184810/476 – deceze Oct 24 '19 at 09:55
  • @deceze ahh and the penny drops ty – treyBake Oct 24 '19 at 10:01

1 Answers1

4

I think this will be only included on the first execution of the method and not on the second one. The second execution of the method will then have the variables not defined. You should use require instead.

Ulrich Thomas Gabor
  • 6,584
  • 4
  • 27
  • 41
  • 2
    In other words, this will fail if that file has already been included anywhere else previously. – deceze Oct 24 '19 at 09:07
  • Thank you very much. Although knowing the difference between `require_once` and `require`, I still fail understanding `require_once`'s behaviour sometimes (now I am ashamed of myself)... – SebasSBM Oct 24 '19 at 09:09
  • You should not be ashamed, you should see required_once as a boolean which if the file has already been loaded once , the rest of the requests it will return FALSE because it already has been used "once". – izk Oct 24 '19 at 09:11