Динамически создавать PHP-объект на основе строки

Я хотел бы создать объект в PHP на основе типа, определенного строкой в ​​базе данных MySQL. В таблице базы данных есть столбцы и выборочные данные:

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

… с типами данных PHP

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

Используя только один запрос, я хотел бы ВЫБРАТЬ строку по id и создать объект типа, который определяет столбец типа таблицы с другими столбцами в строке SELECTed, назначаемой вновь созданному объекту.

Я думал, что используя:

  1. mysql_fetch_object()
  2. Чтение атрибута type
  3. Создание объекта с типом, определенным атрибутом type

Но не знаете, как динамически создать тип на основе строки. Как это сделать?

Но не знаете, как динамически создать тип на основе строки. Как это сделать?

Вы можете сделать это довольно легко и естественно:

 $type = 'myclass'; $instance = new $type; 

Если ваш запрос возвращает ассоциативный массив, вы можете назначить свойства с использованием аналогичного синтаксиса:

 // 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; } с // 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; } 
 $instance = new $classname; // ie $type in your case 

Работает очень хорошо …

Есть очень аккуратный синтаксис, который вы можете использовать, о котором я узнал пару месяцев назад, который не полагается на временную переменную. Вот пример, когда я использую переменную POST для загрузки определенного класса:

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

Однако в вашем конкретном случае вы сможете решить эту проблему с помощью PDO. Он имеет режим выборки, который позволяет первому столбцу быть классом, в который создается строка.

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

как говорит silkfire, это может быть достигнуто с использованием специфичных для PDO режимов, так что вот пример. Использование одинаковых значений базы данных и определенных объектов:

  id |  тип |  propertyVal
 ---- + ------ + -------------
   1 |  foo |  lorum
   2 |  бар |  Ipsum

 class ParentClass {...}
 класс Foo расширяет ParentClass {private $ id, $ propertyVal;  ...}
 класс Bar расширяет ParentClass {private $ id, $ propertyVal;  ...} 
 //...(более классы) ...

с одним запросом (сначала вы должны указать поле, содержащее имя класса):

 $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 

это круто, но с течением времени становится прохладнее

 $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 

вы можете определить конструктор (который будет вызываться после того, как значения из базы данных будут назначены свойствам), чтобы работать с этими динамически назначенными свойствами, например, заменяя строку ее верхним значением

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

Ниже я искал, когда пришел к этой теме. используйте {"objectName"} (скобки), чтобы объявить или ссылаться на имя объекта в форме строки.

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

Этот способ обращения к объекту представляется взаимозаменяемым. Я не мог найти ответ, поэтому мне пришлось обманывать его, пока я не нашел способ.