javascriptphp

Fill() assign excess array variables to single variable


I've been translating a JS package into PHP compatibility for use in my current project. One commonly used JS function is the ability to destructure a function return into variables, as shown below

const { _args, _field, ..._query } = ensureObject(query);

As far as I understand it, an assignment such as this is (somewhat) possible in PHP by using the list() function, which allows assignment from an array into individual variables.

The problem is, in the JS example above, excess variables are grouped into the variable _query. Attempting to use the spread operator in list() is not allowed, and I can't find any information online regarding whether or not providing fewer variables in the list() declaration will group excess arguments into the trailing variable or not, hence this question.

This kind of variable declaration is fairly common in this JS package, which is why ensuring it's translated directly is fairly important.

Obviously there's other, less elegant ways to achieve this, such as removing the _args and _field assignments directly and then using the leftover array as _query, but since I'd prefer to keep this package as lightweight as possible, I wanted to know if there's an elegant way to do this in PHP8.


Solution

  • I do not know what ensureObject() does, but assuming it returns an array with at least 2 items, you could write like this example.

    This is ugly, but I am afraid there is no pretty native way using the ... operator. It can only decompose in function argument and in array itself up to PHP 8.0.3 as far as I know.

    function ensureObject($query):array {
        return $query;
    }
    
    $array = ensureObject([['--verbose', '--force'], 'title', 3, 4, 5]);
    list($_args, $_field, $_query) = [$array[0], $array[1], array_slice($array, 2)];
    

    Then these variables are set.

    $_args  = ['--verbose', '--force'];
    $_field = 'title';
    $_query = [3,4,5];
    

    Update:

    PHP now supports variable-length argument lists. You could do following to get the same result as above:

    function ensureObject($_args, $_field, ...$_query): array {
        return [$_args, $_field, $_query];
    }
    
    [$_args, $_field, $_query] = ensureObject(['--verbose', '--force'], 'title', 3, 4, 5);
    
    var_dump($_args, $_field, $_query);