Hello, Internals!
I’ve implemented an alpha implementation of the Extension Functions in PHP.
Basically, it’s a syntax sugar of the imperative call of the function with the passing the object as a first argument, but anyway.
Here is how it looks like in Kotlin: https://kotlinlang.org/docs/extensions.html
In PHP it might looks like so:
function stdClass.getName() {
return $this->name;
}
$obj = new stdClass;
$obj->name = ‘Dmitrii’;
echo $obj->getName(); // prints Dmitrii
so desugared version is:
function getName(stdClass $obj) {
return $obj->name;
}
$obj = new stdClass;
$obj->name = ‘Dmitrii’;
echo getName($obj); // prints Dmitrii
Quite simple improvement, but a really convenient way to “attach” behaviour and extend vendor code to make it more readable.
Functions register as usual, using use
keyword. So there are no surprises when you call a function which does not exist, only an implicit way to specify the function.
“Attaching” the function with the name of an existing member function raises an exception.
But you may juggle different functions from different namespaces:
namespace A;
use function aa; // from global namespace
OR
use function B\aa; // from B namespace
OR
use function B\aa as Baa; // from B namespace with alias
use function
construction may be enlarged with the “extension” keyword:
use function getTime; // regular function
use extension function getTime; // extension function, unable to call without correct receiver
As in Kotlin, it should access only public members.
class A { private $name; }
function A.getName() {
return $this->name; // raises an exception because private and protected members aren’t available
}
Supporting types DNF is under question, but I’d leave them as future scope.
function ((A&B)|null).smth() { … }
but it could be resolved to
function smth((A&B)|null $obj) { … }
The dot as a delimiter is also under the question, here are a few options:
function stdClass::getName();
function stdClass->getName();
function stdClass.getName();
function ::stdClass getName();
function stdClass<-getName();
function getName of stdClass();
etc.
I’ve tried to implement the feature through attaching a function to the class functions scope, which is wrong and does not follow the requirements. It has memory leaks.
https://github.com/php/php-src/compare/master…xepozz:php-src:extension-functions?expand=1#diff-1dd36b02e5025ec3a5a546f8e41374ee4fc18c411bce447dd1dc2952329ccbe6R25
I also thought about adding this feature as a custom attribute behaviour, but it’s a way difficult:
#[Extension(“stdClass”)]
function hasName(): bool {
return $this->name;
}
I can try to implement the de-sugared version to make it work correctly.
···
Best regards,
Dmitrii Derepko.
@xepozz