Динамически создавать PHP-объект на основе строки - PullRequest
44 голосов
/ 04 февраля 2010

Я хотел бы создать объект в 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)...

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

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

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

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

Ответы [ 5 ]

101 голосов
/ 04 февраля 2010

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

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

$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;
}
8 голосов
/ 18 июня 2013

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

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

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

$sth->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE);
7 голосов
/ 04 февраля 2010
$instance = new $classname; // i.e. $type in your case

Очень хорошо работает ...

0 голосов
/ 13 ноября 2016

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

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

0 голосов
/ 21 мая 2014

, как говорит 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);}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...