First-Class Callable Syntax

Turn any function or method into a Closure with the (...) syntax — type-safe, IDE-friendly references without stringly-typed callables.

PHP 8.1 gave us a clean way to grab a reference to a callable: append (...). strlen(...) is the strlen function as a Closure object; $obj->method(...) is a bound method; Klass::method(...) is a static one. No more error-prone strings like 'strlen' or [$obj, 'method'] arrays.

Easy example

<?php
$lengths = array_map(strlen(...), ['a', 'bb', 'ccc']);
print_r($lengths); // [1, 2, 3]

Because the result is a real Closure, your IDE can follow it, refactoring tools rename it, and static analysis checks the signature — everything the old string callables couldn't do.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Pass strlen(...) directly to array_map without wrapping it in an anonymous function.
  • Store a reference to a specific object method as a closure using $obj->method(...) for deferred invocation.
  • Replace a stringly-typed ['Math', 'sqrt'] callable with Math::sqrt(...) for IDE-refactorable references.

More examples

Built-in function as callable

strtoupper(...) creates a Closure from the built-in, replacing the verbose fn($s) => strtoupper($s) wrapper.

Example · php
<?php
$words  = ['hello', 'world', 'php'];
$upper  = array_map(strtoupper(...), $words);
$lengths = array_map(strlen(...), $words);

print_r($upper);   // HELLO, WORLD, PHP
print_r($lengths); // 5, 5, 3

Static method as callable

Sanitizer::slug(...) creates a Closure from the static method; it is type-checked and IDE-refactorable.

Example · php
<?php
class Sanitizer {
    public static function slug(string $s): string {
        return strtolower(preg_replace('/[^a-z0-9]+/i', '-', trim($s)));
    }
}

$titles  = ['Hello World', 'PHP 8 Features', 'First-Class Callables'];
$slugs   = array_map(Sanitizer::slug(...), $titles);

print_r($slugs);

Instance method as callable

$fmt->format(...) captures both the method and the bound object, creating a closure that remembers the currency.

Example · php
<?php
class Formatter {
    public function __construct(private string $currency) {}

    public function format(float $amount): string {
        return $this->currency . number_format($amount, 2);
    }
}

$fmt    = new Formatter('$');
$prices = [9.9, 24.99, 4.5];
$result = array_map($fmt->format(...), $prices);

print_r($result); // ['$9.90', '$24.99', '$4.50']

Discussion

  • Be the first to comment on this lesson.