The very useful variadic argument
source link: https://www.exakat.io/en/the-very-useful-variadic-argument/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
The very useful variadic argument
Variadic argument is the last argument of a PHP function : it is easy to recognize, with its ellipsis, both at definition and call time. This simple option is actually full of magic powers : it collects all incoming arguments into one parameter.
Now, that is the base description of the variadic. There are several interesting derived features and behaviors, worth noting.
Variadic is always optional
There can only be one variadic argument, and it is always optional. Meaning, there is absolute need to provide it, as it will be always transmitted to the function as an array. So, when the argument is skipped, it is transmitted as an empty array.
<?php function foo(... $b ) { print_r( $b ); } foo(); // $b === []; foo(1); // $b === [1]; foo(1, 2); // $b === [1, 2]; ?> |
Following this, native functions, such as array_unshift(), actually work with only one argument. This is a useless case : there is no need to call array_unshift() to prepend no value, and get back the original array. But it may be useful when that function is called dynamically, of course.
<?php $a = [1, 2, 3]; array_unshift ( $a ); print_r( $a ); // same old $a $b = []; // or, any dynamical build array_unshift ( $a , ... $b ); ?> |
It also means that a variadic parameter cannot have a default value.
Variadic may be referenced
Variadic arguments accept the &
option, so it is possible to send several variables, by reference, in the method.
<?php function array_sort(&... $a ) { foreach ( $a as & $b ) { sort( $b ); } unset( $b ); } $a = [2, 1]; $b = [3, 1, 4]; array_sort( $a , $b ); print_r( $a ); print_r( $b ); ?> |
Make sure that the block of the method handles the references correctly : the &
of the $b
variable inside array_sort() is crucial here. Otherwise, the arrays will only be sorted inside the function, due to loss of reference.
Variadic may be typed
Parameters may be variadic and typed at the same time. This is a good way to check the content of an array. Use the ellipsis at call time, to spread the arguments, and again in the parameter, to make them again into an array.
<?php function foo(A ... $a ) { /* bla bla bla */ } $a = [ new A, new B, new C]; foo(... $a ); //Argument #3 must be of type A, C given class A {} class B extends A {} class C {} ?> |
Variadic is always an array
This paragraph is a paradox, compared to the previous. The typehints that were introduced in the previous paragraph is for the elements of the array, not for the parameter itself. Do not confuse one for the other.
<?php function foo(A ... $a ) { print get_type( $a ); // array print get_type( $a [0]); // A (if any) } ?> |
Variadic may not be last, finally
Well, variadic parameters are always the last. But if you are PHP itself, or use func_get_args(), then you can overcome this limitation. A (very) few native functions such as array_intersect_ukey(), array_diff_uassoc(), and array_intersect_uassoc(). They use an anonymous function to process the intersection of two or more arrays. They also have a peculiar signature : the anonymous function is the last argument, and the variadic is just before, as the early penultimate.
Thanks to Ricardo Boss, who rose the question on the PHP community on Twitter. The problem was related to the following error message : ‘Cannot use positional argument after argument unpacking’.
<?php $arrays = [ $array1 , $array2 ]; print_r( array_intersect_uassoc (... $arrays , "strcasecmp" )); ?> |
Using named parameters lead to the strange array_intersect_uassoc() does not accept unknown named parameters
error message, so, in the end, good old calluserfunc_array is a solution, albeit a good one.
<?php // From the PHP manual $array1 = array ( "a" => "green" , "b" => "brown" , "c" => "blue" , "red" ); $array2 = array ( "a" => "GREEN" , "B" => "brown" , "yellow" , "red" ); $arrays = [ $array1 , $array2 ]; print_r(call_user_func_array( 'array_intersect_uassoc' , [ $array1 , $array2 , "strcasecmp" ])); ?> |
When building a method with such a signature, where the arbitrary number of elements is not the last one, it is not possible to use the variadic PHP operator. The only solution is the func_get_args()function, which will grab all the arguments, at call time, in an array. It is old technology, and all the modern options (default values, typehints, names) will not be available.
Variable list of arguments are cool
Variadic is a surprisingly useful operator, both for collecting arguments and processing them. Coupled with arrays, they are a very convenient way to pass a load of values to a method, and receive them in a convenient packaging.
They are also a trick of the trade : it is often efficient to process multiple similar arguments with a loop, inside the method, rather than make multiple successive calls to that method. Variadic provides a transparent interface for that.
<?php function foo(... $list ) { foreach ( $list as $l ) { // do something with $l } } // called empty foo(); // called once foo(1); // called with multiple arguments foo(1, 2, 3); // dynamically called foo(... $array ); ?> |
Until next time, happy PHP coding!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK