web-dev-qa-db-de.com

Dynamisch erstellen PHP Objekt basierend auf String

Ich möchte ein Objekt in PHP basierend auf einem Typ erstellen, der durch einen String in einer MySQL-Datenbank definiert ist. Die Datenbanktabelle enthält Spalten und Beispieldaten von:

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

... mit PHP Datentypen

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

Mit nur einer Abfrage möchte ich eine Zeile nach ID AUSWÄHLEN und ein Objekt des Typs erstellen, in dem die Typspalte der Tabelle definiert wird, während andere Spalten in der Zeile SELECTed dem neu erstellten Objekt zugewiesen werden.

Ich dachte, dass mit:

  1. mysql_fetch_object()
  2. Lesen des type-Attributs
  3. Erstellen eines Objekts mit einem Typ, der durch das Typattribut definiert ist

Sie kennen jedoch keine Möglichkeit, einen Typ basierend auf einer Zeichenfolge dynamisch zu erstellen. Wie macht man das?

44
Mat Kelly

Es ist jedoch kein Weg bekannt, einen Typ dynamisch basierend auf einer Zeichenfolge zu erstellen. Wie macht man das? 

Das geht ganz einfach und natürlich:

$type = 'myclass';

$instance = new $type;

Wenn Ihre Abfrage ein assoziatives Array zurückgibt, können Sie Eigenschaften mit ähnlicher Syntax zuweisen:

// 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;
}
100
meagar

Es gibt eine sehr ordentliche Syntax, die Sie verwenden können, die ich vor ein paar Monaten gelernt habe und die nicht auf einer temporären Variablen beruht. Hier ein Beispiel, bei dem ich eine POST - Variable verwende, um eine bestimmte Klasse zu laden:

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

In Ihrem speziellen Fall können Sie es jedoch mit PDO lösen. Es gibt einen Abrufmodus, mit dem der Wert der ersten Spalte die Klasse sein kann, in die die Zeile instantiiert.

$sth->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE);
7
silkfire
$instance = new $classname; // i.e. $type in your case

Funktioniert sehr gut ...

7
roman

Nachstehend habe ich gesucht, als ich zu diesem Thread kam. Verwenden Sie {"objectName"} (Klammern), um den Objektnamen in Form einer Zeichenfolge zu deklarieren oder darauf zu verweisen.

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

Diese Art der Bezugnahme auf das Objekt scheint austauschbar zu sein. Ich konnte die Antwort nicht finden, also musste ich damit herumalbern, bis ich einen Weg fand.

0

wie Seidenfeuer sagt, kann dies durch die Verwendung von PDO-spezifischen Modi erreicht werden. Hier ist ein Beispiel. Verwenden Sie dieselben Datenbankwerte und definierten Objekte:

 id | Typ | propertyVal 
---- + ------ + -------------
 1 | foo | Lorum 
 2 | Bar | ipsum 

 class ParentClass {...} 
 class Foo erweitert ParentClass {private $ id, $ propertyVal; ...} 
 class Bar erweitert ParentClass {private $ id, $ propertyVal; ...} 
 // ... (weitere Klassen) ...

mit einer einzelnen Abfrage (Sie müssen zuerst das Feld mit dem Klassennamen benennen):

$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

das ist cool, aber mit der Zeit wird es kühler

$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

sie können einen Konstruktor definieren (der aufgerufen wird, nachdem die Werte aus der Datenbank Eigenschaften zugewiesen wurden), um mit diesen dynamisch zugewiesenen Eigenschaften zu arbeiten, z

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