Hi.
I'd like to propose an RFC, but I don't have the authority.
Below is my suggestion.
If you think this makes sense, please write an RFC for me.
Sincerely.
===== Introduction =====
Allows calling non-static public methods through the __callStatic magic
method instead of throwing an error.
===== Proposal =====
From a conceptual perspective:
It goes without saying that calling a non-static method statically will
result in an error.
However, a confusing situation occurred when the __callStatic magic method
exists.
Non-public methods can be called, but public methods cannot.
This is the opposite of the method visibility policy.
From a practical point of view:
If you can call Non-static public methods through the __callStatic magic
method, you can write code like Laravel ORM more simply and tidy.
==== Before ====
<code> class Foo { protected static ?Foo $instance = null;public static function __callStatic($method, $args)
{
$instance = self::$instance ?? self::$instance = new static();
return $instance->__call($method, $args);
}
public function __call($method, $args)
{
if (method_exists($this, $method)) {
return $instance->$method(...$args);
}
return $this;
}
protected function bar()
{
echo __METHOD__ . '<br />';
return $this;
}
protected function baz()
{
echo __METHOD__ . '<br />';
return $this;
}
}
Foo::bar()->baz();
(new Foo())->bar()->baz();
</code>
There is no error, but the concept of method visibility is broken.
All Non-public methods can be called at instance scope.
==== After ====
<code> class Foo { protected static ?Foo $instance = null;public static function __callStatic($method, $args)
{
$instance = self::$instance ?? self::$instance = new static();
if (method_exists($instance, $method)) {
return $instance->$method(...$args);
}
return $instance;
}
public function bar()
{
echo __METHOD__ . '<br />';
return $this;
}
public function baz()
{
echo __METHOD__ . '<br />';
return $this;
}
}
Foo::bar()->baz();
(new Foo())->bar()->baz();
</code>
This is more tidy.
Only public methods are callable at instance scope.
Hi.
I'd like to propose an RFC, but I don't have the authority.
Below is my suggestion.
If you think this makes sense, please write an RFC for me.
Sincerely.
===== Introduction =====
Allows calling non-static public methods through the __callStatic magic
method instead of throwing an error.===== Proposal =====
From a conceptual perspective:
It goes without saying that calling a non-static method statically will
result in an error.
However, a confusing situation occurred when the __callStatic magic
method exists.
Non-public methods can be called, but public methods cannot.
This is the opposite of the method visibility policy.From a practical point of view:
<code> User::foo()->bar(); </code>
If you can call Non-static public methods through the __callStatic
magic method, you can write code like Laravel ORM more simply and tidy.==== Before ====
<code> class Foo { protected static ?Foo $instance = null;public static function __callStatic($method, $args) { $instance = self::$instance ?? self::$instance = new static(); return $instance->__call($method, $args); } public function __call($method, $args) { if (method_exists($this, $method)) { return $instance->$method(...$args); } return $this; } protected function bar() { echo __METHOD__ . '<br />'; return $this; } protected function baz() { echo __METHOD__ . '<br />'; return $this; }
}
Foo::bar()->baz();
(new Foo())->bar()->baz();
</code>There is no error, but the concept of method visibility is broken.
All Non-public methods can be called at instance scope.==== After ====
<code> class Foo { protected static ?Foo $instance = null;public static function __callStatic($method, $args) { $instance = self::$instance ?? self::$instance = new static(); if (method_exists($instance, $method)) { return $instance->$method(...$args); } return $instance; } public function bar() { echo __METHOD__ . '<br />'; return $this; } public function baz() { echo __METHOD__ . '<br />'; return $this; }
}
Foo::bar()->baz();
(new Foo())->bar()->baz();
</code>This is more tidy.
Only public methods are callable at instance scope.
That calling bar() works at all in this example is rather accidental. The whole point of a non-static method is that it has an implicit required $this argument to it. Without a required argument, a method cannot be called, because it is supposed to fail.
In fact, even your "before" example fails: https://3v4l.org/moH0s
I don't think what you describe is even possible, nor would it be a good idea.
See also: https://peakd.com/hive-168588/@crell/cutting-through-the-static
--Larry Garfield
Le 17 févr. 2024 à 16:51, Larry Garfield larry@garfieldtech.com a écrit :
Hi.
I'd like to propose an RFC, but I don't have the authority.
Below is my suggestion.
If you think this makes sense, please write an RFC for me.
Sincerely.
===== Introduction =====
Allows calling non-static public methods through the __callStatic magic
method instead of throwing an error.===== Proposal =====
From a conceptual perspective:
It goes without saying that calling a non-static method statically will
result in an error.
However, a confusing situation occurred when the __callStatic magic
method exists.
Non-public methods can be called, but public methods cannot.
This is the opposite of the method visibility policy.From a practical point of view:
<code> User::foo()->bar(); </code>
If you can call Non-static public methods through the __callStatic
magic method, you can write code like Laravel ORM more simply and tidy.==== Before ====
<code> class Foo { protected static ?Foo $instance = null;public static function __callStatic($method, $args)
{
$instance = self::$instance ?? self::$instance = new static();
return $instance->__call($method, $args);
}public function __call($method, $args)
{
if (method_exists($this, $method)) {
return $instance->$method(...$args);
}return $this;
}
protected function bar()
{
echo METHOD . '<br />';return $this;
}
protected function baz()
{
echo METHOD . '<br />';return $this;
}
}Foo::bar()->baz();
(new Foo())->bar()->baz();
</code>There is no error, but the concept of method visibility is broken.
All Non-public methods can be called at instance scope.==== After ====
<code> class Foo { protected static ?Foo $instance = null;public static function __callStatic($method, $args)
{
$instance = self::$instance ?? self::$instance = new static();if (method_exists($instance, $method)) { return $instance->$method(...$args); } return $instance;
}
public function bar()
{
echo METHOD . '<br />';return $this;
}
public function baz()
{
echo METHOD . '<br />';return $this;
}
}Foo::bar()->baz();
(new Foo())->bar()->baz();
</code>This is more tidy.
Only public methods are callable at instance scope.That calling bar() works at all in this example is rather accidental. The whole point of a non-static method is that it has an implicit required $this argument to it. Without a required argument, a method cannot be called, because it is supposed to fail.
In fact, even your "before" example fails: https://3v4l.org/moH0s
It does work after having corrected the obvious bug in the bar()
method.
I don't think what you describe is even possible, nor would it be a good idea.
Why wouldn’t it possible? Couldn’t the engine invoke __callStatic() instead of complaining that the targeted method is not static? (I don’t have opinion on whether it is a good idea, though)
—Claude
For the reference to the others: https://3v4l.org/UmPVo
Kind regards,
Jorg