Re: [PHP-DEV] Class Extension

2026-07-11 Thread Holly Schilling
> Again: the "use extension" isn't bad per se, it's just that the "use" keyword 
> *doesn't do anything*, and never has. It's just an alias. Adding "use 
> extension", though being "slightly different" that just having "use", still 
> means that it's gonna be on top of the PHP file, many IDEs already fold these 
> statements for readability.

What is wrong with folding these statements? 

I think you’re overthinking what will likely end up being the common use case 
in an IDE. The user is going to type something like `$m->extensionMethod()`, 
it’s going to get a red squiggly line under it, they’ll click the suggestion to 
add the `use extension` at the top, and they will move on. 

When the PR goes up for review, the reviewer is going to see it, check if they 
used the right extension, and flag it if they used the wrong one. 



> Something else I am thinking about changing the keyword and applying the 
> extension to a class directly at the same time:

This sounds harsh, so my apologies in advance. 

I reject this functionality.

1. Since extensions are scoped to a single file (which is typically a single 
class) and not global, they don’t encounter many situations where this would 
even be a consideration.
2. Extensions only occupy the path that would otherwise throw a method not 
found exception. They are the method of last resort for a match, so they never 
override functionality. Calling an extension method on any class that didn’t 
have the extension applied always results in an exception being thrown.
3. The functionality you are describing already exists in Traits. Extensions 
are complementary to Traits, not a replacement. For the situation you are 
describing, an Extension is not the right tool and trying to make it fit that 
use case would be damaging to the overall simplicity of them. 



Re: [PHP-DEV] Class Extension

2026-07-11 Thread Holly Schilling

Holly

> On Jul 11, 2026, at 4:12 AM, Alex Pierstoval Rock  
> wrote:
> 
> Le 10/07/2026 à 20:33, Holly Schilling a écrit :
>> .
>>> As far as scalar methods goes, I hate my implementation. I’m not suggesting 
>>> someone else could do better, only that the compromises necessary to 
>>> implement it weren’t worth it. After having implemented it and seen what it 
>>> demands, I think the right choice is Autoboxing with extensions on the box 
>>> rather than ever allowing `$this` to not be an object.
>>> 
>>> This is a heated topic lately and I don’t pretend to be an expert.
>>> 
>> Typing this email this morning gave me real hesitation. If I can’t support 
>> my own implementation, no one else should either. I immediately set out to 
>> build a better version that I could put my full weight behind.
>> 
>> Autoboxing turned out to be a non-starter as well. The code just didn’t fit 
>> the model of the code PHP uses. That led me to a diffident path.
>> 
>> C# 14 recently added a new extensions syntax to allow for properties and 
>> more. When I saw it, I knew it was the right solution.
>> 
>> ```
>> extension string $str {
>>   function length() {
>> return strlen($str);
>>   }
>> }
>> 
>> var_dump(“test”->length()); // int(4)
>> ```
>> 
>> By declaring the parameter inline with the extension declaration, we 
>> eliminate the downcast of `$this`, the fake accessibility constraints, and 
>> all the sharp edges the old way introduces.
>> 
>> I immediately rewrote all 3 RFCs to use this new syntax, as well as the code 
>> to implement it.
>> 
>> Anyone who has been following these discussions, please skim the updated 
>> docs for changes.
> 
> 
> Thanks for these changes, they bring better stuff to the table indeed :)
> 
> Still my first thought stands: I think scalar extensions are dispensible, and 
> having scalars behave "like objects" is quite new to PHP

I have some people saying that scalar methods are a hard requirement. I have 
others like yourself saying they are a separate issue and should be treated as 
such. I believe I have struck a good balance here for two reasons. First, they 
*ARE* a separate RFC that can receive separate voting and discussion. Second, 
even if they are adopted, there is no mechanism for global pollution. A user 
only has methods available that they deliberately bring into scope. 

> workarounds do exist for that: there are quite a few PHP packages to 
> manipulate strings, utf8 handling, graphemes or codepoints, etc., that could 
> be used "as string extensions" if such RFC came to become real in the 
> language. I think it needs more time, investigation on packages, whether to 
> decide on adding "standard extensions" to start uniformizing string-related 
> functions (something that's been asked for a long time).

This is also something I’m going to push back on. There is nothing that “more 
time and investigation” will change about how existing libraries will be 
affected by this. This is an additional tool for them and they will need to 
find what works best for them once it lands. What Stringy feels works best for 
them doesn’t have to be what Nette believes works best. That’s the strength of 
the PHP ecosystem. We create the tools and let people find the best way to use 
them. The tool is not prescriptive. 

Re: [PHP-DEV] Class Extension

2026-07-11 Thread Alex "Pierstoval" Rock

Le 10/07/2026 à 17:41, Holly Schilling a écrit :

The two other RFCs imply extensions will need to be imported via manual 
require/require_once calls, therefore package maintainers declaring extensions will have 
to use the "autoload.files" composer option. It works, but it will add an 
overhead (wasting time in file load and wasting memory usage) on extensions that are 
declared but not used.

With the inclusion of the Visibility RFC, explicit `require` or `require_once` 
is not necessary. The `use extension` syntax replaces it. The consequence of 
this is that extension methods are only visible in scopes that explicitly want 
them. This prevents the from polluting globally.


If autoload was triggered when encountering "use extension", it would have the advantage of being 
explicit, but it's counter-intuitive: "use" statements shouldn't usually trigger anything and just 
serve as aliases for symbols referenced in the file, so it's inconsistent with current usage of the 
"use" keyword.
And if package maintainers don't use "autoload.files" to avoid the potentially unnecessary 
overhead, this means that userland code would be forced to write "require_once 'path/to/extension.php'; 
" in their own files, which is not at all what anyone would expect, and defeats the purpose of having a 
dependencies manager like Composer in the first place, even though "it works".

The new `use extension` syntax is a slightly different purpose than developers 
are used to with an ordinary `use` declaration, but it follows the same spirit. 
There is a thing not in this file that needs to be brought into scope.


Again: the "use extension" isn't bad per se, it's just that the "use" 
keyword *doesn't do anything*, and never has. It's just an alias. Adding 
"use extension", though being "slightly different" that just having 
"use", still means that it's gonna be on top of the PHP file, many IDEs 
already fold these statements for readability.


Something else I am thinking about changing the keyword and applying the 
extension to a class directly at the same time:



        return IpUtils::checkIp($this->server->get('REMOTE_ADDR', ''), 
[$ip]);

    }
}

?>

isBehindProxy()); // works


We can imagine that the "extends A with B;" keyword is redundant, but it 
brings an advantage in the fact that an extension declares the "minimum" 
class it's capable of extending, but it could also declare no class at 
all (thus removing the "for ..." part of the extension's declaration).


In such case, the *user* determines which "maximum" class it will 
actually extend, and if there is a mismatch it could throw an error:


extend LastImpl with InterfaceExtension; // Works: LastImpl -> 
TransientClass -> SomeInterface


extend StandaloneClass with InterfaceExtension; // Error: 
"StandaloneClass" does not extend nor implement "SomeInterface"
extend StandaloneClass with ClassExtension; // Error: "StandaloneClass" 
does not extend nor implement "SomeClass"



The "extend ... with ..." is clearer on what it does, userland has a bit 
more control, but extension defines its rules.


WDYT?


Re: [PHP-DEV] Class Extension

2026-07-11 Thread Alex "Pierstoval" Rock

Le 10/07/2026 à 20:33, Holly Schilling a écrit :

.

As far as scalar methods goes, I hate my implementation. I’m not suggesting 
someone else could do better, only that the compromises necessary to implement 
it weren’t worth it. After having implemented it and seen what it demands, I 
think the right choice is Autoboxing with extensions on the box rather than 
ever allowing `$this` to not be an object.

This is a heated topic lately and I don’t pretend to be an expert.


Typing this email this morning gave me real hesitation. If I can’t support my 
own implementation, no one else should either. I immediately set out to build a 
better version that I could put my full weight behind.

Autoboxing turned out to be a non-starter as well. The code just didn’t fit the 
model of the code PHP uses. That led me to a diffident path.

C# 14 recently added a new extensions syntax to allow for properties and more. 
When I saw it, I knew it was the right solution.

```
extension string $str {
   function length() {
 return strlen($str);
   }
}

var_dump(“test”->length()); // int(4)
```

By declaring the parameter inline with the extension declaration, we eliminate 
the downcast of `$this`, the fake accessibility constraints, and all the sharp 
edges the old way introduces.

I immediately rewrote all 3 RFCs to use this new syntax, as well as the code to 
implement it.

Anyone who has been following these discussions, please skim the updated docs 
for changes.



Thanks for these changes, they bring better stuff to the table indeed :)

Still my first thought stands: I think scalar extensions are 
dispensible, and having scalars behave "like objects" is quite new to 
PHP workarounds do exist for that: there are quite a few PHP packages to 
manipulate strings, utf8 handling, graphemes or codepoints, etc., that 
could be used "as string extensions" if such RFC came to become real in 
the language. I think it needs more time, investigation on packages, 
whether to decide on adding "standard extensions" to start uniformizing 
string-related functions (something that's been asked for a long time). 
There's also a few libraries that could benefit from it, like 
nette/utils, with their String manipulation API (check it out: 
https://doc.nette.org/en/utils/strings).
For short: great idea, but needs more benchmarks, packages and ecosystem 
analyses, etc.


Re: [PHP-DEV] Class Extension

2026-07-10 Thread Holly Schilling
.
> 
> As far as scalar methods goes, I hate my implementation. I’m not suggesting 
> someone else could do better, only that the compromises necessary to 
> implement it weren’t worth it. After having implemented it and seen what it 
> demands, I think the right choice is Autoboxing with extensions on the box 
> rather than ever allowing `$this` to not be an object.
> 
> This is a heated topic lately and I don’t pretend to be an expert.
> 

Typing this email this morning gave me real hesitation. If I can’t support my 
own implementation, no one else should either. I immediately set out to build a 
better version that I could put my full weight behind. 

Autoboxing turned out to be a non-starter as well. The code just didn’t fit the 
model of the code PHP uses. That led me to a diffident path. 

C# 14 recently added a new extensions syntax to allow for properties and more. 
When I saw it, I knew it was the right solution.

```
extension string $str {
  function length() {
return strlen($str);
  }
}

var_dump(“test”->length()); // int(4)
```

By declaring the parameter inline with the extension declaration, we eliminate 
the downcast of `$this`, the fake accessibility constraints, and all the sharp 
edges the old way introduces. 

I immediately rewrote all 3 RFCs to use this new syntax, as well as the code to 
implement it. 

Anyone who has been following these discussions, please skim the updated docs 
for changes. 

Re: [PHP-DEV] Class Extension

2026-07-10 Thread Holly Schilling

Holly

> On Jul 10, 2026, at 10:20 AM, Alex Rock  wrote:
>
> Le 10/07/2026 à 06:38, Holly Schilling a écrit :
>>
>>>
>>> For one, I read only internals and github.  I keep seeing "we talked on 
>>> discord" but there is no reference whatsoever to a php.net 
>>> 's discord anywhere i searched for.
>>>
>>> so maybe I would suggest to be a tat bit more descriptive first here too?
>>
>> Yes, this has not been as public of a discussion as it should be, so please 
>> allow me to share some more details here for you and the rest of the 
>> Internals community.
>>
>> There are currently 3 RFCs comprising 3 phases and feature sets to build for 
>> extensions.
>>
>> 1. General Class Extension Syntax: 
>> https://gist.github.com/hollyschilling/f590f3a1e488732eea5b0d8014702276
>> This RFC adds a basic extensions using this syntax:
>> ```
>> extension \DateTimeImmutable {
>> public function isWeekend():bool {
>> return in_array((int)$this->format('N'), [6,7],true);
>> }
>> }
>> var_dump((new DateTimeImmutable('2026-07-11'))->isWeekend());// bool(true)
>> ```
>>
>> 2. Scalar Method Extensions: 
>> https://gist.github.com/hollyschilling/1d247189b8bf45fe044bfbe7fb07dcdb
>> Allow extensions to be applied to scalars, like strings and ints. This has a 
>> lot of code changes to make this work and the blast radius is huge. That’s 
>> why it’s a separate component.
>> ```
>> extension string {
>> public function length():int {return strlen($this); }
>> }
>>
>> var_dump("hello"->length());// int(5)
>> ```
>>
>> 3. Extension Visibility and Importing: 
>> https://gist.github.com/hollyschilling/dc97ea217302de2f4c9ad7d527aaa65b
>> This adds rules and syntax to be able to import an extension without using 
>> `require_once` (or similar).
>>
>> First, the autoloader needs extensions to have a name, so we give them a 
>> name when declared.
>> ```
>> // vendor/acme/dom-kit/src/traversal.php
>> namespace Acme\DomKit;
>>
>> extension DomTraversal on \DOMElement {
>> public function firstByClass(string $class): ?\DOMElement {/* ... */ }
>> }
>> ```
>> Then, as we want to use our declared extensions, we import them with a 
>> `use`, similar to normal classes.
>> ```
>> use extension Acme\DomKit\DomTraversal;
>>
>> $el->firstByClass('hero');// resolves here
>> ```
>>
>>>
>>>I believe I’ve proven out the concept and viability of it in a
>>>2-phase approach using an extension syntax similar to that of Swift.
>>>
>>>Before I go into much more detail, what is the general interest
>>>in adding this to the language?
>>>
>>>
>>> reading the thread, I feel both swift and you aim to the same goal, some 
>>> parts use different approaches but as I am not a user of swift, it may be 
>>> nicer if you could work together,  if desired?
>>>
>>
>> Extension methods allow adding functions to existing classes. As a future 
>> consideration, they can also be used to add readonly virtual properties (No 
>> setter; No storage). This is purely syntactic sugar, but it can be extremely 
>> helpful making code easier to read and increasing code reuse. Think of it as 
>> a Trait that you apply to someone else’s code after the fact.
>>
>> It is also possible to apply an extension to an Interface. While it cannot 
>> be used to implement members of the interface, it can make all classes 
>> implementing that interface have useful methods.
>>
>> The other useful feature is that a class may implement its own version of a 
>> function and the function resolution will go to the class’s implementation 
>> as you might expect.
>>
>> I hope this helps. The 3 links go to the Gists for each phase and a link 
>> from each Gist goes to the implementation for each.
>>
>> I’m happy to answer any additional questions you or anyone else has as you 
>> read through the docs.
>>
>> Holly
>
>
> Thanks for all these links, I think the conversation should start from this 
> thread from now on, to avoid referring to unknown mails or discord channels :)
>
> On the feature itself, I'm not knowledgeable enough on the engine impact, and 
> the concept of Extensions could be a really great addition to PHP, however on 
> the userland-side, things must be extra clear to avoid messing up with 
> potential unidentified edge-cases when declaring or using an extension, and 
> the actual impact on the ecosystem and usage.

There are lots of potential sharp edges here. I believe I’ve addressed them all 
in the code and RFC, but I’m definitely open to having more pointed out.

>
> The RFC about scalar extensions can be deferred and is optional (though very 
> good, but having built-in classes for scalars, but the first RFC and the 
> visibility RFC should be merged and re-thought in order to fix the loading 
> issue. Maybe you could chat with @azjezz about this part, because it's the 
> kind of thing that could be shipped in his "PHP PSL" project (visible there: 
> https://github.com/php-standard-library/php-standard-library)

I’ve never 

Re: [PHP-DEV] Class Extension

2026-07-10 Thread Rowan Tommins [IMSoP]
On 10 July 2026 15:44:47 BST, Holly Schilling  
wrote:
>
>Dispatched inside an extension method is exactly the same as anywhere else 
>besides that `$this` only has the public surface accessible. If a user calls a 
>method name that doesn’t exist, it does the same as usual. That hasn’t changed.

Gotcha. The confusion came from the mention of "compile-time", which isn't when 
visibility checks happen. The method is looked up, then its visibility flags 
are enforced, all at runtime.

So another way of putting it is that an extension method has no privileged 
access to the target class.

That is indeed different from a trait. Whereas a trait is pasted into the 
class, an extension function stays separate and $this is just a normal object 
reference being accessed "publicly".

Regards,

Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Class Extension

2026-07-10 Thread Alex Rock

Le 10/07/2026 à 06:38, Holly Schilling a écrit :




For one, I read only internals and github.  I keep seeing "we talked 
on discord" but there is no reference whatsoever to a php.net 
's discord anywhere i searched for.


so maybe I would suggest to be a tat bit more descriptive first here too?


Yes, this has not been as public of a discussion as it should be, so 
please allow me to share some more details here for you and the rest 
of the Internals community.


There are currently 3 RFCs comprising 3 phases and feature sets to 
build for extensions.


1. General Class Extension Syntax: 
https://gist.github.com/hollyschilling/f590f3a1e488732eea5b0d8014702276

This RFC adds a basic extensions using this syntax:
```
extension \DateTimeImmutable {
 public function isWeekend():bool {
 return in_array((int)$this->format('N'), [6,7],true);
 }
}
var_dump((new DateTimeImmutable('2026-07-11'))->isWeekend());// bool(true)
```

2. Scalar Method Extensions: 
https://gist.github.com/hollyschilling/1d247189b8bf45fe044bfbe7fb07dcdb
Allow extensions to be applied to scalars, like strings and ints. This 
has a lot of code changes to make this work and the blast radius is 
huge. That’s why it’s a separate component.

```
extension string {
 public function length():int {return strlen($this); }
}

var_dump("hello"->length());// int(5)
```

3. Extension Visibility and Importing: 
https://gist.github.com/hollyschilling/dc97ea217302de2f4c9ad7d527aaa65b
This adds rules and syntax to be able to import an extension without 
using `require_once` (or similar).


First, the autoloader needs extensions to have a name, so we give them 
a name when declared.

```
// vendor/acme/dom-kit/src/traversal.php
namespace Acme\DomKit;

extension DomTraversal on \DOMElement {
 public function firstByClass(string $class): ?\DOMElement {/* ... */ }
}
```
Then, as we want to use our declared extensions, we import them with a `use`, 
similar to normal classes.
```
use extension Acme\DomKit\DomTraversal;

$el->firstByClass('hero');// resolves here
```



I believe I’ve proven out the concept and viability of it in a
2-phase approach using an extension syntax similar to that of Swift.

Before I go into much more detail, what is the general interest
in adding this to the language?


reading the thread, I feel both swift and you aim to the same goal, 
some parts use different approaches but as I am not a user of swift, 
it may be nicer if you could work together,  if desired?




Extension methods allow adding functions to existing classes. As a 
future consideration, they can also be used to add readonly virtual 
properties (No setter; No storage). This is purely syntactic sugar, 
but it can be extremely helpful making code easier to read and 
increasing code reuse. Think of it as a Trait that you apply to 
someone else’s code after the fact.


It is also possible to apply an extension to an Interface. While it 
cannot be used to implement members of the interface, it can make all 
classes implementing that interface have useful methods.


The other useful feature is that a class may implement its own version 
of a function and the function resolution will go to the class’s 
implementation as you might expect.


I hope this helps. The 3 links go to the Gists for each phase and a 
link from each Gist goes to the implementation for each.


I’m happy to answer any additional questions you or anyone else has as 
you read through the docs.


Holly



Thanks for all these links, I think the conversation should start from 
this thread from now on, to avoid referring to unknown mails or discord 
channels :)


On the feature itself, I'm not knowledgeable enough on the engine 
impact, and the concept of Extensions could be a really great addition 
to PHP, however on the userland-side, things must be extra clear to 
avoid messing up with potential unidentified edge-cases when declaring 
or using an extension, and the actual impact on the ecosystem and usage.


The RFC about scalar extensions can be deferred and is optional (though 
very good, but having built-in classes for scalars, but the first RFC 
and the visibility RFC should be merged and re-thought in order to fix 
the loading issue. Maybe you could chat with @azjezz about this part, 
because it's the kind of thing that could be shipped in his "PHP PSL" 
project (visible there: 
https://github.com/php-standard-library/php-standard-library)


The two other RFCs imply extensions will need to be imported via manual 
require/require_once calls, therefore package maintainers declaring 
extensions will have to use the "autoload.files" composer option. It 
works, but it will add an overhead (wasting time in file load and 
wasting memory usage) on extensions that are declared but not used.
If autoload was triggered when encountering "use extension", it would 
have the advantage of being explicit, but it's counter-intuitive: "use" 
statements shouldn't 

Re: [PHP-DEV] Class Extension

2026-07-10 Thread Holly Schilling

I'm not sure if I'm misunderstanding, but if you're saying that every reference 
to $this in the body of an extension method will be analysed by the compiler 
against the class definition, that would be extremely surprising to PHP users.

As far as I know, *all* method and property despatch in PHP is dynamic, whether 
it's on $this or any other object reference. In other words, only when you 
actually *run* code like $this->whatever() does PHP even try to look for the 
method definition.

I’m trying to speak vaguely to keep messages brief because I’m generally typing 
from my phone. In doing so, I’m adding inaccurate edge cases which you’re 
astutely noticing, but they aren’t the details I was focused on. For full 
details, please read the draft RFC I posted as a Gist. 
https://gist.github.com/hollyschilling/f590f3a1e488732eea5b0d8014702276

Dispatched inside an extension method is exactly the same as anywhere else 
besides that `$this` only has the public surface accessible. If a user calls a 
method name that doesn’t exist, it does the same as usual. That hasn’t changed.


Re: [PHP-DEV] Class Extension

2026-07-10 Thread Rowan Tommins [IMSoP]
On 10 July 2026 13:46:08 BST, Holly Schilling  
wrote:
>
>Now knowing that, it makes the case for using a different keyword like 
>`extension` much stronger since that is not the case for an extension. 
>Everything on an extension is type-checked at compile time, save some edge 
>cases with scalars. 

I'm not sure if I'm misunderstanding, but if you're saying that every reference 
to $this in the body of an extension method will be analysed by the compiler 
against the class definition, that would be extremely surprising to PHP users. 

As far as I know, *all* method and property despatch in PHP is dynamic, whether 
it's on $this or any other object reference. In other words, only when you 
actually *run* code like $this->whatever() does PHP even try to look for the 
method definition.

Trying to validate that at compile time would presumably break any dynamic code 
- $this->whatever() would not be allowed to fall back to __call('whatever'), 
and $this->{$someVar}() would have to refuse to compile.

While we could argue whether those features make PHP better or worse, having 
them forbidden just in the context of extension methods would feel very 
arbitrary.

However, perhaps we're talking at cross purposes, and this is not actually what 
you're proposing.

Regards,

Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Class Extension

2026-07-10 Thread Holly Schilling


> There is no such check in PHP. Static Analysis tools may warn about it, but a 
> trait will compile fine with code that refers to unknown members. The code 
> will then succeed or fail at runtime just like any other object access:

I have to admit I never knew that worked. I genuinely learned something new 
today. 

Now knowing that, it makes the case for using a different keyword like 
`extension` much stronger since that is not the case for an extension. 
Everything on an extension is type-checked at compile time, save some edge 
cases with scalars. 

Re: [PHP-DEV] Class Extension

2026-07-10 Thread Rowan Tommins [IMSoP]
On 10 July 2026 12:53:39 BST, Holly Schilling  
wrote:
> What I was referring to is that at compile-time from inside a function of the 
> trait, it can only call members known to the trait.


There is no such check in PHP. Static Analysis tools may warn about it, but a 
trait will compile fine with code that refers to unknown members. The code will 
then succeed or fail at runtime just like any other object access: 


Regards,

Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Class Extension

2026-07-10 Thread Holly Schilling

>> The reason I don’t feel the `trait … for` syntax is appropriate is because 
>> of `$this`. In a function inside a typical trait, `$this` refers to an 
>> instance of the trait. In an extension, `$this` refers to an instance of the 
>> class being extended.
> 
> 
> I don't think that's true - there's no such thing as an "instance of a 
> trait", the contents of a trait are pasted directly into the class where 
> they're used, and act just as if they were written inline at that point.
> 
> What that does mean is that they have access to private members, which I 
> understand extensions would not, so that might be a good reason to use a new 
> keyword.
> 
> 
> Rowan Tommins
> [IMSoP]

I was unclear in my description. `$this` in a trait will be an instance of what 
it applies to and will pass runtime checks via `instanceof`. What I was 
referring to is that at compile-time from inside a function of the trait, it 
can only call members known to the trait. Whereas in an extension, the entire 
public surface of the extended type is known and available, plus the members of 
the extension.

So that isn’t to say `trait … for` couldn’t work, but it feels very different 
to a trait in its use. 

Re: [PHP-DEV] Class Extension

2026-07-10 Thread Rowan Tommins [IMSoP]
On 10 July 2026 05:38:08 BST, Holly Schilling  
wrote:
>
>There are currently 3 RFCs comprising 3 phases and feature sets to build for 
>extensions.

Hi Holly,

Thanks for sharing those links, that gives a better idea what we're actually 
discussing here. 

My initial reaction is that the anonymous/global extensions and named/scoped 
extensions feel more like competing versions of the same feature than natural 
phases that build on each other. 

For instance we might choose different conflict resolution behaviour if 
extensions are always scoped, but would hesitate to have two different 
behaviours if we implemented both types of extension.

The named/scoped version feels like it fits better with how I see PHP 
applications structured - heavy reliance on autoloading, as little global 
bootstrapping code as possible. It also gives static analysers and IDEs a 
clearer signal where to look for the extension.

For the anonymous version, does the target have to be defined for the extension 
to be loaded? If it isn't, will the autoloader be called? I'm struggling to 
picture how I'd use that version in practice.

Thanks for your work on this so far,

Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Class Extension

2026-07-10 Thread Rowan Tommins [IMSoP]
On 10 July 2026 06:02:13 BST, Holly Schilling  
wrote:

>The reason I don’t feel the `trait … for` syntax is appropriate is because of 
>`$this`. In a function inside a typical trait, `$this` refers to an instance 
>of the trait. In an extension, `$this` refers to an instance of the class 
>being extended.


I don't think that's true - there's no such thing as an "instance of a trait", 
the contents of a trait are pasted directly into the class where they're used, 
and act just as if they were written inline at that point.

What that does mean is that they have access to private members, which I 
understand extensions would not, so that might be a good reason to use a new 
keyword.


Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Class Extension

2026-07-09 Thread Holly Schilling

First, my apologies to the readers. Something is chewing up my formatting and 
indenting. I’m still trying to figure out a cause.

If we ignore implementation details and ownership it's pretty similar to what 
we have with traits. In PHP, what would be the benefit of extensions over 
traits? One thing that comes to my mind is that traits can be used by whatever 
chooses to add it (back to ownership). Good one, but what else? If ownership is 
the only concern then maybe a small addition to traits could achieve the same?


```
trait Foo
{
for Baz\Bar::class;  // inverse of "use" to limit usage
}

class Bar
{
use Foo;
}
```

Brings conflict resolution for free; and I think it would be cheaper than yet 
another class-like thing. Maybe also feels more php-ish since we already have 
the trait concept?

If we ignore precise syntax and implementation, this is exactly the mental 
model of my RFCs and implementations. It is applying a trait to an existing 
class that you don’t control.

The similarities don’t end there. This is the same infrastructure as what is 
used to implement this feature.

The reason I don’t feel the `trait … for` syntax is appropriate is because of 
`$this`. In a function inside a typical trait, `$this` refers to an instance of 
the trait. In an extension, `$this` refers to an instance of the class being 
extended. Adding the `for` block to the trait changes the type of `$this` in 
the entire trait. That is unintuitive and likely to introduce barriers to 
understanding.


Holly


Re: [PHP-DEV] Class Extension

2026-07-09 Thread Holly Schilling


For one, I read only internals and github.  I keep seeing "we talked on 
discord" but there is no reference whatsoever to a php.net's 
discord anywhere i searched for.

so maybe I would suggest to be a tat bit more descriptive first here too?

Yes, this has not been as public of a discussion as it should be, so please 
allow me to share some more details here for you and the rest of the Internals 
community.

There are currently 3 RFCs comprising 3 phases and feature sets to build for 
extensions.

1. General Class Extension Syntax: 
https://gist.github.com/hollyschilling/f590f3a1e488732eea5b0d8014702276
This RFC adds a basic extensions using this syntax:
```

extension \DateTimeImmutable {
public function isWeekend(): bool {
return in_array((int)$this->format('N'), [6, 7], true);
}
}


var_dump((new DateTimeImmutable('2026-07-11'))->isWeekend()); // bool(true)

```

2. Scalar Method Extensions: 
https://gist.github.com/hollyschilling/1d247189b8bf45fe044bfbe7fb07dcdb
Allow extensions to be applied to scalars, like strings and ints. This has a 
lot of code changes to make this work and the blast radius is huge. That’s why 
it’s a separate component.
```

extension string {
public function length(): int { return strlen($this); }
}

var_dump("hello"->length());   // int(5)

```

3. Extension Visibility and Importing: 
https://gist.github.com/hollyschilling/dc97ea217302de2f4c9ad7d527aaa65b
This adds rules and syntax to be able to import an extension without using 
`require_once` (or similar).

First, the autoloader needs extensions to have a name, so we give them a name 
when declared.
```


// vendor/acme/dom-kit/src/traversal.php
namespace Acme\DomKit;

extension DomTraversal on \DOMElement {
public function firstByClass(string $class): ?\DOMElement { /* ... */ }
}

```


Then, as we want to use our declared extensions, we import them with a `use`, 
similar to normal classes.

```

use extension Acme\DomKit\DomTraversal;

$el->firstByClass('hero');   // resolves here

```


I believe I’ve proven out the concept and viability of it in a 2-phase approach 
using an extension syntax similar to that of Swift.

Before I go into much more detail, what is the general interest in adding this 
to the language?

reading the thread, I feel both swift and you aim to the same goal, some parts 
use different approaches but as I am not a user of swift, it may be nicer if 
you could work together,  if desired?

Extension methods allow adding functions to existing classes. As a future 
consideration, they can also be used to add readonly virtual properties (No 
setter; No storage). This is purely syntactic sugar, but it can be extremely 
helpful making code easier to read and increasing code reuse. Think of it as a 
Trait that you apply to someone else’s code after the fact.

It is also possible to apply an extension to an Interface. While it cannot be 
used to implement members of the interface, it can make all classes 
implementing that interface have useful methods.

The other useful feature is that a class may implement its own version of a 
function and the function resolution will go to the class’s implementation as 
you might expect.

I hope this helps. The 3 links go to the Gists for each phase and a link from 
each Gist goes to the implementation for each.

I’m happy to answer any additional questions you or anyone else has as you read 
through the docs.

Holly


Re: [PHP-DEV] Class Extension

2026-07-09 Thread Pierre Joye
hello,


On Wed, Jul 8, 2026, 12:11 PM Holly Schilling 
wrote:

> Following the discussion in Discord yesterday, I started working on the
> feasibility of implementing class extensions.
>

For one, I read only internals and github.  I keep seeing "we talked on
discord" but there is no reference whatsoever to a php.net's discord
anywhere i searched for.

so maybe I would suggest to be a tat bit more descriptive first here too?

I believe I’ve proven out the concept and viability of it in a 2-phase
> approach using an extension syntax similar to that of Swift.
>
> Before I go into much more detail, what is the general interest in adding
> this to the language?
>

reading the thread, I feel both swift and you aim to the same goal, some
parts use different approaches but as I am not a user of swift, it may be
nicer if you could work together,  if desired?

best,
--
Pierre

@pierrejoye

>


Re: [PHP-DEV] Class Extension

2026-07-09 Thread Rowan Tommins [IMSoP]
On 8 July 2026 17:27:02 BST, Holly Schilling  
wrote:
> You can see my example with \DateTimeImmutable I sent earlier for an example.

Hi Holly, 

I can't see the message you're referring to here, did it fail to reach the 
list? 

Also, there doesn't seem to be any formatting in your reply to show which parts 
you're quoting and which you're adding. In my mail client, and in some 
archives, it doesn't seem to be attached to the thread properly either. For 
example see https://externals.io/message/131819 ( compare the rest of the 
thread: https://externals.io/message/131805 )

I'm not sure what program you're sending from, but maybe there's some settings 
you can tweak? 

Regards,

Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Class Extension

2026-07-08 Thread Holly Schilling

I like how extensions in Swift allow to organise code!

If we ignore implementation details and ownership it's pretty similar to what 
we have with traits. In PHP, what would be the benefit of extensions over 
traits? One thing that comes to my mind is that traits can be used by whatever 
chooses to add it (back to ownership). Good one, but what else? If ownership is 
the only concern then maybe a small addition to traits could achieve the same?


```
trait Foo
{
for Baz\Bar::class;  // inverse of "use" to limit usage
}

class Bar
{
use Foo;
}
```

Brings conflict resolution for free; and I think it would be cheaper than yet 
another class-like thing. Maybe also feels more php-ish since we already have 
the trait concept?


Thanks for the feedback, Nick.

An extension is essentially the reverse of a trait. With a trait, the trait use 
is declared within the class definition and all users of the class get those 
methods. With an extension, they are generally NOT declared by the one who 
defines the class. They are instead declared by the user of the class. They are 
purely syntactic sugar, but they are very nice to have. You can see my example 
with \DateTimeImmutable I sent earlier for an example.

It’s a feature for what I’ve called Phase 2, but scoping the extensions is 
where they become powerful. An extension can provide functionality similar to a 
default implementation on Interface, although the method cannot be a required 
member on the interface.

Holly


Re: [PHP-DEV] Class Extension

2026-07-08 Thread Nick Sdot

Hey Holly,

On 08.07.26 12:08, Holly Schilling wrote:
Following the discussion in Discord yesterday, I started working on 
the feasibility of implementing class extensions. I believe I’ve 
proven out the concept and viability of it in a 2-phase approach using 
an extension syntax similar to that of Swift.


Before I go into much more detail, what is the general interest in 
adding this to the language?



I like how extensions in Swift allow to organise code!

If we ignore implementation details and ownership it's pretty similar to 
what we have with traits. In PHP, what would be the benefit of 
extensions over traits? One thing that comes to my mind is that traits 
can be used by whatever chooses to add it (back to ownership). Good one, 
but what else? If ownership is the only concern then maybe a small 
addition to traits could achieve the same?


```
trait Foo
{
    for Baz\Bar::class;  // inverse of "use" to limit usage
}

class Bar
{
    use Foo;
}
```

Brings conflict resolution for free; and I think it would be cheaper 
than yet another class-like thing. Maybe also feels more php-ish since 
we already have the trait concept?


Before I go into much more detail, what is the general interest in 
adding this to the language? 


Interested in some sort of solution!

--

Cheers
Nick


Re: [PHP-DEV] Class Extension

2026-07-08 Thread John Bafford



> On Jul 8, 2026, at 14:07, Michael Morris  wrote:
> 
> 
> On Wed, Jul 8, 2026 at 1:08 AM Holly Schilling 
>  wrote:
> Following the discussion in Discord yesterday, I started working on the 
> feasibility of implementing class extensions. I believe I’ve proven out the 
> concept and viability of it in a 2-phase approach using an extension syntax 
> similar to that of Swift. 
> 
> Before I go into much more detail, what is the general interest in adding 
> this to the language? 
> 
> We have inheritance (extends keyword, parent / child classes)
> We have traits (an implementation of multiple classes taken from Ruby)
> 
> Looking at Swift's extension syntax I fail to see anything it adds not 
> covered by the above.


Traits and extensions approach a similar problem from the opposite direction. 
Where a class uses a trait to add functionality, instead, an extension declares 
that it has added functionality to a class (or interface).

Besides allowing one avenue for default implementations for interface methods, 
extensions would also allow for polyfills for class methods and properties that 
can be hooked. For example, PHP 8.5 adds the (sadly not documented yet!) 
`Dom\Element::getElementsByClassName()` and `Dom\Element::insertAdjacentHTML()` 
methods. If PHP 8.4 already had extensions, then extensions would have made it 
possible for a userspace library to provide an implementation for those methods 
on PHP 8.4.

In the hypothetical case where we have method calls on scalar types, extensions 
could also be used as a means of adding methods to those types (either in 
userspace, or internally or in php extensions).

-John


Re: [PHP-DEV] Class Extension

2026-07-08 Thread Alex Rock

Le 08/07/2026 à 14:07, Michael Morris a écrit :


On Wed, Jul 8, 2026 at 1:08 AM Holly Schilling 
 wrote:


Following the discussion in Discord yesterday, I started working
on the feasibility of implementing class extensions. I believe
I’ve proven out the concept and viability of it in a 2-phase
approach using an extension syntax similar to that of Swift.

Before I go into much more detail, what is the general interest in
adding this to the language?


We have inheritance (extends keyword, parent / child classes)
We have traits (an implementation of multiple classes taken from Ruby)

Looking at Swift's extension syntax I fail to see anything it adds not 
covered by the above.



I think that Swift's extension system goes the other way round: the 
class itself doesn't declare its extensions, but they are declared from 
userland.


It's similar to how Rust's traits system can allow extending other types 
(though there's kind of a safeguard to avoid extending nonsense) , you 
can check it there: https://doc.rust-lang.org/book/ch10-02-traits.html



PHP with inheritance goes this way:

- Declare Class A
  - Class A internally defines which class it inherits from
  - Class A internally defines which traits it uses
- Everything is now defined for Class A and its structure is finite as 
of the end of its declaration



With an "extension" system, it might go this way:

- Declare Class A
  - Class A internally defines which class it inherits from
  - Class A internally defines which traits it uses
- Class A is defined, but extensions can update it somehow.
- An extension is later declared for Class A: it can customize the inner 
structure of Class A, like new traits or implemented interfaces
- Maybe (depending on how the RFC goes) other extensions can be declared 
later, in order to customize other things.



Conceptually, I'm not against it, but just like Michael said: I can't 
find use-cases that would be better than what we actually have. 
Extending a class "from the outside", whatever the way to do it, implies 
that a new safeguard has to be added. We could use the "final" keyword, 
but "final" is not at all the same thing as "no extension allowed": a 
class could be declared as not-final while still disallowing 
extensibility from the outside. That's the case when you have a 
non-final class but some of its methods are "final". Disallowing 
extensibility would require an entirely new keyword for that, and it 
adds another burden to code maintainers, especially if extensibility is 
opt-out.



So, IMO, such RFC should contain this:

- Thorough examples of the actual problems it solves for package 
maintainers and application developers
- Clear views on how extensibility impacts the current ecosystem (I 
guess it shouldn't have any impact on Composer and the autoloading 
system, because if it's similar to Swift, an extension should just 
behave like a class in terms of autoload, but I might have not thought 
about it completely)
- Extensibility must be either opt-in by design, or opt-out by design, 
but the decision must be made **after** having analysed the impact on 
the ecosystem. I can't imagine extensibility being opt-out and people 
starting to wildly override frameworks core classes. (yeah, I'm talking 
about some Laravel nerds that tend to bend and break fast (pun intended))
- Extension points must be defined on both the extender and the extended 
structures. Like, for example, making sure it's impossible to extend 
something that's "final" by default, but making a non-final structure 
being non-extensible should also be possible. That's part of the concept 
of encapsulation in general, but it also respects the Open/Close 
principle (from SOLID) and several other programming practices that make 
sure we don't do bullcrap in all codebases. And trust me, PHP is already 
full of bullcrap, so adding more isn't a good idea at all. PHP hasn't 
become "more and more strict" over time for nothing... and still, that 
strictness is opt-in (by the eyes of PHP, not from framework 
maintainers, which can be seriously opinionated).



Hope this helps :)


Re: [PHP-DEV] Class Extension

2026-07-08 Thread Rowan Tommins [IMSoP]
On 8 July 2026 06:08:42 BST, Holly Schilling  
wrote:
>Following the discussion in Discord yesterday, I started working on the 
>feasibility of implementing class extensions. I believe I’ve proven out the 
>concept and viability of it in a 2-phase approach using an extension syntax 
>similar to that of Swift.
>
>Before I go into much more detail, what is the general interest in adding this 
>to the language?


Hi Holly, 

Can you give a brief summary of what the feature is, and how it would apply to 
PHP, for those of us who aren't familiar with Swift, and haven't seen the 
Discord discussion?

Thanks,

Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Class Extension

2026-07-08 Thread Michael Morris
On Wed, Jul 8, 2026 at 1:08 AM Holly Schilling <
[email protected]> wrote:

> Following the discussion in Discord yesterday, I started working on the
> feasibility of implementing class extensions. I believe I’ve proven out the
> concept and viability of it in a 2-phase approach using an extension syntax
> similar to that of Swift.
>
> Before I go into much more detail, what is the general interest in adding
> this to the language?
>

We have inheritance (extends keyword, parent / child classes)
We have traits (an implementation of multiple classes taken from Ruby)

Looking at Swift's extension syntax I fail to see anything it adds not
covered by the above.