Alex Gusev @flancer
Я кодирую, потому что я кодирую…
Information
- Rating
- Does not participate
- Location
- Рига, Латвия, Латвия
- Date of birth
- Registered
- Activity
Specialization
Fullstack Developer
Lead
From 3,000 €
JavaScript
HTML
CSS
Node.js
Vue.js
Web development
Progressive Web Apps
PostgreSQL
MySQL
GitHub
Спсибо за пояснения, внесу правки в текст статьи.
Спасибо за коммент. Данная статья задумывалась как краткая сводка доступных способов промежуточного сохранения информации не в БД. Да, имплементаций интерфейса SessionManagerInterface достаточно много (навскидку, штук 10), но полезных рекомендаций по их использованию я дать не могу — я так глубоко не копал. Могу только сказать, что такой механизм существует, что я и сделал (информация действительно сохраняется между запросами, я проверял).
А по регистру — я посмотрел, но не понял, что именно может быть "не так"? Регистр (реестр) позволяет сохранять данные на все время своей жизни (в пределах одного запроса). Через DI доступен практически в любом классе. Если в Magento 2 есть какой-то другой механизм для выполнения таких же задач, было бы интересно о нем узнать. Сообщите, пожалуйста, о нем, и я дополню статью.
По поводу коллеций я уже понял, и я нигде не настаивал на том, что коллекции нужно использовать в коде бизнес-логики :)
Первичный ключ — любой суррогат заменяет оригинал не на все 100%. Я конкатенировал в коллекциях два атрибута в один первичный ключ — для выборки данных это отработало, но манипуляцию (сортировка, фильтрация) я уже копать не стал. Как говорится, каждому овощу свое место, а коллекции — не то место, где можно использовать составные первичные ключи.
Если следовать примеру и вводить BaseRepositoryInrerface, то он может, но не обязательно должен в своих контрактах использовать BaseEntityInterface. Мне моя религия позволяет не указывать типы аргументов и возвращаемого результата, описывая только имена контрактов и набор входных аргументов (кол-во, порядок и соглашение по их наименованию). Моя религия говорит, что договор через код, гораздо более сильный чем договор через документацию, и уж куда более сильный, чем договор на словах. А раз уж PHP позволяет специализировать тип аргумента в производных интерфейсах, то я бы этой возможностью и воспользовался. Я не настаиваю, что это правильно в рамках какой-то другой религии (DDD, например), я просто говорю, что я бы сделал именно так просто потому, что это делает разработку кода с моей точки зрения несколько легче. У разработчиков Magento 2 другая точка зрения, и они действуют по-другому. Я не призываю менять свои религии, если что. Я просто поделился своей точкой зрения.
Спасибо за развернутый ответ, коллега. Насколько я понял, на данный момент альтернативы коллекциям в механизмах фильтрации нет, появится он с версии 2.1, там и посмотреть можно будет, как его использовать.
Что касается составного первичного ключа, то это чисто мои тараканы — я считаю что для описания предметной области хватает простого первичного ключа, а для описания отношений между объектами предметной области простого первичного ключа уже недостаточно. Если та же Доктрина считает по-другому — это ее право.
Общий интерфейс на репозитории? Ну, если API так важен для архитектуры Magento 2, если код бизнес-логики должен быть завязан на Repository Interface, если большинство таких интерфейсов описывают методы для базовой манипуляции сущностями, то с моей точки зрения вполне логично выделить типовой набор методов (save, get, getById, delete, deleteById, getList) и обозвать его как-то типа BaseRepositoryInrerface, наследуя от него все остальные репо-интерфейсы. По крайней мере это было бы отличным маркером для читающих код и нечитающих мануалы, что это связанное подмножество интерфейсов, имеющее весомое значение в архитектуре Magento 2. Плюс, это было удобным примером для объяснения новичкам, что собственно такое "репозиторий сущности (EntityRepositoryInterface) и его метод getList(SearchCriteria $searchCriteria)", не на словах, а в коде. Но разработчики Magento 2 считают по-другому, поэтому такого интерфейса нет.
Для интереса залез в код. Вот интерфейс
\Magento\Catalog\Api\ProductRepositoryInterface
, в нем описан методЗаглядываем в реализацию этого метода
\Magento\Catalog\Model\ProductRepository::getList
:Сразу же бросается в глаза, что, в отношении получения списка записей, "репозиторий" — это всего лишь обертка над той же старой
добройколлекцией со всеми ее достоинствами и недостатками (включая невозможность иметь композитный primary key, которая меня почему-то огорчает больше всего).Если исполнение "технического долга" со стороны Magento 2 Team сводится к оборачиванию коллекций в код, имплементирующий некий общий EntityRepositoryInterface (которого, кстати, нет, хотя он просто обязан быть, если "разработчики мадженто за этим следят"), то все слова в отношении коллекций, сказанные коллегой Oxidant, верны также и для "обернутых коллекций". Если же в недрах Magento 2 есть "типовая" (или хотя бы "эталонная") имплементация "усредненного" интерфейса EntityRepositoryInterface (save, get, getById, delete, deleteById, getList) без использования коллекций внутри, то был бы весьма признателен, если бы коллега maghamed дал ссылку на эту имплементацию.
Только warning вылетает, но это уже мелочи на общем фоне :)
Если дожать еще передачу в DI-фабрику default-параметров для "именованного конструктора", то можно будет снимать свой вопрос по поводу использования в DI-фреймворках объектов с приватным конструктором.
Вылетает исключение:
Все из-за этого:
IMHO, эпиграф было бы лучше поставить такой:
Вполне возможно, в таком случае у меня бы не возникло вопроса, как инжектить объект класса Time (или integer, как вы резонно заметили).
Границы применимости предложенного Матиасом решения для меня стали довольно очевидны. Спасибо еще раз.
Т.е., данный подход предполагает в таких случаях создавать фабрики, которые будут создавать объекты с использованием их собственных статических фабричных методов, и уже эти фабрики инжектить в зависящие от объектов классы (или, как в случае с Symfony, указывать в настройках DI, что для создания экземпляров Time нужно использовать "factory: [TimeFactory, create]"):
Вполне возможно, в этом есть какой-то сакральный смысл, но я бы все-таки конструктор не прятал. Ну или очень сильно ограничил бы применение "именованных конструкторов" — все-таки статика к тестам совсем не friendly. Вообщем, мне эти "именованные конструкторы" как-то не совсем по душе. Но смотрятся красиво, не отрицаю.
Просто у angular'а своя ниша, и ее границы достаточно хорошо видны. Инвестировать свое время в разработку прототипа на angular'е, если твое web-приложение строится на чем-то другом — не самое оптимальное решение, IMHO.