Подтвердить что ты не робот

Динамически создавать 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 и создать объект типа define столбец типа таблицы с другими столбцами в строке SELECTed, назначаемой вновь созданному объекту.

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

Хорошо работает...

Ответ 3

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

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

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

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

Ответ 4

как говорит 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

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

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

Ответ 5

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

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