PHP
Perfect code
Laravel
Comments 33
+1
Дико плюсую автору! Хватит впиливать в проекты сложноподдерживаемые решения и потом мучиться с ними. Если так сильно хочется использовать репозитории, то переходите на Symfony. Это позволит сократить время, которое вам потребуется, чтобы поддерживать свой велосипед на репозиториях.
+1
Начал за здравие, кончил за упокой. Я тоже полностью согласен с автором, но при чем тут Symfony? Это проблема модели взаимодействия с бд AR а не фреймворка.
+2
Люди часто доктрину связывают с симфони. Я спокойно юзаю доктрину в ларавель проекте…
+1
переходите на Symfony
при чем тут Symfony?
Люди часто доктрину связывают с симфони

следующий вопрос: причем тут доктрина? )

+3

Оратор выше, видимо, имеет ввиду, что репозитории с Data Mapper работают прекрасно, в отличии от репозиториев с Active Record.
Doctrine — единственная более менее съедобная имплементация Data Mapper на PHP.


Я же указываю на то, что Doctrine является самостоятельным проектом, разработка которого напрямую никак не связана с Symfony (косвенно может и связана — они там все общаются же).


В общем, переходить на Symfony, просто потому что там Doctrine — глупо (у вас должны быть более веские основания чтобы сменить фреймворк, в котором уже наработан опыт), потому как Doctrine точно также подключается и в Laravel. Я даже знаю человека, который наоборот цеплял Eloquent (illuminate/database) в проект на symfony. Ума не приложу, зачем это ему, но речь не об этом. Я всего лишь хотел сказать, что эти конкретные ORM не завязаны на фреймворк, как таковые. И, при желании, они легко запиливаются/выпиливаются (хотя, с выпиливанеим Eloquent из Laravel, все несколько сложнее, но не безнадежно).

0

А вот оно что — вы призыв перехода на симфони связали с тесной интеграцией с ней доктрины (хотя это прямо нигде не указано).
И тут же пишете, что "Doctrine является самостоятельным проектом" и "ORM не завязаны на фреймворк", хотя тред именно с вашей подачи идет в интерпретации "Симфони = Доктрина".

0
Если так сильно хочется использовать репозитории, то переходите на Symfony.

Это не я сказал. Репозитории можно использовать в том фреймворке, в котром вам вкусно их использовать. Но не с любой ORM.


P.S. я не понимаю в чем вы хотите меня уличить.
P.P.S Можно использовать репозтории даже с Eloquent, если считать, что модели Eloquent это не модели предметной области, а их маппинг на базу данных.
В этом случае, у вас полчится забавный каламбур с DM работающим поверх AR.

+1
Хватит впиливать в проекты сложноподдерживаемые решения и потом мучиться с ними. Если так сильно хочется использовать репозитории, то переходите на Symfony.

лично я понял это как отсылку к излишней академичности решений на симфони. Ведь репозитории действительно можно использовать везде, а репозитории Доктрины — это явно не те абстрактные репозитории, о которых идет речь в статье.

0
Хм… а я последнее предложение понял буквально. Я почему-то подумал, что «сложноподдерживаемые решения» — это именно репозитории с AR, а не репозитории вообще.
Я уж к холивару приготовился. А тут просто недопонимание )
0
— регулярно вижу статьи в стиле «как использовать шаблон Репозиторий с Eloquent»

Впервые о таком слышу. Статей ни одной не видел.

+2
одна такая попала в недавний PHP-дайджест

Тоже негодовал по этому поводу (особенно с тем решением, что предлагалось в статье)


Не буду в этой статье ругать ненужный суффикс Interface

И не нужно ругать. Как-никак, PSR Naming Conventions


А в целом, согласен с автором.

0
Внесу небольшую поправку по поводу PSR Naming Conventions: это внутренний документ, регулирующий правила именования для самих PSR. То есть один из стандартов для публикуемых рекомендаций.
PSR Naming Conventions предназначен для разработчиков PSR и не оформлен сам как PSR, а потому он не является рекомендацией для нейминга теми проектами, которые используют PSR.

UPD. Впрочем как и Symfony Conventions — это, соответственно, тоже правила и конвенции, предназначенные для разработчиков и контрибьютеров Symfony
+1
Всегда добавляю суффикс Interface (за исключением тех случаев, когда название интерфейса является прилагательным). Но PSR Naming Conventions тут вообще не причем. Просто в глобальном поиске IDE (PHP Storm в моем случае) легче отличать интерфейс от имплементации. Вот такой вот я плохиш )
0
А зачем их отличать?
Видел и NameInterface, и NameContract, и IName и даже I_Name, но никокого практического смысла так из этих приемов и не извлек.
+1

Суффикс Interface — это венгерская нотация для более высокого уровня абстракции. Раньше тип переменных включали в имя переменной (intCount, strName, и т.д.). Теперь возможности языка и IDE таковы, что в венгерской нотации нет необходимости, в том числе и для интерфейсов. Почему мы все классы в проекте суффиксом Class не награждаем? Пора сделать код более читабельным и отказаться от мусорного суффикса для интерфейсов в том числе. Список литературы:
https://www.alainschlesser.com/interface-naming-conventions/


https://dev.to/scottshipp/when-hungarian-notation-lies-hidden-in-plain-sight-372


https://phpixie.com/blog/naming-interfaces-in-php.html


https://twitter.com/nikolaposa/status/1077327810627358721

+3

Всё верно, но бывает, что он даже не попадает в первый экран выдачи. А когда ты добавляешь заветное I, то оказывается прямо под рукой. Я например, для перехода к CacheInterface забиваю CaI, и шторм махом понимает что именно я хочу. В то время, как если бы это был просто Cache, то я бы собрал всю папку vendor и все, что там называется Cache, и не факт что интерфейс оказался бы в первом экране выдачи.

0

то у вас появляется еще куча проблем, которые можно, но не нужно, решать именованием файлов/классов.

0
Не согласен с автором. Лучше прикрутить репозитории, чем писать eloquent запросы в контроллере. Мы же хотим использовать те же запросы и в других местах тоже? А ещё когда понадобится прикрутить кеширование? Если есть репозиторий то добавишь декораторы и будет удобное кеширование
0
Если же у вас в проекте Eloquent и очень хочется побаловаться шаблонами проектирования, то в следующей статье я покажу как можно частично применить шаблон Репозиторий и получить от этого пользу.

Как раз про это будет.
+1
Если честно не понял статью (может просто пятница?): Вроде призыв к не работе в Eloquent в концепции репозитория. Но предложения составлены так, что это «не» не видно. Много кода, но все для «не» делайте так. А если нужно, альтернативы не прописано.

Зачем вводить в проект абстракцию, которая только усложнит его?

Потому, что если действие повторяется, при этом есть другой код, а не просто save, то логично его вынести отдельно, а не в каждом контроллере повторять — Но не в Репозитории, а в Сервис.

Почему не Репозитории. В 99% случае в модели нужно описывать методы с отношениями к другим таблицам. Т. е. Ломается логика в получении данных не через репозитории зависимой модели, а через встроенный обработчик отношений.
0
ну в какой-нибудь доктрине тоже отношения часто через прокси реализованы. смысл в персисте. во всех реализациях Active Record — приходится вручную их в базу кидать, либо минуя репозиторий, либо использовать другой «репозиторий».
+1
Поддерживаю, никогда не понимал сакрального смысла репозитория возвращающего eloquent модели
+2
Я отчасти понимаю негодование автора, НО автор слишком заостряет внимание на шаблоне.
1. Шаблон это рекомендация.
2. Помимо разделения и тестирования есть ещё жизненный цикл. И подобный подход позволяет в определённой степени поддерживать и обновлять продукт гораздо проще со всеми итерациями рефакторинга и дальнейшей разработкой. С тестированием да, возникают проблемы.
3. Автору оригинала задавали уйму вопросов в комментариях, в том числе из разряда, что ваш репозиторий — не репозиторий вовсе.
Дочитывая пост до конца, остаётся чувство, будто на тебя вылили ушак помоев, но извиниться забыли. Зачем автор вместо того, чтобы писать пост «программистского гнева», который в целом понятен и я отчасти его поддерживаю, не предложил сразу альтернативный вариант, который отвечает всем «критериям» автора?
В любом случае, спасибо за материал, жду альтернативный подход.
0
Пожалуй, с этой точки зрения действительно стоило не превращать это в две статьи, а написать все в одной…
0
Эта тема стабильно поднимается и поднимается. Несколько лет назад я споткнулся где-то рядом habr.com/ru/post/316836.

Возникает тот же вопрос: а зачем это все?


Попробую засветить мысли к которым я пришел. Дело в том, что есть множество RAD-разработчиков, которые практически ничего не использовали за рамками Laravel5 и/или Yii2.
Однако некоторые из них слышали про существование других инструментов, паттернов и тп.
А еще некоторые из некоторых хотят развиваться и далеко не у всех есть верховный маг PHP стоящий выше.

Следовательно такие разработчики читают про что-то новое, в особенности паттерны и бегут это сразу же применять (тут я могу и себе подмигнуть).

Так вот, почти всем нам хорошо известно, что ActiveRecord нарушает принципы SOLID.
Поэтому, если наш AR Repository будет возвращать такую штуку как Model, то можно сделать следующее:

<?php
    $post = $repository->find($id);
    //...Какая-нибудь проверка с $post->... 
    $post->published = true;
    $post->delete(); // или $post->save() // или $post->{любая магия AR}

    $repository->save($post);


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

Что касается смены базы данных, поддержки разных баз в AR и тп. Тут нужно кейс рассматривать совсем в другом ключе. Репозиторий это абстракция над хранилищем, а хранилище может быть в другом источнике. Например у вас есть блог на сайте и мы берем данные из нашей базы, а затем у нас появляется кейс, брать данные не из нашей базы, а уже из внешнего ресурса, например стороннего API (какой-то там биржи статей или другого блога). Тогда в теории нам нужно подменить только реализацию, что бы все завелось.

Однако, если у нас нет сущностей и мы гоняем AR Model в репозиториях, то тогда возникнут большие проблемы.

Собственно ключевая особенность RAD-инструмента от Enterprise, как раз в простоте.
Как когда-то мне сказал zelenin, выбирая инструмент нужно принимать правила игры.

Но есть еще 1 момент. Можно использовать Repository не как паттерн абстракции над хранилищем в рамках RAD-инструмента, а как некий класс в котором будут лежать наши запросы для удобства. В таком случае нам и интерфейс не нужен:

<?php
class UserRepository
{
    public static function findActiveUsers(): User
   {
   }

    public static function findBestUser(): User
   {
   }

    public static function findBannedUsers(): Users
   {
   }

...
}


0
Но есть еще 1 момент. Можно использовать Repository не как паттерн абстракции над хранилищем в рамках RAD-инструмента, а как некий класс в котором будут лежать наши запросы для удобства. В таком случае нам и интерфейс не нужен

в таком случае это не репозиторий, а сервис

+2
Максимально точно выражено мое мнение, полностью поддерживаю. Но необходимо дополнить.

Использование репозитория просто как абстракции над хранилищем зачастую не имеет смысла в продуктах до определенного размера. Тут проблема в том, что любое изменение бизнес-условий в продукте чуть выше размером, чем домашняя CRUD страничка, вызовет мучительные боли чуть пониже спины, потому что эти изменения коснутся каждого файла проекта, где подобные операции используются.
К примеру, буквально вчера в большой лигаси-системе я зарелизил небольшой блок, который касался добавления нового типа сущности. Проблема в том, что этот тип сущности требовалось получить из внешнего источника, отличного от базы данных. Кроме того, его нужно было зарегистрировать во всех элементах сайта, где он может потенциально использоваться. Итого, мне пришлось изменить что-то в районе 80 файлов на стороне сервера, чтобы добавить тривиальную функцию. А это непаханое поле ошибок и потенциальных багов, которые необходимо еще отлавливать.

Используй разработчик паттерн репозиторий, да и в целом, поддерживай он исходники в более качественном состоянии, подмена кода была бы не такой страшной и менять пришлось бы не более 10-15 файлов.

То есть выбирая инструмент, а я пропагандирую отказ от AR в пользу более очевидного, но имеющего больший порог входа репозитория и сущности, как коллекции — объектного представления структуры данных, необходимо понимать и представлять не только то, что будет сейчас, но и загадывать на перспективу. Ибо, как сказал небезызвестный в узких кругах широких масс, некий М. Фраулер, чистая архитектура это такая архитектура, изменения в которую вносятся максимально просто.

Суть репозитория не только в том, чтобы было легко подменять источник получения данных, а в том, чтобы в принципе было удобно подменять логику работы с хранилищем. К примеру, у вас были в приложении новости, которые возвращались в десятке контроллеров. Приходит бизнес и просит вас добавить к этим постам параметр видимость. У вас несколько решений: если вы не использовали репозиторий, вы будете писать скоуп для модели, ползти в те места (если вы их помните, а в командной разработке это не факт), где это работать не должно, например, в админке, править это безобразие. В случае же с репозиторием, вы подменяете в одном из методов реализацию выборки добавлением этого скоупа, не добавляя ее в выборку для админки или сбрасываете ее.

Резюмируя. Если вы хотите сделать быстро, проверить гипотезы, не планируете вносить большие изменения от слова совсем — используйте Eloquent as is — это крутейший инструмент, значительно ускоряющий процесс разработки продукта. Но если вы делаете проект для заказчика, в условиях изменяющихся бизнес-требований, с учетом необходимости длительной поддержки сервиса, не поленитесь, пишите репозитории: они окупятся. И дело даже не в смене базы данных, а в целом, в простоте поддержки продукта на разных этапах его существования.
0
Полностью согласен. И даже коротко примерно описал:
Если же бизнес-логика так сложна, что очень хочется покрыть ее тестами, то лучше взять data mapper библиотеку вроде Doctrine и полностью отделить бизнес-логику от остального приложения. Юнит-тестирование станет раз в 10 проще.
Полностью отделенная логика предполагает абстракции вроде Репозиториев. По крайней мере, для write моделей.
Only those users with full accounts are able to leave comments., please.