2010-01-21 10 views
11

tengo que comprobar si existeuna instancia de class_A, y si hay sí existe, obtener esa instancia.¿Cómo obtener instancia de una clase específica en PHP?

¿Cómo hacerlo en PHP?

Como siempre, creo que un ejemplo simple es el mejor.

Ahora mi problema se ha convertido en:

$ins = new class_A(); 

Cómo almacenar la instancia en una variable miembro estática de class_A cuando instanciar?

Será mejor si la instancia se puede almacenar al llamar al __construct(). Diga, debería funcionar sin limitaciones en la forma en que se crea una instancia.

+1

No hay una forma mágica de encontrar un objeto, conociendo solo su clase. Tendrás que poner tu instancia en algún lugar donde puedas encontrarla más tarde. –

+1

Con al menos ocho respuestas y Singleton, Registry y instanceof, etc. todos mencionados, es posible que desee ser más preciso acerca de lo que está tratando de hacer. – Gordon

Respuesta

27

Lo que ha descrito es esencialmente el patrón singleton. Por favor, see this question por buenas razones por las que es posible que no desee hacer esto.

Si realmente quiere hacerlo, se podría implementar algo como esto:

class a { 
    public static $instance; 
    public function __construct() { 
     self::$instance = $this; 
    } 

    public static function get() { 
     if (self::$instance === null) { 
      self::$instance = new self(); 
     } 
     return self::$instance; 
    } 
} 

$a = a::get(); 
+0

¡Oh, está funcionando! +1 – user198729

+1

$ este es el objeto actual. self es la clase actual, que se usa para acceder a los miembros estáticos. –

+1

¿Para qué sirve UseCase? – Gordon

4
+0

Si class_A es una clase sobre la cual el usuario no tiene control, el patrón singleton puede ser imposible de aplicar. – Dathan

+0

class_A no tiene que convertirse en el singleton. Puede crear una clase_B que contenga una sola clase_A. –

+0

Eso funciona si el usuario va a ser responsable de la instanciación de class_A, y puede asegurarse de que se hace a través de class_B. ¿Qué pasa si la instancia de class_A es generada por algún otro código que ignora class_B? – Dathan

1

Para ampliar la respuesta Pikrass, que, básicamente, tendrá que hacer algo como esto:

class class_A { 
    private static $instance = false; 

    public static function getInstance() { 
    if (!self::$instance) { 
     self::$instance = new class_A(); 
    } 

    return self::$instance; 
    } 

    // actual class implementation goes here 
} 


// where you need to use the instance: 
$mySingleton = class_A::getInstance(); 
// do something with $mySingleton 
+0

Necesito ** obtener ** instancia existente, no ** crear ** – user198729

2

El patrón Singleton, con un PHP example from Wikipedia que yo' he añadido un método "checkExists" para que parezca que desea verificar la existencia de la clase sin crearla necesariamente si no sale:

final class Singleton 
{ 
    protected static $_instance; 

    protected function __construct() # we don't permit an explicit call of the constructor! (like $v = new Singleton()) 
    { } 

    protected function __clone() # we don't permit cloning the singleton (like $x = clone $v) 
    { } 

    public static function getInstance() 
    { 
     if(self::$_instance === NULL) { 
     self::$_instance = new self(); 
     } 
     return self::$_instance; 
    } 

    public static function checkExists() 
    { 
     return self::$_instance; 
    } 
} 

if(Singleton::checkExists()) 
    $instance = Singleton::getInstance(); 
+0

No veo cómo 'Singleton :: getInstance()' devolverá una instancia ** existente **. No hay operación activada ' self :: $ _ instance' en '__construct()' – user198729

+0

He creado la instancia de esta manera en alguna parte: '$ ins = new class_A()', así que necesito 'Singleton :: getInstance()' para trabajar en este caso – user198729

+0

¿Por qué no puedes cambiar $ ins = new class_A(); a $ ins = Singleton :: getInstance()? –

3

Tal vez usted quiere algo así como

for (get_defined_vars() as $key=>$value) 
{ 
    if ($value instanceof class_A) 
    return $value; 
} 

EDIT: Tras la lectura adicional, usted tiene que saltar a través de algunos aros para obtener referencias a objetos. Por lo tanto, es posible que desee return $$key; en lugar de return $value;. O algunos otros trucos para obtener una referencia al objeto.

+0

Sí, eso es lo que quiero, pero también me importa el rendimiento – user198729

+2

Esto es exactamente lo que solicitó el OP, solo espero que no se vote negativamente por este. –

+0

@unknown (google): No hay una solución mágica para eso ... Y puede empeorar si quieres que maneje la recursividad (objetos dentro de arreglos multidimensionales). –

0

Recuerde que al usar un singleton, básicamente está creando un gran global variable. Si tiene estado que cambia, su código puede volverse impredecible. Entonces, ten cuidado.

7

Lo que usted pide es imposible (Bueno, quizás no en un sentido técnico, pero muy poco práctico). Sugiere que tiene un malentendido más profundo sobre el propósito de los objetos y las clases.

+7

+1 - Creo que has golpeado el clavo en la cabeza. –

+2

Este es un caso de uso común para el patrón Singleton, que de hecho es posible implementar en PHP. – feeela

0

Si la sustitución de la Instrucion de instancias singleton en sus archivos es un problema que puede convertirse en un comportamiento constante impulsado: las constantes son tales para toda la duración de la secuencia de comandos, por lo que en el caso de una instancia cuyo requisito sea único (para toda la duración de la secuencia de comandos), el método de construcción puede vincularse adecuadamente con la existencia/valor de una constante.

 
class superObject { 
    public function __construct() { 
     if (defined('SUPER_OBJECT')) { 
      trigger_error('Super object '.__CLASS__.' already instantiated', E_USER_ERROR); 
        // ...or just do whatever you want to do in case of instances overlap 
     } else { 
      define('SUPER_OBJECT', true); 
     } 
    // the rest of your construct method 
    // ... 
    } 
} 
0

El código de abajo tiene una calidad que promueve la eficiencia de almacenamiento en caché:

class Object { 

    public $instance_variable; 
    public $last_added_global_variable; 

    public function __construct(){ 
    //we are saving the global variable before this one so that 
    //we can be confident that we will always get the correct value 
    $this->last_added_global_variable = $this->get_last_variable_added()[count($array_of_global_variables)-1]; 
    } 

    //runs everytime a function is called in this class 
    public function __call(){ 
    //remember, this is skipped whenever the variable name is saved 
    if(!$this->instance_variable){ 
     for($i=0; $i=count($this->get_last_variable_added()); $i++){ 
     if($this->last_added_global_variable == get_last_variable_added()[$i]){ 
      $this->instance_variable = get_last_variable_added()[$i+1]; 
     } 
     } 
    } 
    } 

    private function get_last_variable_added(){ 
    $array_of_global_variables = array(); 

    foreach($GLOBALS as $g=>$v){ 
     array_push($array_of_global_variables, $g); 
    } 

    //return last added global variable 
    return $array_of_global_variables; 
    } 

} 

Aunque aparece costosa, es insignificante.

Puede notar que encontrar la última variable añadida a través de un bucle de variable global es imposible mientras todavía está en la función de construcción.

Cuestiones relacionadas