Related
I have an array of arguments that are in order for a function.
The number of items in the array differ. I want to be able to pass in each item in the array individually to the functions (eg...func(arg1, arg2, arg3, arg4);). Opposed to just passing in the whole array.
Keep in mind, I do not know the length of the array, it differes depending on which function I am calling.
since PHP 5.6 you have the Variable-length argument lists so you can call your function like this:
$arr = array(1, 2, 5, "ten");
and you can send all the elements in the $arr to a function by calling it like this:
myFunc(...$arr);
If you mean you have a function that its argument is an array, you can use foreach to fetch all the array elements:
function my_func($arg_array)
{
foreach($arg_array as $key=>$value)
{
......
}
....
}
But if you mean you have a function that has unknown number of arguments you can use func_get_args function that returns an array containing arguments as an array.
function my_func()
{
foreach(func_get_args() as $key=>$value)
{
......
}
....
}
Use : call_user_func_array("functionName", $arrayofArgs);
<?php
function unknown($arg1,$arg2,$arg3){
echo "arg1 = $arg1 <br>";
echo "arg1 = $arg2 <br>";
echo "arg1 = $arg3 <br>";
}
$array = [
"arg1" => "Hi",
"arg2" => "Marhaba",
"arg3" => "Hola",
"arg4" => "foo"
];
call_user_func_array("unknown", $array);
?>
and you can call the function from class by passing the first param as array of ["className","methodName"]
php Docs :
http://php.net/manual/en/function.call-user-func-array.php
In PHP you have:
func_num_args()
func_get_args()
func_get_arg()
for that purpose.
EDIT
If you are fine using PHP 5.6 then you have splat operator. Quoting sample from docs (link):
<?php
function add($a, $b, $c) {
return $a + $b + $c;
}
$operators = [2, 3];
echo add(1, ...$operators);
While I am installing Magento 2 on my Server, I got an error. After investigating the code and found that there is are three dots (...), which is producing the error. I included the code I found below:
return new $type(...array_values($args));
What is this operator called, and what is its purpose?
This is literally called the ... operator in PHP, but is known as the splat operator from other languages. From a 2014 LornaJane blog post on the feature:
This feature allows you to capture a variable number of arguments to a function, combined with "normal" arguments passed in if you like. It's easiest to see with an example:
function concatenate($transform, ...$strings) {
$string = '';
foreach($strings as $piece) {
$string .= $piece;
}
return($transform($string));
}
echo concatenate("strtoupper", "I'd ", "like ", 4 + 2, " apples");
(This would print I'D LIKE 6 APPLES)
The parameters list in the function declaration has the ... operator in it, and it basically means " ... and everything else should go into $strings". You can pass 2 or more arguments into this function and the second and subsequent ones will be added to the $strings array, ready to be used.
There are TWO uses for the ellipsis (...) PHP token—think of them as packing an array and unpacking an array. Both purposes apply to function arguments.
Pack
When defining a function, if you need a dynamic number of variables provided to the function (i.e., you don't know how many arguments will be provided to that function when called in your code), prefix the ellipsis (...) token to a variable name—e.g., ...$numbers—to capture all (remaining) arguments provided to that function into an array assigned to the named variable—in this case $numbers—that is accessible inside the function block. The number of arguments captured by prefixing ellipsis (...) can be zero or more.
For example:
// function definition
function sum (...$numbers) { // use ellipsis token when defining function
$acc = 0;
foreach ($numbers as $nn) {
$acc += $nn;
}
return $acc;
}
// call the function
echo sum(1, 2, 3, 4); // provide any number of arguments
> 10
// and again...
echo sum(1, 2, 3, 4, 5);
> 15
// and again...
echo sum();
> 0
When packing is used in function instantiation, prefixing ellipsis (...) to a variable name captures all remaining arguments, i.e., you can still have any number—zero or more—of initial, fixed (positional) arguments:
function sum ($first, $second, ...$remaining_numbers) {
$acc = $first + $second;
foreach ($remaining_numbers as $nn) {
$acc += $nn;
}
return $acc;
}
// call the function
echo sum(1, 2); // provide at least two arguments
> 3
// and again...
echo sum(1, 2, 3, 4); // first two are assigned to fixed arguments, the rest get "packed"
> 10
...the prefixed ellipsis variable captures all the rest. For this reason it must be the final function argument.
Unpack
Alternatively, when calling a function, if the arguments you provide to that function are previously combined into an array use a ellipsis (...) token prefixed variable "inline" to convert that array variable into individual arguments provided to the function. When any number of function arguments are replaced with an ellipsis prefixed variable, each array element is assigned to the respective function argument variable named in the function definition.
For example:
function add ($aa, $bb, $cc) {
return $aa + $bb + $cc;
}
$arr = [1, 2, 3];
echo add(...$arr); // use ellipsis token when calling function
> 6
$first = 1;
$arr = [2, 3];
echo add($first, ...$arr); // used with positional arguments
> 6
$first = 1;
$arr = [2, 3, 4, 5]; // array can be "oversized"
echo add($first, ...$arr); // remaining elements are ignored
> 6
Unpacking is particularly useful when using array functions to manipulate arrays or variables.
For example, unpacking the result of array_slice:
function echoTwo ($one, $two) {
echo "$one\n$two";
}
$steaks = array('ribeye', 'kc strip', 't-bone', 'sirloin', 'chuck');
// array_slice returns an array, but ellipsis unpacks it into function arguments
echoTwo(...array_slice($steaks, -2)); // return last two elements in array
> sirloin
> chuck
Every answer refers to the same blog post, besides them, here is the official documentation about variable-length argument lists:
http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list
In PHP 5.6 and later, argument lists may include the ... token to denote that the function accepts a variable number of arguments. The arguments will be passed into the given variable as an array
It seems "splat" operator is not an official name, still it's cute!
In PHP 7.4 the ellipsis is also the Spread operator:
$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
Source: https://wiki.php.net/rfc/spread_operator_for_array
Meaning is that it decomposes an associative array to a list. So you do not need to type N parameters to call a method, just one. If method allows a decomposed parameter and if parameters are of the same type.
For me, the most important thing about splat operator is that it can help to typehint array parameters:
$items = [
new Item(),
new Item()
];
$collection = new ItemCollection();
$collection->add(...$items); // !
// what works as well:
// $collection->add(new Item());
// $collection->add(new Item(), new Item(), new Item()); // :(
class Item {};
class ItemCollection {
/**
* #var Item[]
*/
protected $items = [];
public function add(Item ...$items)
{
foreach ($items as &$item) {
$this->items[] = $item;
}
}
}
it saves some effort on type control, especially while working with huge collections or very object-oriented.
Important to notice is that ...$array do decompose an array despite the type of its items, so you can go the ugly way also:
function test(string $a, int $i) {
echo sprintf('%s way as well', $a);
if ($i === 1) {
echo('!');
}
}
$params = [
(string) 'Ugly',
(int) 1
];
test(...$params);
// Output:
// Ugly way as well!
But please don't.
PHP 8 update - named arguments
Since PHP 8 you can now decompose associative arrays, it is, arrays that have keys for them values. If you use it in function that has arguments named the same, PHP will transfer values to proper variables:
$arr = [
'pi' => 3.14,
'r' => 4,
];
function circ($r, $pi) {
return 2*$pi*$r;
}
// so that call
circ(...$arr);
// will be effectively a call of
circ(pi: 3.14, r: 4);
and you can slightly less bother about order of parameters.
PHP 8.1 update - new syntax for creating callable
Despite usage with arrays, ... earned a whole new, very useful functionality that help creating callable from any context:
$f = strtoupper(...); // creating a callable
echo $f('fo');
class test {
public function func($a) {
echo $a . PHP_EOL;
}
}
$f = (new test)
->func(...); // creating a callable
$f('x');
In PHP 8.1, this syntax "(...)" is used as a new way to create callables.
Before PHP 8.1:
$callable = [$this, 'myMethod'];
After PHP 8.1:
$callable = $this->myMethod(...);
Source: https://wiki.php.net/rfc/first_class_callable_syntax
To use this feature, just warn PHP that it needs to unpack the array into variables using the ... operator. See here for more details, a simple example could look like this:
$email[] = "Hi there";
$email[] = "Thanks for registering, hope you like it";
mail("someone#example.com", ...$email);
This is the so called "splat" operator. Basically that thing translates to "any number of arguments"; introduced with PHP 5.6
See here for further details.
It seems no one has mentioned it, so here to stay[It will also help Google (& Other SEs) guide devs who asking for Rest Parameters in PHP]:
As indicated here its called Rest Parameters on JS & I prefer this meaningful naming over that splat thing!
In PHP, The functionality provided by ...args is called Variadic functions which's introduced on PHP5.6. Same functionality was used to be implemented using func_get_args().
In order to use it properly, you should use rest parameters syntax, anywhere it helps reducing boilerplate code.
I need to call a function as such:
function something($argument1, $argument2, $data)
where $data can be any amount of variables comma separated:
1,2,3,4
so for instance I would call:
function something ('blue', 'green', 1,2,3)
or
function something ('red', 'black', 1,2,3,4,5,6,7,8,9)
I have looked into the ellipsis keyword (...) but I cannot see how I can implement this with my 2 static arguments ($argument1 and $argument2).
My intuition would be to put the comma separated into an array before calling the function and sending the array to the function?
Thanks!
i don't know exactly what you are trying to do but, if you want a function with lots of arguments and since you know that the first 2 argument is fixed, you can use php func_get_args() to get the arguments passed to the function.
You can include required arguments before using the splat operator. All arguments captured by the splat operator will be available in an array. For example,
function splat_example($arg_1, $arg_2, ...$data_list) {
echo $arg_1 . "\r\n";
echo $arg_2 . "\r\n";
foreach ($data_list as $data) {
echo $data . "\r\n";
}
}
So the following,
splat_example('red', 'blue', 1, 2, 3, 4);
would result in,
red
blue
1
2
3
4
See it working here http://sandbox.onlinephpfunctions.com/code/36d991aeb4321faf8400d0f6fb017efc50ebe567
you can pass third parameter as a comma separated string.
and then you can convert into array using explode with comma.
function something ('blue', 'green', '1,2,3'){
}
base on my understanding, this how list() work.
list($A1,$A2,$A3) = array($B1,B2,B3);
So with the help of list() we can assign value out from array accordingly.
here is my question... how to generate a dynamic list()?
1). base on database return result, I'm not sure how many of it but I assign it all into array
2). so we can use count(array) to know how many of it.
3). so then HOW CAN I GENERATE/PREPARE a list for it?
Example: client A, have 3 kids, name Apple, Boy, Cat
so I use list($kid1, $kid2, $kid3) for it.
but when client B, have more then 3 kids, I only get first 3
or if client C, have only 1 kids, then error encounter.
I know if base on the situation above, there is many way to solve it without using list()
but I wish to know or find out the solution with using list().
How to generate dynamic list() base on count of array()
thanks guys/gals
If you have a variable number of elements, use arrays for them! It does not make sense to extract them into individual variables if you do not know how many variables you'll be dealing with. Say you did extract those values into variables $kid1 through $kidN, what is the code following this going to do? You have no idea how many variables there are in the scope now, and you have no practical method of finding out or iterating them next to testing whether $kid1 through $kidN are isset or not. That's insane use of variables. Just use arrays.
Having said that, variable variables:
$i = 1;
foreach ($array as $value) {
$varname = 'kid' . $i++;
$$varname = $value;
}
You can create a lambda expression with create_function() for this. The list() will be only accessible within the expression.
This creates variables $A1, $A2, .... $AN for each element in your array:
$list = array("a", "b", "c", "d");
extract(array_combine(array_map(function($i) {
return "A" . $i;
}, range(1, count($list))), $list));
echo implode(" ", array($A1, $A2, $A3, $A4)), PHP_EOL;
You can modify the name of the variables in the array_map callback. I hope I'll never see code like that in production ;)
This is not what PHP's list is meant for. From the official PHP docs
list is not really a function, but a language construct.
list() is used to assign a list of variables in one operation.
In other words, the compiler does not actually invoke a function but directly compiles your code into allocations for variables and assignment.
You can specifically skip to a given element, by setting commas as follows:
list($var1, , $var2) = Array($B1, B2, B3);
echo "$var1 is before $var2 \n";
or take the third element
list( , , $var3) = Array($B1, B2, B3);
(I am assuming B2, B3 are constants? Or are you missing a $?)
Specifically using list, you can use PHP's variable variables to create variables from an arbitrary one-dimensional array as follows:
$arr = array("arrindex0" => "apple", "banana", "pear");
reset($arr);
while (list($key, $val) = each($arr)) {
$key = is_numeric($key) ? "someprefix_" . $key : $key;
echo "key sdf: $key <br />\n";
$$key = $val;
}
var_dump($arrindex0, $someprefix_0, $someprefix_1);
Result
string 'apple' (length=5)
string 'banana' (length=6)
string 'pear' (length=4)
so suppose I have a function:
function j($a, $b){
return $a + $b;
}
and then I put the intended arguments of the function into a string:
$str = '1,3';
is there a way to make the function treat the single string argument as if it were the arguments that the programmer inserted into the function....so when you do
j($str),
instead of having the function treat the $str as a single string argument, it fetches the content of the string and treats it as if the programmer wrote j(1,3) instead of j($str)
also this is a rather simple example, but I'd like it to work for even more complicated argument strings involving arrays, multidimensional arrays, associative arrays, array within arrays, as well as string arguments that have commas in it (so just exploding by comma is not really feasible)
also I'd rather not use eval() in the solution
EDIT
Also I'm trying to get this to work on any function not just mine (and not just this specific function which is just a worthless example function) so preferably the operation is to be done outside of the function
call_user_func_array('j', explode(',', $str));
http://www.php.net/call_user_func_array
I have no idea how you want to make this work for "more complex argument strings including arrays of arrays", since it's hard to express those as strings. If you can format whatever string you have into an array though, for example using JSON strings and json_decode, call_user_func_array is your friend.
This should work for a single, comma-separated string:
function j($str){
list($a, $b) = explode(',', $str);
return $a + $b;
}
What do you want to sum in a multi-dimensional array? All of the values?
If yes: You only have to check the type of your argument (e.g. using is_array()) and then iterate through it. When it is multi-dimensional, call your function recursively.
make all parameter but except the first one optional and then use list() and explode() if the first parameter is a string (or contains ,):
function j($a, $b=null){
if(strpos($a,',')!==false){
list($a,$b) = explode(',',$a)
}
return $a + $b;
}
this is just a basic example, but the principle should be clear:
check if one of the arguments is composed of multiple parameters
if so, parse it on your own to get the single parameters
function j($a, $b = 0){ // make second arg optional
if (! $b) { // is second arg specified and not zero
if (strpos($a, ',') !== false){ // has provided first arg a comma
list($first, $second) = explode(',' $a); // yes then get two values from it
return $first + $second; // return the result
}
}
else {
return $a + $b; // two args were passed, return the result
}
}
Now your function will support both formats, with one argument eg:
$str = '1,3'
j($str);
as well as two arguments:
j(5, 10);
This works :)
function f($str, $delimiter = ';')
{
$strargs = explode($delimiter, $str);
$args = array();
foreach($strargs as $item)
eval("\$args[] = " . $item. ";");
// $args contains all arguments
print_r($args);
}
Check it:
f("6;array(8,9);array(array(1,0,8), 5678)");
Most of the answers assume, that everything is nicely separated with coma ",", but it's not always the case. For example there could be different variable types, even strings with coma's.
$values = "123, 'here, is, a, problem, that, can\'t, be, solved, with, explode() function, mkay?'";
This can be handled with eval() and dot's "..." args retrieval in php 7.
function helper_string_args(...$args) {
return $args;
}
$func = "\$values = \\helper_string_args($values);";
try {
eval($func);
} catch (Exception $e) {
var_dump($e);
exit;
}