Загрузка динамического класса PHP
Давайте скажем, что у меня есть массив, который я хочу преобразовать в объект значения.
Мой класс объектов свойств выглядит следующим образом:
/* file UserVO.php*/
class UserVO
{
public $id;
public $email;
public function __construct($data)
{
$this->id = (int)$data['id'];
$this->email = $data['email'];
}
}
И я создаю свой массив объектов значений следующим образом:
/* file UserService.php*/
$array = array(
array(...),
array(...));
$count = count($array);
for ($i = 0; $i < $count; $i++)
{
$result[] = new UserVO($array[$i]);
}
return $result;
ОК, так что все работает отлично. Тем не менее, я хотел бы указать VO, который должен быть создан динамически, так что у меня может быть одна динамическая функция для создания моих VO.
Что-то вроде:
$ret = create_vo($array, 'UserVO');
function create_vo($data, $vo)
{
$count = count($data);
for ($i = 0; $i < $count; $i++)
{
$result[] = new $vo($data[$i]); //this obviously wont work...Class name must be a valid object or a string
}
return $result;
}
Я понимаю, что могу сделать это с помощью оператора switch (итерации через все мои VO)... но, без сомнения, гораздо более элегантное решение. Это также было бы supercool, если бы я мог ленить загружать VO по мере необходимости, вместо того, чтобы иметь несколько "включает"
Любая помощь очень ценится.
Ответы
Ответ 1
$result[] = new $vo($data[$i]); //this obviously wont work...Class name must be a valid object or a string
Вы пробовали? Он работает так, как ожидалось (в php 5.1, я не знаю, как это было с ООП в php 4, но если вы используете __construct
для конструктора, это должно работать).
Чтобы избежать множественного включения, определите магическую функцию __autoload
перед использованием любого класса
function __autoload($className)
{
require_once 'myclasses/'.$className.'.php';
}
Итак, первый вызов new UserVo
приведет к включению этой функции в файл myclasses/UserVo.php.
Ответ 2
Похоже, что include_once() и require_once() производительность довольно плохая.
Мое предложение:
Убейте все "require_once" и "include_once" и создайте автозагрузчик. Зарегистрируйте эту реализацию
Ответ 3
Сначала преобразование данных в объект массива для UserVO должно выполняться с помощью ArrayObject
так
class UserVO extends ArrayObject
{
}
Вы пытаетесь использовать шаблон factory, и ваш код кажется правильным, хотя вы, похоже, забыли define $result в виде массива ($ result = array()).
Вы также можете использовать ReflectionClass для передачи аргументов конструктора, а также таких:
$rc = new ReflectionClass($vo);
$rc->newInstanceArgs($data[$i]);
Чтобы "автозагрузить" ваш объект UserVO, вы должны использовать функцию spl_autoload_register с помощью пути включения php.
Ответ 4
Это работает
<?
class UserVO
{
public $id;
public $email;
public function loadData($data)
{
$this->id = (int)$data['id'];
$this->email = $data['email'];
}
}
function create_vo($data, $vo)
{
$count = count($data);
for ($i = 0; $i < $count; $i++)
{
$tmpObject = new $vo;
$tmpObject->loadData($data[$i]);
$result[] = $tmpObject;
unset($tmpObject);
}
return $result;
}
$data = array();
$data[] = array('id'=>1,'email'=>'[email protected]');
$data[] = array('id'=>2,'email'=>'[email protected]');
$data[] = array('id'=>3,'email'=>'[email protected]');
$data[] = array('id'=>4,'email'=>'[email protected]');
$data[] = array('id'=>5,'email'=>'[email protected]');
$data[] = array('id'=>6,'email'=>'[email protected]');
$result = create_vo($data,'UserVO');
var_dump($result);
?>