ФорумПрограммированиеPHP для идиотовPHP и ООП → Паттерн ActiveRecord

Паттерн ActiveRecord

  • Timur

    Сообщения: 1068 Репутация: N Группа: Джедаи

    Spritz 15 февраля 2008 г. 19:23

    Суть паттерна вроде ясна. Не ясно только как лучше быть со связями таблиц. Т.е., например, есть таблицы author (id, name, …) и work (id, author, name, …), связанные 1:М и соответствующие классы Author и Work. У Work есть метод getAuthor(). Вопрос - что он должен возвращать - то, что непосредственно хранится в поле (т.е. id автора) или соответствующий объект Author.
    Объект, конечно удобнее, но если например мне нужно получить значения полей work, запрос проходит только к одной таблице. Но тогда, если понадобиться получить информацию из author придётся делать ещё один запрос.
    Дык как лучше - один запрос по всем таблицам или отдельные запросы для каждого по мере необходимости?
  • vasa_c

    Сообщения: 3131 Репутация: N Группа: в ухо

    Spritz 15 февраля 2008 г. 21:28, спустя 2 часа 4 минуты 56 секунд

    Вот там самая тема которую я тут как-то поднимал.
    Нестыковка между прекрасным, идеальным и возвышенными миром абстрактных шаблонов и грубой реальностью (особенно грубой в веб-программировании).
    Как искать между ними компромисс, каждый решает сам, в зависимости от конкретных условий.
  • Timur

    Сообщения: 1068 Репутация: N Группа: Джедаи

    Spritz 15 февраля 2008 г. 23:49, спустя 2 часа 21 минуту 52 секунды

    блин, я уже не знаю с какой стороны лучше подойти… Как раньше - писать запросы в коде сценария и не заморачиваться?
    маппер тоже выглядит как-то громоздко, у меня и связей-то немного в базе, просто хотелось простое и универсальное решение…

    А вообще об объектах и базах данных…
    Прочитал тут несколько статей на тему ООП-подхода к работе с РСУБД. Там предлагалось вообще забыть про нормализацию, модель сущность-связь в БД и т.п. вещи. Типа всего несколько таблиц - таблица классов, таблица объектов, таблица атрибутов; у каждого объекта - свой уникальный в рамках всей базы ID… Статья: http://www.ibase.ru/devinfo/oop_rdbms.htm
    Кто-нибудь применял такой подход? Просто мне кажется чем диким…
  • Patrick

    Сообщения: 506 Репутация: N Группа: Кто попало

    Spritz 16 февраля 2008 г. 11:41, спустя 11 часов 52 минуты 2 секунды

    Привет Timur!
    Конечно объект Author, ну или их коллекцию объектов!!!

    Но тогда, если понадобиться получить информацию из author придётся делать ещё один запрос.
    Дык как лучше - один запрос по всем таблицам или отдельные запросы для каждого по мере необходимости?



    <?php
    $work = new Work(1);
    $author = $work->getAuthor();
    ?>

    Переносим это дело на SQL ;)

    SELECT * FROM `work` WHERE `work_id` = 1;
    SELECT * FROM `author` WHERE `author_id` = 3; // К примеру ;)

    id - у нас это индекс, так что выборка будет выполняться влёт!
    В данный момент, мы  как раз так и делаем….


    Вот там самая тема которую я тут как-то поднимал.
    Нестыковка между прекрасным, идеальным и возвышенными миром абстрактных шаблонов и грубой реальностью (особенно грубой в веб-программировании).
    Как искать между ними компромисс, каждый решает сам, в зависимости от конкретных условий.

    Никакой несостыковки нет! Просто надо научится их готовить! и смешивать ;).



    блин, я уже не знаю с какой стороны лучше подойти… Как раньше - писать запросы в коде сценария и не заморачиваться?


    Ну эт каждый должен выбрать сам! например мне в лом писать каждый раз одни и те же  действия….


    маппер тоже выглядит как-то громоздко, у меня и связей-то немного в базе, просто хотелось простое и универсальное решение…


    Хм, AR у нас на 200 строчек кода ;) вроде всё норм! Вот ещё вопрос , ты случаем не путаешь AR и DataMapper?


    А вообще об объектах и базах данных…
    Прочитал тут несколько статей на тему ООП-подхода к работе с РСУБД. Там предлагалось вообще забыть про нормализацию, модель сущность-связь в БД и т.п. вещи. Типа всего несколько таблиц - таблица классов, таблица объектов, таблица атрибутов; у каждого объекта - свой уникальный в рамках всей базы ID… Статья: http://www.ibase.ru/devinfo/oop_rdbms.htm
    Кто-нибудь применял такой подход? Просто мне кажется чем диким…


    Вот лично тебе должно быть пофиг откуда берутся данные, из БД, файлов или памяти! Ты должен работать источником данных! Для клиентских сайтов(визитки & etc.) подойдёт и AR, но вот если будет, что то посерьёзней со сложной логикой домена, то без DataMapper'a не обойтись….

    Всё же, думаю,  к DataMapper'у мы перейдём на след недели… Уж очень хочется в это верить…
  • Timur

    Сообщения: 1068 Репутация: N Группа: Джедаи

    Spritz 16 февраля 2008 г. 13:05, спустя 1 час 23 минуты 51 секунду

    Переносим это дело на SQL ;)

    так и есть, но ведь получается 2 запроса, а ведь если нужно получить например данные и по автору, и по работе, то вместо:
    SELECT * FROM `work` WHERE `work_id` = 1;
    SELECT * FROM `author` WHERE `author_id` = 3; // К примеру ;)

    лучше было бы написать 1 запрос:
    SELECT * FROM `author`, `work` WHERE 
    `work`.`author_id`=`author`.`author_id` AND
    `work_id`=1

    Т.о. количество запросов линейно возрастает вместе с количеством связей: если work связано, например ещё с двумя таблицами, то запросов будет уже 4 вместо одного, и т.д.

    Вот ещё вопрос , ты случаем не путаешь AR и DataMapper?

    Да, тут не совсем AR, я наверное некорректно обозвал, просто принцип действия вроде похож.

    Есть абстрактный класс ActiveRecord, где описаны все операции по обмену данными с базой. От него идут потомки: Work, Author, etc., конкретизирующие работу ActiveRecord (т.е. сообщающие ему имена таблицы и полей). Выглядит это примерно так:

    если при создании экземпляра любого потомка ActiveRecord был указан ID - работа идет с существующей записью (при сохранении - UPDATE), если нет - то с новой (при сохранении - INSERT). Например:
     // Существующая запись:
    $work = new Work(3);
    //запрос к таблице, вывод данных
    echo $work->getName();
    echo $work->getAuthor();
    // установка значений и их изменение:
    $work->setName('xxx');
    $work->setAuhtor(3);
    $work->save(); // UPDATE записи

    // Новая запись
    $work = new Work(); // ID не указываем
    $work->setName('yyy');
    $work->setAuthor(4);
    $work->save(); // ID не указан при инстанцировании, делаем INSERT новой записи


    Вопрос вот именно в том как избежать дополнительных запросов там, где можно обойтись одним?

    Есть мысли, типа создаем статический метод getWork($id), который будет делать один запрос ко всем таблицам имеющим отношение к work, создавать объект Work и все связанные с ним объекты (Author, Material, Type…) помещать в соответствующие поля Work. Флаг isLoaded для всех объектов при этом установливается в true.
    Тогда методы getAuthor(), getType()… будут возвращать не ID записей, а сразу объекты. Может так?

  • Patrick

    Сообщения: 506 Репутация: N Группа: Кто попало

    Spritz 16 февраля 2008 г. 16:01, спустя 2 часа 55 минут 22 секунды

    Статическими должны быть только Find методы!!! ИМХО.

    Т.о. количество запросов линейно возрастает вместе с количеством связей: если work связано, например ещё с двумя таблицами, то запросов будет уже 4 вместо одного, и т.д.

    Будет интересно посмотреть на скорость выполенения 4 запросов ( WHERE id=1 или IN(2,4,5) ) и одного запроса с JOIN'ом. Если не разу не тестил, то советую взглянуть! таблицы бери тока по больше ~100k тебе хватит))) Так же прочитай про Lazy Load!!!!
  • Timur

    Сообщения: 1068 Репутация: N Группа: Джедаи

    Spritz 16 февраля 2008 г. 16:13, спустя 12 минут 38 секунд

    http://www.gotdotnet.ru/LearnDotNet/NETFramework/451426.aspx#_Toc165869915
    загрузка по требованию (Lazy Load) — создание объектов, которые не содержат требуемых данных, но могут загрузить их в случае необходимости.
    а у меня так и есть. Объект создается пустым, а метод reload() вызывается только с первым вызовом какого-нибудь get'а.

    Тестить не буду, поверю на слово )
  • mechanic

    Сообщения: 125 Репутация: N Группа: Кто попало

    Spritz 22 февраля 2008 г. 17:51, спустя 6 дней 1 час 37 минут


    таблица классов, таблица объектов, таблица атрибутов; у каждого объекта - свой уникальный в рамках всей базы ID… Статья: http://www.ibase.ru/devinfo/oop_rdbms.htm
    Кто-нибудь применял такой подход? Просто мне кажется чем диким…


    не поверите - я сам себе его придумал, а щас вот наткнулся на эту ветку, прошел по ссылке и с удивлением обнаружил в статье описание этой концепции ))
    тока вместо classid у меня type_id, каждый тип имеет "шаблонный" набор свойств, которые привязываются к каждому новому объекту этого типа при создании, но и разумеется можно добавлять неограниченное кол-во свойств для любого объекта

    вся "байда в сборе" обслуживается тремя классами: класс типа, класс собсна объекта и основной статический класс Driver, через который и идет вся работа
  • Timur

    Сообщения: 1068 Репутация: N Группа: Джедаи

    Spritz 23 февраля 2008 г. 9:52, спустя 16 часов 1 минуту 2 секунды

    Я пока от такого сращивания ООП с реляционными базами отказался - слишком большие потери производительности получаются, запросы не поддаются оптимизации.
  • Patrick

    Сообщения: 506 Репутация: N Группа: Кто попало

    Spritz 23 февраля 2008 г. 16:52, спустя 7 часов 22 секунды


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


    Как доведём нашу модель до ума, обязательно выложу код, а пока с нашей реализацией AR, ab -c 10 -t 60, мы держим 100 запросов в секунду!!! и это на апаче!!!

    не поверите - я сам себе его придумал

    Теперь мы знаем создателя AR! ;) Ура!!!
  • mechanic

    Сообщения: 125 Репутация: N Группа: Кто попало

    Spritz 24 февраля 2008 г. 10:49, спустя 17 часов 56 минут 59 секунд


    Теперь мы знаем создателя AR! ;) Ура!!!

    ээ ну вообще-то activerecord тут ни при чем )
    я про другое говорил, про управление "объектами с произвольными свойствами" поделенными на типы
  • Timur

    Сообщения: 1068 Репутация: N Группа: Джедаи

    Spritz 24 февраля 2008 г. 11:37, спустя 48 минут 7 секунд

    Как доведём нашу модель до ума, обязательно выложу код

    было бы отлично )

    про управление "объектами с произвольными свойствами" поделенными на типы

    покажешь реализацию?
  • mechanic

    Сообщения: 125 Репутация: N Группа: Кто попало

    Spritz 24 февраля 2008 г. 16:25, спустя 4 часа 47 минут 58 секунд


    покажешь реализацию?

    показать коды или описать на словах?
    склоняюсь ко второму
  • md5

    Сообщения: 11960 Репутация: N Группа: в ухо

    Spritz 24 февраля 2008 г. 16:29, спустя 4 минуты 3 секунды

    давай второе затем первое
    все умрут, а я изумруд
  • mechanic

    Сообщения: 125 Репутация: N Группа: Кто попало

    Spritz 25 февраля 2008 г. 11:15, спустя 18 часов 45 минут 27 секунд

    таблички
    Types (id, name) - типы объектов
    Pattern (id, type_id, name, def_value) - шаблонные (дефолтные) свойства для каждого вновь создаваемого объекта типа type_id

    далее таблички объектов
    Objects (id, type_id) - обекты
    Properties (id, obj_id, name, value) - их свойства

    как видно таблички типов и объектов похожи, в связи с чем была мысль использовать вообще только 2 таблицы ) но че то показалось совсем извратно

    далее реализация:
    статичный класс-драйвер представляет интерфейс для полного управления типами и объектами
    например

    $pattern = array(
    'title' => 'New title',
    'descr' => 'Text here'
    );
    $type = Driver::createType('News', $pattern);
    $newNews = $type->makeObject();
    $newNews->title = 'TItle';
    $newNews->descr = 'News text';
    $newNews->update();

    вот как то так

Пожалуйста, авторизуйтесь, чтобы написать комментарий!