Search code examples
phpdestructuring

Destructuring assignment in php for objects / associative arrays


In CoffeeScript, Clojure, ES6 and many other languages we have destructuring of objects/maps/etc somewhat like this:

obj = {keyA: 'Hello from A', keyB: 'Hello from B'}
{keyA, keyB} = obj

I've found the list function in php which lets you destructure arrays like so:

$info = array('coffee', 'brown', 'caffeine');
list($drink, $color, $power) = $info;

Is there a way to destructure objects or associative arrays in PHP? If not in the core libs maybe someone wrote some smart helper function?


Solution

  • For PHP 7.0 and below that is beyond the functionality of list. The docs state:

    list only works on numerical arrays and assumes the numerical indices start at 0.

    One of the things that could suit your purpose would be the extract() function which imports variables from an array into the current symbol table. While with list you are able to define variable names explicitly, extract() does not give you this freedom.

    Extracting an associative array

    With extract you could do something like that:

    <?php
    
    $info = [ 'drink' => 'coffee', 'color' => 'brown', 'power' => 'caffeine' ];
    extract($info);
    
    var_dump($drink); // string(6) "coffee"
    var_dump($color); // string(5) "brown"
    var_dump($power); // string(8) "caffeine"
    

    Extracting an Object

    Extracting an object works almost the same. Since extract only takes an array as an argument we need to get the objects properties as an array. get_object_vars does that for you. It returns an associative array with all public properties as key and their values as value.

    <?php
    
    class User {
    
        public $name = 'Thomas';
    
    }
    
    $user = new User();
    extract( get_object_vars($user) );
    
    var_dump($name); // string(6) "Thomas"
    

    Pitfalls

    extract() is not the same as list since it does not allow you to explicitly define the variable names that get exported to the symbol table. The variable names correspond the array keys by default.

    • list is a language construct while extract() is a function
    • It might happen that you overwrite variables that you have defined beforehand unintentionally
    • Your array keys might be invalid as variable names

    With the $flags parameter that you can pass as second argument to extract() you can influence the behavior in case of colliding or invalid variables. But still it's important to know how extract() works and to use it with cauton.

    Edit: As of PHP 7.1 this is possible:

    http://php.net/manual/en/migration71.new-features.php#migration71.new-features.support-for-keys-in-list

    You can now specify keys in list(), or its new shorthand [] syntax. This enables destructuring of arrays with non-integer or non-sequential keys.

    https://php.net/manual/en/migration71.new-features.php#migration71.new-features.symmetric-array-destructuring

    The shorthand array syntax ([]) may now be used to destructure arrays for assignments (including within foreach), as an alternative to the existing list() syntax, which is still supported.

    For example this:

    $test_arr = ['a' => 1, 'b' => 2];
    list('a' => $a, 'b' => $b) = $test_arr;
    var_dump($a);
    var_dump($b);
    

    Will output the following as of 7.1.0

    int(1) 
    int(2)