Search code examples
phprequire

why do I lose access to php variables when I render a new page


I have a render function that looks like:

function render($template, $values = array()){

   // if template exists, render it
   if (file_exists("../views/$template")){

      // extract variables into local scope
      extract($values);

      // render header_form
      require("../views/header_form.php");

      // render template
      require("../views/$template");

      // render footer
      require("../views/footer_form.php");

   }else{

      // else err
      trigger_error("Invalid template: $template", E_USER_ERROR);

   }
}

Suppose I have a script crew.php that looks like this:

<?php

    require('../includes/config.php');
        $values=[];           

        $today = new DateTime();

        render('crew_form.php',$values);

?>

Why don't I have access to $today in crew_form.php? For instance, if crew_form.php was:

<?php

    echo $today;
?>

When you use require doesn't that just add the script to the existing code? Is it because of local scope of the function render()?


Solution

  • You don't have access to $today because you're out of scope. The variable is defined outside a function, and is not available inside it -- and render() is a function.

    You can obviate the problem with the use keyword, or by abusing the global directive, but a better way to avoid polluting the scope would be passing the variables explicitly and reading them with extract().

    Which is exactly what your code was attempting doing, using $values. But you need to put $today inside $values and pass it to render():

    $values['today'] = $today;
    

    Now, a variable called $today will be available in crew-form.php, but it will not be the same $today even if it will start as a copy of the same value. You can see it better like this:

    $values['today2'] = $today;
    

    Inside crew-form.php, $today2 will exist, $today will not, because the latter is "out of scope".

    Changes to the extracted values will be lost upon exit from render (you can use EXTR_REFS but that adds complications).