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.

Reply via email to