2010-02-04 19 views
42

Me gustaría crear un objeto en PHP basado en un tipo definido por una cadena en una base de datos MySQL. La tabla de base de datos tiene columnas y datos de la muestra de:Crear dinámicamente un objeto PHP basado en la cadena

id | type | propertyVal 
----+------+------------- 
    1 | foo | lorum 
    2 | bar | ipsum 

... con tipos de datos PHP

class ParentClass {...} 
class Foo extends ParentClass {private $id, $propertyVal; ...} 
class Bar extends ParentClass {private $id, $propertyVal; ...} 
//...(more classes)... 

Usando sólo una consulta, me gustaría seleccionar una fila por id y crear un objeto de el tipo define la columna de tipo de la tabla con otras columnas en la fila SELECCIONADA que se está asignando al objeto recién creado.

Estaba pensando que el uso de:

  1. mysql_fetch_object()
  2. lectura el atributo de tipo
  3. Creación de un objeto con el tipo definido por el atributo de tipo

Pero conozco ninguna manera de crear dinámicamente un tipo basado en una cadena. ¿Cómo hace uno esto?

Respuesta

96

Pero no hay forma de crear dinámicamente un tipo basado en una cadena. ¿Cómo hace uno esto?

Puede hacerlo con bastante facilidad y de forma natural:

$type = 'myclass'; 

$instance = new $type; 

Si la consulta devuelve un array asociativo, puede asignar propiedades utilizando una sintaxis similar:

// build object 
$type = $row['type']; 
$instance = new $type; 

// remove 'type' so we don't set $instance->type = 'foo' or 'bar' 
unset($row['type']); 

// assign properties 
foreach ($row as $property => $value) { 
    $instance->$property = $value; 
} 
+29

También puede pasar argumentos al constructor $ instancia = new $ type (5, 'hi'); – goat

7
$instance = new $classname; // i.e. $type in your case 

Obras muy bien ...

7

Hay una sinta muy clara x puede usar lo que aprendí hace un par de meses que no depende de una variable temporal. He aquí un ejemplo en el que yo uso una variable POST para cargar una clase específica:

$eb = new ${!${''} = $_POST['entity'] . 'Binding'}(); 

En su caso específico, sin embargo, que sería capaz de resolverlo mediante el uso de DOP. Tiene un modo de búsqueda que permite que el valor de la primera columna sea la clase en la que la fila crea una instancia.

$sth->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE); 
+0

No lo entiendo, aparentemente obtendrías '$ eb = new $ {FALSE}();' ¿o me estoy perdiendo algo ?? – FrancescoMM

+0

La razón por la que este truco funciona es porque '$ {false}' evalúa a '$ {''}' (lo mismo que escribir '(cadena) falso') y la variable con el nombre' [cadena vacía] 'es la acabamos de crear en la cláusula del bracket interno. Muy ingenioso – silkfire

0

como silkfire dice, esto se puede lograr mediante el uso de modos específicos de PDO, así que aquí está un ejemplo.Utilizando sus mismos valores de bases de datos y objetos definidos:

 
id | type | propertyVal 
----+------+------------- 
    1 | foo | lorum 
    2 | bar | ipsum 

class ParentClass {...} 
class Foo extends ParentClass {private $id, $propertyVal; ...} 
class Bar extends ParentClass {private $id, $propertyVal; ...} 
//...(more classes)... 

con una sola consulta (hay que nombrar el campo que contiene el nombre de la clase en primer lugar):

$stmt = $db->prepare('SELECT type,id,propertyVal FROM table WHERE id=1'); 
$stmt->execute(); 
$foo = $stmt->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE); 
var_dump($foo); // $foo is a newly created object of class foo, with properties named like and containing the value of subsequent fields 

esto es genial, pero se pone más frío con un tiempo

$stmt = $db->prepare('SELECT type,id,propertyVal FROM table'); 
$stmt->execute(); 
while ($object = $stmt->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE)) 
{var_dump($object);} // here all desired objects, dynamically constructed accordingly to the first column returned by the query 

puede definir un constructor (que se llamará después de los valores de la base de datos se asignan a propiedades) para trabajar en esas propiedades asignadas dinámicamente, por ejemplo por cambiar aceit ng una cadena con él es uppercased valor

class foo 
{function __construct() 
    {$this->uper = strtoupper($this->propertyVal);}} 
0

continuación es lo que estaba buscando cuando llegué a este hilo. use {"objectName"} (corchetes) para declarar o hacer referencia al nombre del objeto en forma de cadena.

  $gameData = new stdClass(); 
    $gameData->location = new stdClass(); 
    $basementstring = "basement"; 
    class tLocation { 

       public $description; 

       } 

     $gameData->location->{'darkHouse'} = new tLocation; 
     $gameData->location->{"darkHouse"}->description = "You walkinto a dusty old house"; 


    $gameData->location->{$basementstring} = new tLocation; 
    $gameData->location->{"basement"}->description = "its really damp down here."; 

    // var_dump($gameData); 
    echo $gameData->location->basement->description; 

Esta forma de referirse al objeto parece ser intercambiable. No pude encontrar la respuesta, así que tuve que jugar con eso hasta que encontré el camino.

Cuestiones relacionadas