Partial function application (PFA) lets you fill in some of a function's arguments and get back a closure that takes the rest. Instance methods have a hidden extra input, though: the object on the left of ->. PFA can't leave that one open, so you still need a hand-written closure when you want to call the same method on a list of objects. This RFC from Tim Düsterhus and Arnaud Le Blanc adds a this: ? placeholder to fix that.

How it works

You reference the method as ClassName::method and put this: ? where the object should go:

$dates = [new DateTimeImmutable('now')];

$formatted = array_map(DateTimeImmutable::format(this: ?, "c"), $dates);

The resulting closure is roughly equivalent to:

static fn (DateTimeImmutable $__this): string => $__this->format('c');

The class name you write becomes the type of the object parameter. this: ? can appear anywhere in the argument list, and its position sets the order of the closure's parameters. The only rule is that a ... placeholder still has to come last.

If you name an interface or a parent class, the closure uses that method's parameter names and types, even when the object turns out to be a child class. Methods handled by __call() work too.

Some uses are errors:

str_contains(this: ?, ?, ?);           // not a method
$dateTime->format(this: ?, "c");      // object is already given
DateTimeImmutable::getTimestamp(this: $date); // must be a placeholder

The RFC also shows a real-world case with a Symfony form's choice_label option, written as Category::getName(this: ?).

What it means for existing code

There's one small backward compatibility break. Today you can pass this: as a named argument to a variadic function, and it ends up as an array key. With this RFC, that becomes a compile-time error, though you can still pass it with ...['this' => 'test']. A scan of 18,975 Packagist packages by Seifeddine Gmati found no code using this: that way.

One open question is the name of the object parameter in the generated closure. It's $__this for now and might change.

Where it stands

It's under discussion and targets PHP 8.6. There's no vote yet.