PHP 8.1 and 8.2 brought named arguments and first-class callables – two features that change the way code is written. Named arguments eliminate “argument order confusion” and improve the readability of function calls with many parameters. First-class callables replace Closure::fromCallable() and [$this, 'method'] with the clean func(...) syntax.
Named arguments
<?php
declare(strict_types=1);
// Without named arguments - you have to remember the order
array_slice($array, 0, 10, true); // What does true mean? (preserve_keys)
// With named arguments - readable, order does not matter
array_slice(array: $array, offset: 0, length: 10, preserve_keys: true);
function createProduct(
string $sku,
string $name,
float $price,
int $qty = 0,
bool $isVisible = true,
bool $isEnabled = true,
string $type = 'simple',
?int $categoryId = null,
): array {
return compact('sku', 'name', 'price', 'qty', 'isVisible', 'isEnabled', 'type', 'categoryId');
}
// With named arguments - only specify what you want to change
createProduct(
sku: 'SKU-001',
name: 'Widget',
price: 99.99,
categoryId: 5,
);
// Named spread from config array - order does not matter!
$config = ['db' => 'magento', 'host' => 'localhost', 'port' => 3306];
connect(...$config);
First-class callables
<?php
// PHP 8.1: first-class callable syntax
// Before:
$closure = Closure::fromCallable('strlen');
$method = Closure::fromCallable([$this, 'processItem']);
// After - cleaner syntax:
$closure = strlen(...);
$method = $this->processItem(...);
$static = MyClass::staticMethod(...);
class OrderProcessor
{
public function processOrders(array $orders): array
{
return array_map($this->processOrder(...), $orders);
}
public function processOrder(array $order): array
{
return ['id' => $order['id'], 'processed' => true];
}
public function filterAndProcess(array $orders): array
{
return array_map(
$this->processOrder(...),
array_filter($orders, $this->isEligible(...))
);
}
private function isEligible(array $order): bool
{
return $order['status'] === 'pending' && $order['total'] > 0;
}
}
Pipeline style with first-class callables
<?php
class Pipeline
{
private array $stages = [];
public function pipe(callable $stage): static
{
$clone = clone $this;
$clone->stages[] = $stage;
return $clone;
}
public function process(mixed $payload): mixed
{
return array_reduce(
$this->stages,
fn($carry, $stage) => $stage($carry),
$payload
);
}
}
class OrderPipeline
{
public function handle(array $order): array
{
return (new Pipeline())
->pipe($this->validator->validate(...))
->pipe($this->taxCalculator->calculate(...))
->pipe($this->discountApplier->apply(...))
->pipe($this->notifier->notify(...))
->process($order);
}
}
Summary
Named arguments help most with calls that have many optional parameters and with spreading from config arrays. First-class callables eliminate the [$this, 'method'] boilerplate and improve readability of pipeline-style code. Together with match expressions and enums from PHP 8.x they form a set that significantly shortens and clarifies modern PHP.
