[php-src] PR #24030: [Draft RFC] Automated delegation using implements by
| From: | knegyesi | Date: | Thu, 01 Oct 2026 00:16:42 +0000 |
| Subject: | [php-src] PR #24030: [Draft RFC] Automated delegation using implements by | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-39019@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/24030
Author: knegyesi
====== PHP RFC: Automated delegation using implements by ======
* Version: 0.9
* Date: 2026-09-30
* Author: Karoly Negyesi <karoly@negyesi.net>
* Status: Draft
* Implementation: right here
* Discussion thread: https://news-web.php.net/php.internals/…
* Voting thread: tbd
===== Introduction =====
Composition is a frequently used design pattern. For example,
```php
class MetadataBubblingUrlGenerator implements UrlGeneratorInterface {
public function __construct(
private UrlGeneratorInterface $url_generator,
private RendererInterface $renderer
) {}
public function setContext(SymfonyRequestContext $context): void {
$this->urlGenerator->setContext($context);
}
public function getContext(): SymfonyRequestContext {
return $this->urlGenerator->getContext();
}
```
The disadvantages are obvious: unnecessary boilerplate and maintenance burden as the interface gets
more methods over time.
===== Proposal =====
Automate the pattern above using a new syntax
implements by. When a class uses
implements T by $t then generate all the proxy methods for methods of T if
the class doesn't have them. Explicitly defined methods -- whether they are on the class, a
parent class or a trait -- always win. Generated methods win over __call.
==== Examples ====
```php
interface T1 {
function T1method();
}
class ExampleImplementation implements T1 {
function T1method() { print "Example"; }
}
class C implements T1 by $t1 {
public function __construct(
private T1 $t1,
) {}
}
new C(new ExampleImplementation)->T1method(); // Example
```
===== Backward Incompatible Changes =====
None. The scanner rule ensures only the "by" keyword followed by a variable gets parsed
into T_BY. (I copied the rule from enum with appropriate adjustements.)
===== Proposed PHP Version(s) =====
next PHP 8.x
===== RFC Impact =====
==== To the Ecosystem ====
Less boilerplate.
==== To Existing Extensions ====
No.
==== To SAPIs ====
None.
===== Open Issues =====
1. Does opcode need an update?
2. Does reflection need something?
===== Future Scope =====
When two interfaces have a method of the same name the first one wins naturally because it gets a
generated method and the second interface will see it as an existing method. Using novel call time
syntax to resolve the ambiguity is planned but it is out of scope.
===== References =====
- Kotlin, Delegation: https://kotlinlang.org/docs/delegation.html
- Go, Embedding: https://go.dev/doc/effective_go#embedding
===== Rejected Features =====
===== Changelog =====