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.