magicoder писал(а):Правильнее использовать pdo?
Можно Query::find() или createCommand(), как в приведённом мной на первой странице репозитории. Без разницы.
Сама суть разделения - делать доменную модель и практически весь сайт отдельно от базы. Сущность реализуется в своём классе, не наследующиеся от ActiveRecord и прочего. Тогда где же это сохранять в базу? Как раз всё преобразование в базу и обратно при этом будет в репозиториях.
Для чего это и чем AR неудобен? AR - это один-в-один таблица из базы. Из одной базы и из одной таблицы. Для любого изменения базы придётся изменять AR-модель. То есть даже столбик в таблице переименовать нельзя без изменения модели и переписывания кода на всём сайте. В простых сайтах такое терпимо и этого хватает.
А если сайт посложнее, то надо придумать, как в одно поле массив или вложенный объект сохранить, или чтобы даты в полях хранились в виде объектов DateTime вместо строк, чтобы удобно было преобразовывать формат для различных виджетов-календарей. Это всё задачи не для слабонервных. Или, например, половину полей хранить в MySQL, а текст и закешированные комментарии подгружать из MongoDB или Redis... В AR для этого нужно будет целиком весь фрагмент выносить в подмодель и подвязывать через hasOne.
AR ничего экзотического изначально делать не умеет. А в случае наличия отдельного адаптера (репозитория) просто делаем в нём несколько MySQL и Redis запросов, десерелизуем массивы, оборачиваем и формируем свой результат именно таким, какой нужен:
Код: Выделить всё
$commentsFromRedis = ...;
return new Post(
new PostId($data['id']),
$data['title'],
new \DateTime($data['createdAt'])],
unserialize($data['attibutes']),
$commentsFromRedis
);
Никакой стандартный Post::findOne($id) с несколькими базами так делать не сумеет.
Теперь базы данных и таблицы в них можно менять и перестраивать как угодно, просто переписывая время от времени репозиторий.
И кстати, есть ещё один лайфхак. Сущность поста блога для выполнения различных операций может содержать связанные категории, метки, фотографии, текст, комментарии, автора, версии и т.п. А выборок на сайте может быть много:
- В виджете популярных статей нужны только заголовок и превью.
- В списке статей достаточно выводить превью, автора, категорию, главное фото и число комментариев.
- На странице статьи нужны целиком весь основной текст, фотографии, автор, категория, метки, сами комментарии...
Выбирать целиковые громоздкие сущности для этого всего может быть слишком напряжно. Поэтому для вывода на сайте можно сделать второй PostReadRepository чисто для выборок. И он из метода getPopularPosts($limit) вместо массивов оригинальных тяжёлых сущностей Post может возвращать массивы легковесных вмпомогательных DTO вроде $popular[] = new PopularPost($id, $title, $photo, $commentsCount) только с нужными полями. И для их извлечения из базы в репозитории уже можно легко формировать любые отдельные SQL-запросы.
В этом и суть. Примитивность AR и отсутствие настройки полей часто мешает делать то, что нам хочется. Вместо этого мы постоянно думаем таблицами из базы, постоянно терпим, что не можем сохранить в поле массив и не можем сделать вложенный объект Address внутри Company без hasOne и hasMany связей, так как поля в базе поддерживают только числа и строки; постоянно думаем, хранить время created_at в INTEGER, в DATETIME или в TIMESTAMP; постоянно думаем, поддерживает ли наша база JSON или на хостинге ещё его нет. Отсюда получаем поколение ActiveRecord-программистов, всю сознательную жизнь программирующих всё только в понятиях MySQL.