Search code examples
phpclassscopephp-include

Does scope change at all when including class files in a class method in PHP?


I feel silly asking but can I check with the experts about the behaviour of including inside a class method.

When I use require_once to include class definition files inside a class method are there any gotchas I need to be aware of. I am thinking of an autoloading method on a factory class but really any time the a method does include or require.

My expectation is that it should be exactly the same as if I had simply included them at the start in, say, an include file. Am I right? I only ask as when you include a file in a class method it inherits the method scope.


Solution

  • One thing to watch out for is scoping of global variables. By example:

    File: a.php

    <?php
    $foo = 'bar';
    

    File: b.php

    <?php
    require_once 'a.php';
    echo $foo;
    

    File: c.php

    <?php
    load_foo();
    show_foo();
    
    function load_foo() {
      require_once 'a.php';
    }
    function show_foo() {
      require_once 'b.php';
    }
    

    Now if you run b.php directly (e.g. php b.php) you will get the proper output:

    bar
    

    However, if you run c.php you get this:

    PHP Notice:  Undefined variable: foo in C:\temp\b.php on line 3
    PHP Stack trace:
    PHP   1. {main}() C:\temp\c.php:0
    PHP   2. show_foo() C:\temp\c.php:3
    PHP   3. require_once() C:\temp\c.php:9
    

    The reason for the error is that inside c.php we load a.php within the function load_foo(). This causes the variable $foo to be scoped as a local variable for function load_foo() whereas otherwise it would be a global variable. Then when show_foo() is called it loads b.php, which skips the require_once (since we already loaded a.php) and then tries to print $foo. But it can't, because $foo isn't defined anymore. It went out of scope when we load_foo() exited.

    So, bringing it back to your original question - if you use autoload and the autoload happens in a function/method context, global variables are going to be scoped locally as in the example above. If you absolutely need to use global variables, make sure you use the global keyword before you define them (that would be global $foo as the first line of a.php above) and before you use them (again, global $foo after the require_once in b.php).