2011-12-05 15 views
80

El PHP manual indica

No es posible utilizar $this de función anónima antes de PHP 5.4.0

en el anonymous functions page. Pero he descubierto que puedo hacerlo funcionar asignando $this a una variable y pasando la variable a una declaración use en la definición de la función.

$CI = $this; 
$callback = function() use ($CI) { 
    $CI->public_method(); 
}; 

¿Es esta una buena práctica?
¿Hay una mejor manera de acceder al $this dentro de una función anónima utilizando PHP 5.3?

+1

sólo una convención foro de menor importancia - por lo general es mejor aceptar una respuesta que al editar una pregunta para reflejar su respuesta preferida. Principalmente esto es para que las respuestas sigan teniendo sentido a perpetuidad, pero también para dar crédito a una respuesta correcta. – halfer

+3

Tenga en cuenta que '$ CI = $ this;' y '$ CI = & $ this;' ** no son ** realmente idénticos. Quizás para tus propósitos, pero no son lo mismo. Pruebe '$ CI = 'bla'; var_dump ($ this); 'con ambas versiones para ver la diferencia. – Rudie

+1

@Rudie Estoy agregando la [documentación] (http://php.net/manual/en/language.oop5.references.php) para su comentario – steampowered

Respuesta

61

Fallará cuando intente llamar a un método privado o protegido, ya que usarlo de esa manera cuenta como llamar desde el exterior. No hay manera de solucionar este problema en 5.3 por lo que yo sé, pero vienen de PHP 5.4, funcionará como se espera, fuera de la caja:

class Hello { 

    private $message = "Hello world\n"; 

    public function createClosure() { 
     return function() { 
      echo $this->message; 
     }; 
    } 

} 
$hello = new Hello(); 
$helloPrinter = $hello->createClosure(); 
$helloPrinter(); // outputs "Hello world" 

Aún más, usted será capaz de cambiar lo $ esto apunta a en tiempo de ejecución, para las funciones anonymus (revinculación de cierre):

class Hello { 

    private $message = "Hello world\n"; 

    public function createClosure() { 
     return function() { 
      echo $this->message; 
     }; 
    } 

} 

class Bye { 

    private $message = "Bye world\n"; 

} 

$hello = new Hello(); 
$helloPrinter = $hello->createClosure(); 

$bye = new Bye(); 
$byePrinter = $helloPrinter->bindTo($bye, $bye); 
$byePrinter(); // outputs "Bye world" 

Efectivamente, las funciones anonymus tendrán un bindTo() method, donde el primer parámetro se puede utilizar para especificar lo que $ this puntos a, y el segundo parámetro controla ¿cuál debería ser el nivel de visibilidad. Si omite el segundo parámetro, la visibilidad será como llamar desde el "exterior", ej. solo se puede acceder a las propiedades públicas. También tome nota de la forma en que funciona bindTo, no modifica la función original, , devuelve una nueva.

+1

Marcando su respuesta correcta, pero solo para aclarar a otros lectores: la convención usado en la pregunta funcionará para métodos públicos que usan el objeto que hace referencia a '$ this'. – steampowered

+5

[Métodos no públicos] (http://stackoverflow.com/a/6386863/90527) se puede acceder utilizando la reflexión. Ineficiente y un poco malvado, pero funciona. – outis

1

Eso parece correcto si pasa por referencia, es la forma correcta de hacerlo. Si usa PHP 5, no necesita el símbolo & antes de $this ya que siempre pasará por referencia independientemente.

+2

El OP debe estar utilizando 5.3 o superior, ya que 4.x no admite funciones anónimas :-) – halfer

1

Esto está bien. Ya lo creo que podría hacer esto también:

$CI = $this; 

... ya que las asignaciones que implican objetos siempre van a copiar las referencias, no objetos enteros.

5

Esa es la manera normal en que se hizo.
b.t.w, intente eliminar el &, debería funcionar sin esto, ya que los objetos pasan por ref de cualquier forma.

5

No siempre confíe en PHP para pasar objetos por referencia, cuando está asignando una referencia, el comportamiento no es el mismo que en la mayoría de los lenguajes OO donde se modifica el puntero original.

tu ejemplo:

$CI = $this; 
$callback = function() use ($CI) { 
$CI->public_method(); 
}; 

debe ser:

$CI = $this; 
$callback = function() use (&$CI) { 
$CI->public_method(); 
}; 

NOTA LA REFERENCIA "&" y $ CI deben ser asignados después de las llamadas finales a que se ha hecho, de nuevo otra cosa que podría tener salida impredecible, en PHP acceder a una referencia no es siempre lo mismo que acceder a la clase original, si eso tiene sentido.

http://php.net/manual/en/language.references.pass.php

Cuestiones relacionadas