PDO: Опция извлечения класса для отправки полей конструктору в виде массива
Эй, парни (и девушки?) Мне интересно, можно ли элегантно сопоставить результаты запроса PDO с членом массива в классе, а не использовать их в качестве общедоступных свойств этого объекта.
Скажем, у меня есть (сокращенное) следующее:
class DBObject {
protected
$record = array();
function __construct(array $record) {
if(!empty($record)) {
$this->loadRecord($record);
}
}
}
В идеале я хочу вызвать конструктор с массивом значений, переданных из базы данных, а не использовать __set или любые другие странные методы. Так что использование существующего API PDO было бы здорово.
Мой грубый get_all
функция на данный момент зашла так далеко:
static function get_all() {
$class = get_called_class();
$results = DB::factory()->query('SELECT * FROM ' . $class . ' ORDER BY ID');
$results->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, $class);
return $results;
}
NB: Я запускаю PHP 5.3 и MySQL через PDO и уже знаю, что эта проблема разрешима с помощью __set, но я явно хочу избежать ее использования в пользу чего-то более производительного.
3 answers
Удален предыдущий код
Верно, разве ты не можешь сделать что-то подобное:
class DBObject {
protected $record = array();
function __construct($record = null) {
if(null === $record){
$obj_vars = get_object_vars($this);
$cls_vars = get_class_vars(get_class($this));
$this->$record = array_diff_key($obj_vars, $cls_vars);
}else{
$this->record = $record;
}
}
}
Проблема с этим, однако, заключается в том, что значения по-прежнему доступны в качестве общедоступных элементов. Но то, что он будет делать, - это сравнивать "предопределенные" (классовые) члены с фактическими (объектными) членами.
Поскольку PDO создаст новые элементы в объекте, вы можете использовать array_diff_key для получения "новых" элементов.
Да, это все равно не передаст их через ваш конструктор.
Вам не нужно передавать аргументы конструктору, чтобы создать класс с закрытыми членами с помощью PDO::FETCH_CLASS. Вы можете сделать что-то вроде этого:
<?php
class Songs
{
private $artist;
private $title;
public function __construct()
{
}
public function get_artist()
{
return $this->artist;
}
public function get_title()
{
return $this->title;
}
private function set_artist($artist)
{
$this->artist = $artist;
}
private function set_title($title)
{
$this->title = $title;
}
}
На самом деле я делаю это на демо-сайте, который я создал. Это отлично работает с PDO::FETCH_CLASS. По умолчанию FETCH_CLASS создает объекты, заполняя поля ПЕРЕД конструктором. Думайте об этом как об обход конструктора. И он будет делать это с частными участниками.
Если вы предпочитаете передавать аргументы в конструктор вы можете выполнить свой запрос следующим образом:
$obj = $statement->fetchALL(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'Songs', $params);
В этом случае ваш конструктор будет выглядеть так:
public function __construct($params)
{
$this->artist = $params[0]['artist'];
$this->title= $params[0]['title'];
}
Как насчет использования метода magic __set():
<?php
class MyClass
{
protected $record = array();
function __set($name, $value) {
$this->record[$name] = $value;
}
}
$pdo = new PDO("mysql:host=localhost;dbname=db", 'user', 'password');
$results = $pdo->query('SELECT * FROM table');
$results->setFetchMode(PDO::FETCH_CLASS, 'MyClass');
PHP вызовет этот волшебный метод для каждого несуществующего свойства, передавая его имя и значение.