Search code examples
phpfunctionextractcopy-on-write

Does PHP's extract() function add variables to the symbol table using copy-on-write?


Sorry, Im sure this answer is somewhere on the internet (maybe even stackoverflow) but I have spent the last hour searching and cant seem to find the answer...

Does PHP's extract() function add variables to the symbol table using copy-on-write?

I know that PHP function calls all have a copy-on-write by default (unless you specify by reference), just curious about this as I am integrating a templating system so I grab a whole bunch of variables into a $data array, which can be quite large sometimes and am wondering if extracting them before including the template file is the best way to go about this.

thanks!

EDIT:

To clarify:

    $array = array('a' => array(1,2,3), 'b' => array(3,4,5), 'c' => array(6,7,8));
    extract($array);
    //is $a, $b, $c Copy-On-Write at this point? Would be a lot better performance as opposed to allocating 3 new array()'s

    //I would like to avoid having this change the original $array values so using EXTR_REFS is not a good solution for me here if I can avoid it and still keep performance!
    $a = array(3);

Solution

  • Both versions are possible (extract values and extract by reference) - and it's quite easy to showcase both:

    function value() {
        $array = array('a' => 1, 'b' => 2);
        extract($array);
        var_dump($a);
        var_dump($b);
        $a = 3;
        $b = 4;
        var_dump($a);
        var_dump($b);
        var_dump($array);
    }
    
    function reference() {
        $array = array('a' => 1, 'b' => 2);
        extract($array, EXTR_REFS);
        var_dump($a);
        var_dump($b);
        $a = 3;
        $b = 4;
        var_dump($a);
        var_dump($b);
        var_dump($array);
    } 
    
    value();
    /* 
    int(1)
    int(2)
    int(3)
    int(4)
    array(2) {
      ["a"]=>
      int(1)    // original array item is unchanged
      ["b"]=>
      int(2)    // original array item is unchanged
    }
    */
    
    reference();
    /*
    int(1)
    int(2)
    int(3)
    int(4)
    array(2) {
      ["a"]=>
      &int(3)    // original array item is changed because it's a reference to the extracted variable
      ["b"]=>
      &int(4)    // original array item is changed because it's a reference to the extracted variable
    }
    

    extract() allows for a second parameter which features EXTR_REFS as an option:

    Extracts variables as references. This effectively means that the values of the imported variables are still referencing the values of the var_array parameter. You can use this flag on its own or combine it with any other flag by OR'ing the extract_type.