PDO: выбор класса для отправки полей конструктору в виде массива - PullRequest
5 голосов
/ 27 февраля 2012

Привет, ребята (и девочки?) Мне интересно, возможно ли элегантно отобразить результаты запроса 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;
}

Примечание: я запускаю PHP 5.3 и MySQL через PDO и уже знаю, что эту проблему можно решить с помощью __set, но я явно хочу не использовать ее в пользу чего-то более производительного.

Ответы [ 3 ]

3 голосов
/ 04 июля 2012

Вам не нужно передавать аргументы в конструктор, чтобы создать класс с закрытыми членами, используя 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'];
}
1 голос
/ 27 февраля 2012

Удален предыдущий код


Правильно, вы не можете сделать что-то вроде этого:
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 для получения «новых» членов.

Да, это все равно не пропустит их через ваш конструктор.

0 голосов
/ 28 февраля 2012

Как насчет использования магического __ 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 будет вызывать этот магический метод для каждого несуществующего свойства, передавая его имя и значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...