PDO fetchObject

hell0w0rd

Продвинутый новичок
Подскажите пожалуйста, как можно разделить результат запроса на два объекта?
На сколько я знаю рефлексия работает достаточно медленно.
 

hell0w0rd

Продвинутый новичок
PHP:
CREATE TABLE `city` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`(255))
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(256) DEFAULT NULL,
  `city` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`(255)),
  KEY `city` (`city`),
  CONSTRAINT `city` FOREIGN KEY (`city`) REFERENCES `city` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
PHP:
$db = new PDO($dsn, 'dev', null);
$query = <<<SQL
SELECT city.id as city_id, city.name as city_name, user.id as user_id, user.name as user_name
FROM user
JOIN city ON user.city = city.id
SQL;
$query = $db->prepare($query);
$query->execute();
$obj = $query->fetch(PDO::FETCH_ASSOC);
var_dump($obj);

class User
{
    private $id;
    private $name;
    private $city;

    public function getCity()
    {
        return $this->city;
    }

    public function setCity(City $city)
    {
        $this->city = $city;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

}

class City
{
    private $id;
    private $name;

    public function getId()
    {
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }
}
При таком раскладе простейший select парсится в объект отлично, а вот как это сделать если я вытягиваю несклько объектов - вопрос:)
Доктрина на сколько я понимаю это через рефлексию делает
 

AmdY

Пью пиво
Команда форума
у тебя уже всё готово, по префиксу рассовывай по объектам.
city_ -> City
user_ -> User

p.s. Я делаю два запроса с кешем.
 

hell0w0rd

Продвинутый новичок
у тебя уже всё готово, по префиксу рассовывай по объектам.
city_ -> City
user_ -> User

p.s. Я делаю два запроса с кешем.
Не, как отфильтровать я понимаю, как приватным полям установить значения без рефлексии? Или FetchObject как раз рефлексию юзает?
А какой смысл делать два запроса? Так делает доктрина по умолчанию с ее lazy loading, но ведь 1 запрос лучше, чем 2?
 

AmdY

Пью пиво
Команда форума
hell0w0rd
Так и эзай сеттеры, зачем приватные поля заполнять напрямую.

А какой смысл делать два запроса? Так делает доктрина по умолчанию с ее lazy loading, но ведь 1 запрос лучше, чем 2?
Это вещь субъективная http://habrahabr.ru/post/184160/
 

AmdY

Пью пиво
Команда форума
hell0w0rd
Всё должно через сеттер, иначе какой смысл. Да и вообще, лучше всё же магию __get __set юзать с проверкой на method_exists "set{$fieldName}"

>>А при чем тут тестирование?
Это про субъективность, а не про тестирование.
 

fixxxer

К.О.
Партнер клуба
FetchObject использует внутреннее php api. Он вообще до вызова конструктора.

2 запроса лучше, чем 1, если это повышает cache hit/miss ratio.
 

hell0w0rd

Продвинутый новичок
FetchObject использует внутреннее php api. Он вообще до вызова конструктора.

2 запроса лучше, чем 1, если это повышает cache hit/miss ratio.
Так если есть datamapper в том или ином виде, вытянув сразу два объекта, они кешироваться по одиночке будут?)
То есть только рефлексия и никак иначе?:)
 

fixxxer

К.О.
Партнер клуба
Ну почему.
Можно сделать у базового класса метод setAttributes по аналогии с рельсами.
Можно сделать все model-классы implements Seriazable, и на этом построить свой ActiveRecord с блудницами и преферансом.
Можно, в конце концов, генерировать сериализованную строку и делать unserialize :)
 

hell0w0rd

Продвинутый новичок
По поводу последнего тоже уже думал, но мне кажется работа с рефлексией будет быстрее) А по поводу опкод-кеширования рефлексии что-то можете сказать?)
Я вообще подумал что если я хочу сделать аля доктринскую орм, без extends AR, с простыми объектами - ничего плохого в setId по идее нет. Просто datamapper может его не учитывать и все:)
 

fixxxer

К.О.
Партнер клуба
ну попробуй побенчить. не думаю что настолько уж прямо медленно
 

Ragazzo

TDD interested
hell0w0rd
рефлексия, внешние xml, либо in-code правила для распределения результата по объектам. Пока что ничего особо нового не придумали.
 

hell0w0rd

Продвинутый новичок
hell0w0rd
рефлексия, внешние xml, либо in-code правила для распределения результата по объектам. Пока что ничего особо нового не придумали.
Ну вот fixxxer когда предложил про unserialize, я подумал что можно например делать подготовленную строку и в нее запихивать аргументы sprintfом например:)
 

Ragazzo

TDD interested
hell0w0rd
ты бы определился что тебе надо, ORM где главное entities или где главное таблицы, ибо это важно, и уже потом смотреть как маппить. А вообще тут про доктрину речь, я так мимо проходил вообще.
 

hell0w0rd

Продвинутый новичок
Ragazzo
Не очень понял, как могут быть главными таблицы, или entities. Одно представление другого. entities - все те же строки таблиц в php, а таблицы - те же наборы php-объектов в БД?:)
 

Ragazzo

TDD interested
entities - все те же строки таблиц в php, а таблицы - те же наборы php-объектов
это называется AR.
есть ORM вида хибернейт, там могут быть embedded values. ORM рассчитанная на entities старается максимально соблюдать PI (правда это уже больше к смой DM), отсюда и куча проблем. Ты решай лучше доктриной, а не пиши свою ORM :D
 

hell0w0rd

Продвинутый новичок
это называется AR.
есть ORM вида хибернейт, там могут быть embedded values. ORM рассчитанная на entities старается максимально соблюдать PI, отсюда и куча проблем. Ты решай лучше доктриной, а не пиши свою ORM :D
Хм, AR - это всего лишь паттерн, в котором все entities наследуются от класса, умеющего сохраняться в бд самостоятельно.
А datamapper - класс, знающий откуда взять объект и как сохранить объекты, которые ничего не знают о базе, в этом и все различие
У меня времени много, могу посидеть, поразбираться, так что все ок)
 

Ragazzo

TDD interested
Хм, AR - это всего лишь паттерн, в котором все entities наследуются от класса, умеющего сохраняться в бд самостоятельно.
А datamapper - класс, знающий откуда взять объект и как сохранить объекты, которые ничего не знают о базе, в этом и все различие
видишь как у тебя все просто :)
 
Сверху