2010-02-04 2 views
42

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

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)... 

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

Я думал, что с помощью:

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

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

ответ

96

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

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

$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; 
} 
+29

Вы также можете передать аргументы конструктору $ instance = new $ type (5, 'hi'); – goat

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

Works очень хорошо ...

7

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

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

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

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

Я не понимаю, видимо, вы бы получили '$ eb = new $ {FALSE}();' или я что-то пропустил? – FrancescoMM

+0

Причина, по которой этот хак работает, заключается в том, что '$ {false}' оценивается как '$ {''}' (то же самое, что и запись '(string) false'), а переменная с именем' [empty string] '- мы только что создали в предложении внутренней скобки. Очень изящный. – silkfire

0

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

 
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)... 

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

$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 

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

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

Ниже приведено то, что я искал, когда пришел к этой теме. используйте {"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; 

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