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.
<code>
User::foo()->bar();
</code>
==== 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.