2024년 3월 28일 (목) 오후 6:33, Stéphane Hulard <s.hul...@chstudio.fr>님이 작성:
> Le jeudi 28 mars 2024 à 10:40, Claude Pache <claude.pa...@gmail.com> a > écrit : > > > > > > > > > > Le 28 mars 2024 à 03:29, 하늘아부지 <daddyof...@gmail.com> a écrit : > > > > > > > > > > > Hi. > > > > > > > I would like to register an RFC on the following issue. > > > https://github.com/php/php-src/issues/13813 > > > > > > > To summarize briefly, users expect that the `__callStatic` magic > method will be called in all cases when a method is not static while using > the `__callStatic`. However, in reality, if the method is public, the > `__callStatic` magic method is not called, and an error still occurs. > > > > > > > I would like to hear your opinions. > > > I also hope someone can help with the RFC registration. > > > > > > > > > > > -------------------------------------------------------- > > > > > > > ```php > > > <?php > > > class MyClass > > > { > > > public static function __callStatic($method, $args) > > > { > > > echo $method . "\n"; > > > } > > > > > > > private function privateMethod() {} > > > protected function protectedMethod() {} > > > public function publicMethod() {} > > > } > > > > > > > MyClass::privateMethod(); > > > MyClass::protectedMethod(); > > > MyClass::publicMethod(); > > > ``` > > > > > > > Resulted in this output: > > > ``` > > > privateMethod > > > protectedMethod > > > Fatal error: Uncaught Error: Non-static method MyClass::publicMethod() > cannot be called statically in ... > > > ``` > > > > > > > But I expected this output instead: > > > ``` > > > privateMethod > > > protectedMethod > > > publicMethod > > > ``` > > > > > > > > > > > > > > > > Hi, > > One of the issue is that it is not possible to determine statically that > a certain call is static or not. It is possible to determine it at runtime; > but you must be careful to articulate clearly the rules. Although it is > absolutely possible to have logical rules, I fear that they couldn’t be > sufficiently simple in order to avoid confusion. > > > > > In the following real-world (but hopefully rare) case (it is taken from > my own codebase), I am calling a method of a grandparent class. It is *not* > a static method: > > > > > ```php > > > > > foo = new class(/* ... */) extends Bar { > > > > > // ... > > > > > function Header() { > > $grandparent_class = get_parent_class(parent::class); > > $grandparent_class::Header(); > > // ... rest of code > > } > > > > > // ... > > }; > > ``` > > > > > In the following more general case, I might intend to call to a static > method. However, as of today, a call to a non-static method will occur if > `A` has a non-static accessible method `qux()` *and* `$this` is an > instance of `A`: > > > > > ```php > > class Foo { > > function baz() { > > A::qux(); > > } > > } > > ``` > > > > > (In older versions of PHP, a non-static call would occur even when > `$this` is not an instance of `A`. Hopefully, this is no longer the case > since PHP 8.) > > > > > > > > —Claude > > Hello ! > > In Laravel the static versus non static context is handled inside the > different calls. So a static call on a non static method will be forwarded > to a non static instance to be handled properly. > I don't see any advantages to call `__callStatic` on any method call since > the difference with `__call` is clear. Also, as Claude said, determining > that the call is static or not is not easy. > > Also, building Singleton is possible using the current PHP behavior. An > example : > > ```php > <?php > > class User > { > public function __callStatic($name, $arguments) > { > return (new static)->$name(...$arguments); > } > > public static function __call($name, $arguments) > { > // Here handle the call the $name method. > echo $name; > } > } > > $user = User::find(1); > //Will output > // find > ``` > > That's the way it's done in Laravel. Also note that the find method > doesn't exists in the User object. That's why it works, the method is truly > "magic". > If the method is defined as non static, it'll break with the error given. > > Stéphane > Hi. I tested what Claude pointed out. https://3v4l.org/qb6HH >From the test results and comments by iluuu1994 on GitHub (( https://github.com/php/php-src/issues/13813#issuecomment-2021625413), it seems that visibility is checked first, followed by whether it's static or not. I wonder if swapping these checks might solve the issue, but it seems like this part will have to be left to the experts. I understand what Stéphane pointed out. The part I'm interested in is whether it's possible to use singletons easily without separating the class. __call alone cannot solve this part. For example, in Laravel, methods defined in the DB class can be called through __callStatic in the Model class, but methods defined in the Model class or classes inheriting from the Model class cannot be called using ::. Therefore, scope-related methods must be implemented using a scope prefix. You're using scopeKeyword methods like User::keyword. I think this awkward usage and the grotesque form that arose because __callStatic is not called in the case of all public methods. daddyofsky