Загрузка связанных сущностей объекта

Cx2

Новичок
это выдуманная строка, в ней только подсказка что это задачи маппера
Названия методов сбивают с толку. Кажется, что $mapper->getPost( $entity ) должен вернуть Post, а если дальше getAuthor(), то уже getPost должен передать маппер. Ну да ладно, свой велосипед не очень хочется городить и времени и опыта маловато.
 

WMix

герр M:)ller
Партнер клуба
$mapper->getPost( $entity )
это должно по идеи вернуть сущность post это может быть lazy (proxy) entity или коллекция array<post> (какая связь?) или даже lazy collection,
а getAuthor() или ->author -- getter, но это твоя реализация.

важно что не из сущности тянем, а из маппера
 

AnrDaemon

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

fixxxer

К.О.
Партнер клуба
Нормальная, если это делается прозрачно: LazyLoadEntityProxy extends Entity или LazyLoadProxyCollection<Entity> extends Collection<Entity>.
Так себе, но более-менее приемлемая, если вместо наследования делегирование через magic __methods (сломаются instanceof и typehints, но зато не надо генерировать классы для entity; с collection все проще, достаточно того, что LazyLoadProxyCollection implements CollectionInterface, который используется в entities).
Ненормальная, если для того, чтобы дернуть lazy load, надо явно написать какую-то фигню типа $this->getAuthor(), а просто $this->author не сработает.
 

AnrDaemon

Продвинутый новичок
Ну, дальше, как из поста автора доставать будем? (Автор - это у нас Entity User - в БД хранится…)
 

WMix

герр M:)ller
Партнер клуба
Автор - это у нас Entity User
ах вот ты о чем, я думал автор в посте
как из поста автора доставать будем
то же самое, у тебя mapper в нем relations в них mappers в них relations. ничего в entity инжектить не надо
сложнее скрутить $repo->byId(42)->with(Author::class) чтоб запрос после был один
 

Cx2

Новичок
@WMix, Загружать одну сущность через другую нельзя? Что допускается делать самой сущности, помимо геттеров и сеттеров своих свойств?
В ответе #28 зачем ижектить маппер в маппер? Может это должно было быть репозиторием (в который инжектится маппер)?
Ну или правильно было бы инжектить нужные мапперы в конкретный репозиторий?
И репозиторий - это обязательно реализация определенного интерфейса или тут может быть что угодно, лишь бы был функционал репозитория?
 

WMix

герр M:)ller
Партнер клуба
у меня так (но я это еще не использую это экспериментально на работе у нас doctrine), в конкретном repository конкретный mapper. на уровне mapper есть только crud операции и связки. загружать из одного mapper (как выше сказано через посты пользователей) нет смысла. но это возможно, иначе это не работает. Эту задачу решают уже в service в котором может быть несколько repositories. вообще правильно ввести в разговор понятие Query которое будет гулять между mapper, relation и service, такая абстракция которая создаст join или in(..) или where name='foo'.
теперь о репозитории. его задача хранить загруженную сущность и в случае если ее попросят, вернуть. грубо говоря $repo->byId(42) вернет туже инстанцию обьекта которая была загружена ранее к примеру запросом $repo->find(['name' => 'foo']);

Загружать одну сущность через другую нельзя?
а как иначе делать? ключик в сущности лежит (или я вопрос не понял)
Что допускается делать самой сущности, помимо геттеров и сеттеров своих свойств?
правильнее написать как с нею работать если у нее нет или почти нет getter и setter. - там только изменение внутреннего состояния
спроси @Вурдалак
В ответе #28 зачем ижектить маппер в маппер?
я этого и не делал я описывал связи между таблицами те я инжектил в mapper relation и в relation mapper. там в примере я влепил relations через конструктор, но по идеи это отдельный метод, иначе от рекурсии не избавишься
И репозиторий - это обязательно реализация определенного интерфейса или тут может быть что угодно, лишь бы был функционал репозитория?
конечно изначально он реализует один или несколько интерфейсов find, store, delete .. и конечно он имеет методы специфичные для этого конкретного репозитория getOrderPositions
 
  • Like
Реакции: Cx2

Cx2

Новичок
я этого и не делал я описывал связи между таблицами те я инжектил в mapper relation и в relation mapper. там в примере я влепил relations через конструктор, но по идеи это отдельный метод, иначе от рекурсии не избавишься
Кажется понял - логично. Смутило new One2One(..., $posts) именно внутри конструктора;
Может как-нибудь в конструктор уже что-то готовое передавать, например через фабрику?
Например:
PHP:
class UserMapper{
  protected $relstions = [];
  public function __construct($relstions){
    $this->relations = $relstions
  }
}
// использование:
$user_relations = [
   'post' => new One2One(PostMapper);
   'roles' => new One2Many(RolesMapper);
]
$user = new UserMapper($user_relations);
Чтобы relations создавались например через константы других, связанных мапперов.
Не уверен, что это у меня именно фабрика в создании массива $user_relations.

Очень много изучил готовых продуктов и всевозможных примеров, в итоге очень понравился Eloquent из Laravel. И по быстродействию хорош, и проще Доктрины, но это уже получается не маппер, а актив рекорд. Т.е. Я могу и новый объект создать и загрузить и уничтожить готовый, все понятно и удобно.
Но один момент я не понял. В той же документации к нему, есть информация про репозитории.
А зачем они нужны, если я могу все делать через сам объект сущности?
Предполагаю, что для создания методов, хорошо понятных в контексте.
Разделение отвественности? Наверное нет ... ведь репозиторий будет жестко связан в АР объектом.
Или предполагается, что можно создать другой репозиторий с такими же методами, но другой логикой?
 

WMix

герр M:)ller
Партнер клуба
Может как-нибудь в конструктор уже что-то готовое передавать, например через фабрику?
это не важно, смотри чтоб не получилось так, чтоб создать mapper нужен relation для него нужен mapper для которого нужен relation итд.
на базе Eloquent существует Аналог я им вдохновлялся. еще простенько написан Relational не для пользования а для поглядеть как сделано
А зачем они нужны
теперь о репозитории. его задача хранить загруженную сущность и в случае если ее попросят, вернуть. грубо говоря $repo->byId(42) вернет туже инстанцию обьекта которая была загружена ранее к примеру запросом $repo->find(['name' => 'foo']);
 
  • Like
Реакции: Cx2

Cx2

Новичок
Еще по репозиториям тогда вопрос-уточнение.
Репозиторий возращает сущности или коллекции сущностей, тут теперь все ясно, а нужно ли тогда этот репозиторий использовать для удаления/обновления/добавления сущностей в БД? Если да то, ты какая выгода?
 

WMix

герр M:)ller
Партнер клуба
ну хочется слово Mapper уже не использовать, или? в сервисе работать только с репами и сущностями
PHP:
// добавить
$repo->store(new Entity($foo, $bar));
// обновить
$entity = $repo->get(42);
$entity->bla($foo, $bar)
$repo->store($entity);
// удалить
$repo->remove($repo->get(42));
repository это не обязательно база, ты не знаешь как или где все хранится, у тебя представление что все хранится в памяти.

PHP:
$entity = $repo->get(42);
$entities = $repo->find(['foo' => 'bar']); // к примеру тут по запросу вернется одна запись 42
// тогда
$this->assertEquals($entity, $entities[0]);
$this->assertSame($entity, $entities[0]);
где хранится знает mapper, хотя если быть совсем чесным в mapper лежит абстракция типо driver а вот он уже конкретный -- база, файл, удаленный json запрос итд.
 

Cx2

Новичок
ну хочется слово Mapper уже не использовать
Это я для наглядности в примерах использовал.

Это то понятно

// добавить
$repo->store(new Entity($foo, $bar));
// обновить
$entity = $repo->get(42);
$entity->bla($foo, $bar)
$repo->store($entity);
// удалить
$repo->remove($repo->get(42));
Я вот чего до сих пор не пойму это.
Можно сделать так? И нормально ли это? Если у нас АР объект и репозиторий.
PHP:
$entity = $repo->get(42);
$entity->bla($foo, $bar)->store();
// или
$entity->remove();
 

WMix

герр M:)ller
Партнер клуба
конечно можно
PHP:
class Repo{
  public function store($ar){
    $ar->store();
  }
}
но я уже не вижу смысла
в этом и "прелесть" AR что он сам "активен".

ну те в случае маппера у тебя нет выбора, entity она ничего не умеет делать сама
 
Сверху