2010-02-04 10 views
42

Vorrei creare un oggetto in PHP basato su un tipo definito da una stringa in un database MySQL. La tabella del database ha colonne e dati di esempio di:Creare dinamicamente un oggetto PHP in base alla stringa

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

... con tipi di dati PHP

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

con una sola interrogazione, vorrei selezionare una riga da id e creare un oggetto di il tipo definisce la colonna di tipo della tabella con altre colonne nella riga SELEZIONATA assegnata all'oggetto appena creato.

Stavo pensando che l'utilizzo di:

  1. mysql_fetch_object()
  2. Leggendo l'attributo type
  3. Creazione di un oggetto con tipo definito dal type

Ma conosco nessun modo per creare dinamicamente un tipo basato su una stringa. Come si fa a fare questo?

risposta

96

Ma non c'è modo di creare dinamicamente un tipo basato su una stringa. Come si fa a fare questo?

Si può fare abbastanza facilmente e naturalmente:

$type = 'myclass'; 

$instance = new $type; 

Se la query restituisce un array associativo, è possibile assegnare proprietà utilizzando la sintassi simile:

// 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

È inoltre possibile passare argomenti al costruttore $ istanza = nuovo $ tipo (5, 'ciao'); – goat

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

Opere molto bene ...

7

C'è una sintassi molto accurata x puoi usarlo che ho imparato circa un paio di mesi fa che non si basa su una variabile temporanea. Ecco un esempio in cui io uso una variabile POST per caricare una specifica classe:

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

Nel vostro caso specifico, però, si sarebbe in grado di risolverlo utilizzando DOP. Ha una modalità di recupero che consente al valore della prima colonna di essere la classe in cui la riga viene istanziata.

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

Non capisco, a quanto pare si otterrebbe '$ eb = new $ {FALSE}();' o mi manca qualcosa ?? – FrancescoMM

+0

Il motivo per cui questo hack funziona perché '$ {false}' valuta '$ {''}' (stessa cosa che scrivere '(string) false') e la variabile con il nome' [stringa vuota] 'è quella abbiamo appena creato la clausola della parentesi interna. Molto elegante. – silkfire

0

come dice silkfire, questo può essere ottenuto utilizzando le modalità specifiche PDO, quindi ecco un esempio.Utilizzando i valori di database stessi e gli oggetti definiti:

 
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 singola query (è necessario assegnare un nome al campo che contiene il nome della classe prima):

$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 

questo è cool ma diventa più fresco con un po '

$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 

si può definire un costruttore (che si chiamerà dopo i valori dal database vengono assegnati alle proprietà) di lavorare su quelle proprietà assegnati in modo dinamico, ad esempio per sosti ng una stringa con la sua maiuscolo valore

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

Qui di seguito è quello che cercavo quando sono arrivato a questo thread. utilizzare {"objectName"} (parentesi) per dichiarare o fare riferimento al nome dell'oggetto sotto forma di stringa.

  $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; 

Questo modo di fare riferimento all'oggetto sembra essere intercambiabile. Non sono riuscito a trovare la risposta, quindi ho dovuto giocarci fino a quando non ho trovato un modo.

Problemi correlati