Pregunta

Yo estaba trabajando en una clase abstracta para ahorrar algo de código para un par de clases. Estas clases son todas las fábricas que ejemplifican a sí mismos a través de diferentes llamadas estáticas. Podría ahorrar algo de código, poniendo todos esos métodos en una clase abstracta.

Sin embargo, me encontré con un el enlace en tiempo problema ... ya que nuestro proveedor de alojamiento web no está utilizando 5.3 o posterior, no tengo acceso a get_called_class estática. Si tengo

$class = __CLASS__;
return new $class();

en la clase abstracta, __CLASS__ es el nombre de la clase abstracta, cuando en realidad lo quiero utilizar la clase llamada.

He visto ejemplos de fábricas abstractas en la web donde las clases hijas tienen sus propios métodos de instancias, y no se basan en la matriz abstracta para ello. Sin embargo, en esta situación, la única razón de la clase abstracta es salvar código, por lo que si no puedo hacerlo allí, el valor de la misma disminuye en gran medida.

¿Hay una solución alternativa en php <5,3? debug_backtrace()?


Editar

Me hizo una prueba y parece debug_backtrace() no va a funcionar! Creo que es por eso que necesitamos la ligadura estática .

<?

abstract class abstractFactory {
    public function create() {
            print_r(debug_backtrace());
            $class = __CLASS__;
            return new $class();
    }
}

class concreteFactory extends abstractFactory {}

$chimborazo = concreteFactory::create();

y el resultado:

$ php test.php
Array
(
    [0] => Array
        (
            [file] => /var/www/test.php
            [line] => 13
            [function] => create
            [class] => abstractFactory
            [type] => ::
            [args] => Array
                (
                )

        )

)

Fatal error: Cannot instantiate abstract class abstractFactory in /var/www/test.php on line 7
¿Fue útil?

Solución 3

Una vez manera de hacerlo es reemplazar los diversos métodos de instancias, y pasar el nombre de la clase directamente:

<?

abstract class abstractFactory {

    public function create($class) {
        return new $class();
    }

    public function instantiate($class) {
        return new $class();
    }

}

class concreteFactory extends abstractFactory {

    public function create() {
        parent::create(__CLASS__);
    }

    public function instantiate() {
        parent::instantiate(__CLASS__);
    }
}


$chimborazo = concreteFactory::create();
$chimborazo = concreteFactory::instantiate();

Otros consejos

La única solución que he visto para esto implica llamar debug_backtrace para determinar el nombre de la clase de la persona que llama (s). Esto es por supuesto un corte gigante. He visto algo de código que combina una traza con tener que abrir el archivo de llamadas y analizarlo de entender las cosas. Extraño, cosas horribles.

La falta de LSB se va a volver y morder más tarde. Actualiza ahora, incluso si esto significa anfitriones de conmutación. De hecho, especialmente si esto significa conmutación hosts. 5.3 ha estado fuera desde hace un año.

Esto es lo que he estado usando hasta trasladarse a 5.3:

if (!function_exists('get_called_class')) {

   /**
    * Implementation of get_called_class() for pre-5.3 PHP
    *
    * @return string
    */
   function get_called_class()
   {
      $bt = debug_backtrace();
      $lines = file($bt[1]['file']);
      preg_match('/([a-zA-Z0-9\_]+)::'.$bt[1]['function'].'/',
               $lines[$bt[1]['line']-1],
               $matches);
      return $matches[1];
   }
}

Esto le permite determinar en una función estática lo nombre de la clase que la función haya sido invocada. Es una solución que tiene algunos problemas de rendimiento, pero es el único que he encontrado he. Si hay otros que estaría interesado en saber.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top