Re: RFC Proposal : Allows calling non-static public methods through the __callStatic magic method instead of throwing an error.

From: Date: Sat, 17 Feb 2024 21:26:44 +0000
Subject: Re: RFC Proposal : Allows calling non-static public methods through the __callStatic magic method instead of throwing an error.
References: 1 2  Groups: php.internals 
Request: Send a blank email to internals+get-122416@lists.php.net to get a copy of this message
> Le 17 févr. 2024 à 16:51, Larry Garfield <larry@garfieldtech.com> a écrit : > > On Fri, Feb 16, 2024, at 7:56 PM, 하늘아부지 wrote: >> 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. > > 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

« previous php.internals (#122416) next »