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
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
Le 28 mars 2024 à 03:29, 하늘아부지 daddyofsky@gmail.com a écrit :
Hi.
I would like to register an RFC on the following issue.
https://github.com/php/php-src/issues/13813To 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 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:
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
:
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
Le jeudi 28 mars 2024 à 10:40, Claude Pache claude.pache@gmail.com a écrit :
Le 28 mars 2024 à 03:29, 하늘아부지 daddyofsky@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 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:
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 methodqux()
and$this
is an instance ofA
:
class Foo { function baz() { A::qux(); } }
(In older versions of PHP, a non-static call would occur even when
$this
is not an instance ofA
. 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
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
2024년 3월 28일 (목) 오후 6:33, Stéphane Hulard s.hulard@chstudio.fr님이 작성:
Le jeudi 28 mars 2024 à 10:40, Claude Pache claude.pache@gmail.com a
écrit :Le 28 mars 2024 à 03:29, 하늘아부지 daddyofsky@gmail.com a écrit :
Hi.
I would like to register an RFC on the following issue.
https://github.com/php/php-src/issues/13813To 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 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:
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 methodqux()
and$this
is an
instance ofA
:class Foo { function baz() { A::qux(); } }
(In older versions of PHP, a non-static call would occur even when
$this
is not an instance ofA
. 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 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