PHP está manejando incorrectamente mi llamada estática
class methods (5)
Esto es probablemente debido a la notación estándar de llamar a los métodos principales, independientemente del estado. Usted podría verificar si $this
palabra clave está establecida en el método __call
y si no, haga una llamada a __callStatic
?
EDITAR: Esto no es un error per se, la llamada estática se realiza desde un contexto de objeto. Eche un vistazo a este hilo de error en php .
Tengo un problema en PHP 5.3. Necesito llamar a un método usando __callStatic
, pero si lo uso en un objeto instancied, PHP llama a __call
en __call
lugar.
Por encima de un ejemplo de la vida real:
<?php
class A {
function __call($method, $args){
// Note: $this is defined!
echo "Ops! Don''t works. {$this->c}";
}
static function __callStatic($method, $args){
echo ''Fine!'';
}
}
class B extends A {
public $c = ''Real Ops!'';
function useCallStatic(){
static::foo();
// === A::foo();
// === B::foo();
}
}
$foo = new B();
$foo->useCallStatic();
// This works:
// B::foo();
?>
Grabados : ¡Ops! No funciona Real Ops!
Tenga en cuenta que llamo useCallStatic
desde un new B()
. Si llamo directamente funciona bien como B::foo()
.
¿Qué puedo hacer para que funcione bien?
La herencia de métodos estáticos es un poco raro en PHP. Sospecho que debes redefinir __callStatic
en B
Después de pensarlo, no es realmente un error. Pero definitivamente no es intuitivo.
<?php
class A
{
public function foo()
{
static::bar();
}
public function bar()
{
echo "bar()/n";
}
}
$a = new A();
$a->foo();
Esto es válido y llama a bar (). No significa barra de llamada estáticamente. Significa buscar el nombre de clase actual y la bar
función de llamada bar
si existe, ya sea que se trate de una función estática o no.
Para aclarar un poco más: ¿crees que parent::bar()
significa llamar a una función estática llamada bar()
? No, significa que llamar a cualquier función se llama bar()
.
Considerar:
<?php
class A
{
function __call($name, $args)
{
echo "__call()/n";
}
static function __callStatic($name, $ags)
{
echo "__callStatic()/n";
}
function regularMethod()
{
echo "regularMethod()/n";
}
static function staticMethod()
{
echo "staticMethod()/n";
}
}
class B extends A
{
function foo()
{
parent::nonExistant();
static::nonExistant();
parent::regularMethod();
parent::staticMethod();
}
}
$b = new B();
$b->foo();
El método parent::nonExistant()
invoca A::__call()
, al igual que static::nonExistant()
. Invocar A::__callStatic()
para cualquiera de las llamadas sería igual de válido. No hay forma de que PHP sepa a cuál te quieres llamar. Sin embargo, por diseño, PHP le da a __call
la prioridad cuando se invoca desde este tipo de contexto.
parent::regularMethod()
invoca la función no estática regularMethod()
. (De nuevo, el operador ::
no significa "llamar a esta función estática"). Asimismo, parent::staticMethod()
invoca A::staticMethod()
como uno podría esperar.
Para resolver su problema:
Puede llamar manualmente a self::__callStatic(''foo'')
en la clase heredada.
O dentro del método __call
del filtro clase A contra una lista conocida y llame a self::__callStatic
.
function __call($f, $a)
{
if ($f == ''foo'')
return self::__callStatic($f, $a);
else
{
}
}
Es feo, pero al menos las personas que extienden la clase no necesitarán hacer nada especial.
Primero, asegúrese de estar usando PHP 5.3.0 o posterior, ya que es cuando se implementó __callStatic. Todo parece funcionar como se esperaba, ver este ejemplo:
<?php
class A {
public function __call($method, $args) {
echo ''A::__call, '' .
var_export(array($method, $args), true), PHP_EOL;
}
/** As of PHP 5.3.0 */
public static function __callStatic($method, $args) {
echo ''A::__callStatic, '' .
var_export(array($method, $args), true), PHP_EOL;
}
}
$a = new A;
$a->foo(''abc'');
A::bar(''123'');
class B extends A {
function invokeStatic($args) {
echo ''B::invokeStatic'', PHP_EOL;
self::someStatic($args);
}
}
$b = new B;
$b->invokeStatic(''456'');
?>
La salida debe ser (o al menos, es para mí):
A::__call, array (
0 => ''foo'',
1 =>
array (
0 => ''abc'',
),
)
A::__callStatic, array (
0 => ''bar'',
1 =>
array (
0 => ''123'',
),
)
B::invokeStatic
A::__callStatic, array (
0 => ''someStatic'',
1 =>
array (
0 => ''456'',
),
)
Cuando ejecuto su ejemplo anterior, me sale "¡Bien!" como el único resultado, que es exactamente lo que habría esperado.
¿Exactamente qué versión de PHP estás ejecutando? Puedes verificar con esto:
$ php -r ''echo phpversion(), PHP_EOL;''
5.3.3-7+squeeze1
Buenas noticias
Hago un gran trabajo alrededor, pero funciona bastante bien. Este es el código:
class NoContext {
public static function call($callback, $args = null){
return call_user_func_array($callback, $args ?: array());
}
}
NoContext::call
llamar a NoContext::call
(estáticamente) como si llamara call_user_func
o similar. Eliminará el $this
contexto. Todavía creo que es un error de PHP, pero ...
Para resolver mi problema, lo hago:
class B extends A {
function useCallStatic(){
NoContext::call(''A::foo'');
}
}
Y se imprimirá: Fine!
.
Gracias a todos los que me ayudan. Realmente aprendo demasiado con tus respuestas y espero que mis consejos sean útiles para ti alguna vez.