Search code examples
phprequire-once

Why file is required however variable is still undefined


I try to understand OOP ways in PHP. And I think -not sure for this case- I have issues with variable scopes. Here are my questions:

  1. After running test.php; why I can't access $nums variable in foo.php?
  2. What is the solution?
  3. If the solution requires to use global keyword somewhere, what is my other option without global keyword. (I don't want to use it)

foo.php

<?php
$nums = array(4, 7);
$s = $nums[0]+$nums[1];
echo 'string in foo.php is written here.<br> SUM is '.$s.'<br>';
print_r($nums);
echo '<br><br>';

test.php

<?php

class Loader {

    private static $load_name;

    public static function loadFile($load_file) {

        self::$load_name = $load_file;

        $file_to_load = self::$load_name;

        require_once($file_to_load);

        unset($file_to_load);
    }
}

class TestClass {

    public function getnums() 
    {
        $a = Loader::loadFile("foo.php");

        echo 'var_dump($a) :<br><pre>'; var_dump($a); echo '</pre>'; 

        echo 'var_dump($nums) :<br><pre>'; var_dump($nums);     echo '</pre>';
    }
}

$n = new TestClass();
$g = $n->getnums();

echo 'var_dump($g) :<br><pre>'; var_dump($g); echo '</pre>';

test.php returns

string in foo.php is written here.
SUM is 11
Array ( [0] => 4 [1] => 7 ) 

var_dump($a) :
NULL

var_dump($nums) :


Notice:  Undefined variable: nums in ...UniServerZ\www\test.php on line 27

NULL

var_dump($g) :
NULL

Solution

  • You're 100% correct - the issue is with the scopes.

    $nums will only be defined in the scope of the file and the including scope; in this instances thats the Loader::loadFile() function.

    If you want to retrieve the variable out of the file and make it available in your getnums() method, you'll need a way for it to be returned from loadFile. I believe you're assuming this happens automatically with the variable $a.

    To make this work, try:

    public static function loadFile($filename) {
      // ... existing code
      return $nums;
    }
    

    And then $a will be $nums.

    To make this more verbose and reusable:

    function loadFile($filename, $variableName) {
      // existing code here.
      return $$variableName; // variable variables are a dangerous thing to debug.
    }
    

    Therefore your getnums() function will look like:

    $a = Loader::loadFile("foo.php", "nums"); // "nums" being the variable name.