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.
This is my php function it must return "5" but it returns nothing.
<?php
function get_second($num){
$second = $num[1]; //must return second number of the variable.
return $second;
}
$numbers=456789;
echo get_second($numbers);
?>
When I tried out this code, this returns nothing (NULL, empty).
But I tried out this function below, worked perfectly.
<?php
function get_second($num){
$second = $num[1]; //must return second number of the variable.
return $second;
}
$numbers=$_POST['number_input'];//that includes numbers
echo get_second($numbers);
?>
This code returns me second number of the post data. What I must do to work my First function? What is the difference between first $numbers variable and second $numbers variable?
Here the problem has to be better defined: how to get the second digit from a number. Your initial approach was correct in logic, but incorrect in the assumption that a number is a order set of characters. Only strings are ordered set of characters. Once you transform the integer 45678 to the string 45678 you can easily intercept the second character by using substr or even directly the string - because in PHP strings can be treated as arrays of characters.
#RamRaider solution is better than other have suggested but is overkill to use preg_split. Other solutions ask you to modify the type of the variable which is not done by adding quotes, but is done by casting to string, which is simpler and faster than a regular expression and you maintain your original variable in original form and your original function definition.
function get_second($num){
$second = $num[1]; //must return second number of the variable.
return $second;
}
$numbers = 456789;
// casting to string
echo get_second((string)$numbers);
// or transform to string by concatenation to a string
echo get_second($numbers ."");
// even quoting works
echo get_second("$numbers");
// using strval
echo get_second(strval($numbers));
// using settype
echo get_second(settype($numbers, "string"));
Try this: (add quotes to your integer variable)
<?php
function get_second($num){
$second = $num[1]; //must return second number of the variable.
return $second;
}
$numbers="456789";
echo get_second($numbers);
?>
If you want to get Character by its number then you can use substr()
function get_second($num)
{
return substr($num,1,1);
}
$numbers="456789";
echo get_second($numbers);
you are declaring a number in the $number variable.
if you want to view the second element than you have to use string.
try
$numbers= "456789";
it will output 5.
You could use preg_split to force an array from which you can choose any number by index, like:
$number=12358397;
function get_number($num,$i){
$num=preg_split( '#^\d$#', $num );
return $num[0][$i];
}
echo ' [1] > > > ' . get_number($number,1);
Suppose a string:
$str = 'a_b_c';
I want match all possible combination with a, b, c with above. For example:
b_a_c, c_a_b, a_c_b..etc will be give true when compare with above $str.
NOTE:
$str may be random. eg: a_b, k_l_m_n etc
I would split your string into an array, and then compare it to an array of elements to match on.
$originalList = explode('_', 'a_b_c');
$matchList = array('a', 'b', 'c');
$diff = array_diff($matchList, $originalList);
if (!empty($diff)) {
// At least one of the elements in $matchList is not in $originalList
}
Beware of duplicate elements and what not, depending on how your data comes in.
Documentation:
array_diff()
explode()
There is no builtin way to quickly do this. Your task can be accomplished many different ways which will vary on how general they are. You make no mention of null values or checking the formatting of the string, so something like this might work for your purpose:
function all_combos($str,$vals) {
$s=explode("_",$str);
foreach($s as $c) {
if(!in_array($s,$vals)) return false;
}
return true;
}
Call like all_combos("b_c_a",array("a","b","c"));
I am trying to turn a multidimensional array into a patterned string with this array_map function:
function array_to_string($array) {
return implode("&",array_map(function($a){return implode("~",$a);},$array));
}
$arr = array("hello",array("blue","red"),array("one","three","twenty"),"random");
array_to_string($arr);
Between each array element "&" and between each sub-array element (if it is an array) "~"
Should Output: hello&blue~red&one~three~twenty&random
However this outputs: Warning: implode(): Invalid arguments passed (2)
I tried changing the function within the array_map to detect whether the multi-array's value is_array but from my outputs, I don't think that is possible? So essentially, I guess the real question is how can I place a test on the array_map function to see whether or not it is_array
Since $a can be an array or a string, you should check it in your callback function:
function array_to_string($array) {
return implode("&",
array_map(function($a) {
return is_array($a) ? implode("~",$a) : $a;
}, $array)
);
}
Is there any simple way of checking if all elements of an array are instances of a specific type without looping all elements? Or at least an easy way to get all elements of type X from an array.
$s = array("abd","10","10.1");
$s = array_map( gettype , $s);
$t = array_unique($s) ;
if ( count($t) == 1 && $t[0]=="string" ){
print "ok\n";
}
You cannot achieve this without checking all the array elements, but you can use built-in array functions to help you.
You can use array_filter to return an array. You need to supply your own callback function as the second argument to check for a specific type. This will check if the numbers of the array are even.
function even($var){
return(!($var & 1));
}
// assuming $yourArr is an array containing integers.
$newArray = array_filter($yourArr, "even");
// will return an array with only even integers.
As per VolkerK's comment, as of PHP 5.3+ you can also pass in an anonymous function as your second argument. This is the equivalent as to the example above.
$newArray = array_filter($yourArr, function($x) { return 0===$x%2; } );
Is there any simple way of checking if all elements of an array [something something something] without looping all elements?
No. You can't check all the elements of an array without checking all the elements of the array.
Though you can use array_walk to save yourself writing the boilerplate yourself.
You can also combine array_walk with create_function and use an anonymous function to filter the array. Something alon the lines of:
$filtered_array = array_filter($array, create_function('$e', 'return is_int($e)'))