Array Repack Operator in PHP Concept
Presenting concept of array operator which repacks array by keys to newly created array. I’ve called it Array Repacking because such functionality will produce new array based on original array just with some few improvements.
Syntax
Proposed syntax doesn’t break any current syntax upon PHP 7.1.
$strings = ['one' => 1, 'two' => 2, 'three' => 3];
$onlyThreeAndTwo = $strings['three', 'two'];
var_dump($onlyThreeAndTwo);
//array(2) {
// ["three"]=>
// int(3)
// ["two"]=>
// int(2)
//}
As we can observe array $strings
is being repacked with only two keys
three and two with different order and returns new array which is stored
in $onlyThreeAndTwo
.
Benefits
This behaviour can be useful when we need to cut off some values from array. It’s kinda shorthand for:
$strings = ['one' => 1, 'two' => 2, 'three' => 3];
$onlyThreeAndTwo = array_intersect_key($strings, array_flip(['three', 'two']));
var_dump($onlyThreeAndTwo);
//array(2) {
// ["two"]=>
// int(2)
// ["three"]=>
// int(3)
//}
Results are different because there is original keys order as in $strings
table.
In most cases it doesn’t matter but there is one specific feature in PHP
which would actually benefit from this - it’s called variadic function.
Variadic function can accept undefined number of arguments passed by adding
...
in front of function argument, for eg.:
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
In above example there can be undefined number of arguments passed into
function and all became accessible by $numbers
array.
But that’s not the whole point I’m referring to variadic.
There is also possibility to pass function arguments by array with ...
at function call.
function add($a, $b) {
return $a + $b;
}
echo add(...[1, 2])."\n";
$a = [1, 2];
echo add(...$a);
As we can see calling add an array with 1 and 2 was passed and those became
values of $a
and $b
variable.
Now imagine quite longer example where Array Repack would help:
class Service {}
class ServiceFactory {
public function createService($name, $type, $scheme, $host, $port, $path) : Service {
return new Service($name, $type, $scheme, $host, $port, $path);
}
}
// and now we're going to repack entities into `Service` instances
$data = [
[
'id' => 156789,
'host' => 'localhost',
'port' => 80,
'type' => 'auth',
'scheme' => 'http',
'path' => '/auth',
'name' => 'authorisation'
],
];
$serviceFactory = new ServiceFactory();
foreach ($data as $service) {
$serviceFactory->createService(...$service['name', 'type', 'scheme', 'host', 'port', 'path']);
}
// and without repacking it'll be
$serviceFactory = new ServiceFactory();
foreach ($data as $service) {
$serviceFactory->createService($service['name'], $service['type'], $service['scheme'], $service['host'], $service['port'], $service['path']);
}