Допустим, всякий раз, когда я выполняю операцию CRUD или изменяю отношения определенным образом, я также хочу делать что-то еще. Например, всякий раз, когда кто-то публикует сообщение, я также хочу что-то сохранить в таблице для аналитики. Может быть, не лучший пример, но в целом есть много этой "сгруппированной" функциональности.
Обычно я вижу этот тип логики в контроллерах. Это нормально, пока вы не захотите воспроизвести эту функцию во многих местах. Когда вы начинаете разбираться в частичках, создавая API и создавая фиктивный контент, становится проблемой сохранять вещи СУХИМЫМИ.
Я видел способы управления этим: события, репозитории, библиотеки и добавление в модели. Вот мое понимание каждого:
Службы: это, где большинство людей, вероятно, поместили бы этот код. Моя основная проблема со службами заключается в том, что иногда трудно найти в них определенную функциональность, и я чувствую, что о них забывают, когда люди сосредоточены на использовании Eloquent. Откуда мне знать, что мне нужно вызывать метод publishPost()
в библиотеке, когда я могу это сделать $post->is_published = 1
?
Единственное условие, в котором я вижу, что это работает хорошо, - это если вы используете ТОЛЬКО сервисы (и в идеале делаете Eloquent недоступным как-то для всех контроллеров).
В конечном счете кажется, что это просто создаст кучу лишних ненужных файлов, если ваши запросы в целом соответствуют структуре вашей модели.
Репозитории: Насколько я понимаю, это в основном похоже на сервис, но есть интерфейс, позволяющий переключаться между ORM, которые мне не нужны.
События: Я считаю, что это самая элегантная система в некотором смысле, потому что вы знаете, что события вашей модели всегда будут вызываться с помощью методов Eloquent, поэтому вы можете писать свои контроллеры, как обычно. Я могу видеть, что они становятся грязными, и если у кого-то есть примеры крупных проектов, использующих события для критической связи, я бы хотел это увидеть.
Модели: Традиционно у меня были классы, которые выполняли CRUD, а также обрабатывали критическую связь. Это на самом деле упростило задачу, потому что вы знали все функциональные возможности CRUD +, что бы с ним ни было, оно было там.
Просто, но в архитектуре MVC это обычно не то, что я вижу. Хотя, в некотором смысле, я предпочитаю это, а не сервисы, так как найти их немного легче, и меньше файлов для отслеживания. Это может стать немного дезорганизованным все же. Я хотел бы услышать недостатки этого метода и почему большинство людей, кажется, не делают этого.
Каковы преимущества / недостатки каждого метода? Я что-то упускаю?
источник
Ответы:
Я думаю, что все шаблоны / архитектуры, которые вы представляете, очень полезны, если вы следуете принципам SOLID .
Для того, чтобы добавить логику, я думаю, что важно сослаться на принцип единой ответственности . Кроме того, мой ответ считает, что вы работаете над средним / большим проектом. Если это проект типа « что-то на странице », забудьте этот ответ и добавьте его в контроллеры или модели.
Краткий ответ: где это имеет смысл для вас (с услугами) .
Длинный ответ:
Контроллеры : Какова ответственность контроллеров? Конечно, вы можете поместить всю свою логику в контроллер, но это ответственность контроллера? Я так не думаю.
Для меня контроллер должен получить запрос и вернуть данные, и это не место для проверки, вызова методов БД и т. Д.
Модели . Является ли это хорошим местом для добавления логики, такой как отправка приветственного письма по электронной почте, когда пользователь регистрируется или обновляет счет голосов для сообщения? Что если вам нужно отправить то же электронное письмо из другого места в вашем коде? Вы создаете статический метод? Что, если для этого письма нужна информация от другой модели?
Я думаю, что модель должна представлять сущность. С Laravel, я использую только класс модели , чтобы добавить такие вещи , как
fillable
,guarded
,table
и отношения (это потому , что я использую Repository Pattern, в противном случае модель будет также иметьsave
,update
,find
, и т.д. методы).Репозитории (Repository Pattern) : В начале я был очень смущен этим. И, как и вы, я подумал: «Ну, я использую MySQL, и все».
Тем не менее, я уравновесил плюсы и минусы использования шаблона репозитория, и теперь я использую его. Я думаю, что сейчас , в этот самый момент, мне нужно будет использовать только MySQL. Но если через три года мне нужно перейти на что-то вроде MongoDB, большая часть работы будет выполнена. Все за счет одного дополнительного интерфейса и
$app->bind(«interface», «repository»)
.События ( шаблон наблюдателя ): события полезны для вещей, которые могут быть выброшены в любой класс в любой момент времени. Подумайте, например, об отправке уведомлений пользователю. Когда вам нужно, вы запускаете событие, чтобы отправить уведомление в любой класс вашего приложения. Затем у вас может быть такой класс,
UserNotificationEvents
который обрабатывает все ваши запущенные события для пользовательских уведомлений.Услуги : до сих пор у вас есть возможность добавить логику в контроллеры или модели. Для меня имеет смысл добавить логику в Сервисы . Посмотрим правде в глаза, Услуги это модное название для классов. И вы можете иметь столько классов, сколько это имеет смысл для вас в вашем приложении.
Возьмите этот пример: недавно я разработал что-то вроде Google Forms. Я начал с
CustomFormService
и в конечном итоге сCustomFormService
,CustomFormRender
,CustomFieldService
,CustomFieldRender
,CustomAnswerService
иCustomAnswerRender
. Зачем? Потому что это имело смысл для меня. Если вы работаете с командой, вы должны поставить свою логику там, где это имеет смысл для команды.Преимущество использования служб по сравнению с контроллерами / моделями заключается в том, что вы не ограничены ни одним контроллером, ни одной моделью. Вы можете создать столько сервисов, сколько вам нужно, в зависимости от дизайна и потребностей вашего приложения. Добавьте к этому преимущество вызова Сервиса в любом классе вашего приложения.
Это долго, но я хотел бы показать вам, как я структурировал свое приложение:
Я использую каждую папку для определенной функции. Например,
Validators
каталог содержитBaseValidator
класс, отвечающий за обработку валидации, основанный на$rules
и$messages
конкретных валидаторов (обычно один для каждой модели). Я мог бы так же легко поместить этот код в Службу, но для меня имеет смысл иметь для этого специальную папку, даже если она используется только внутри Службы (на данный момент).Я рекомендую вам прочитать следующие статьи, так как они могут объяснить вам немного лучше:
Дэйл Рис (автор CodeBright): «Я ломаю планку». Именно здесь я собрал все это вместе, хотя я изменил несколько вещей в соответствии со своими потребностями.
Разделение вашего кода в Laravel с использованием репозиториев и сервисов Криса Гуси: этот пост хорошо объясняет, что такое сервис и шаблон репозитория и как они сочетаются друг с другом.
У Laracasts также есть Репозитории с Упрощенной и Единой Ответственностью, которые являются хорошими ресурсами с практическими примерами (даже если вы должны заплатить).
источник
Я хотел опубликовать ответ на свой вопрос. Я мог бы говорить об этом в течение нескольких дней, но я постараюсь опубликовать это быстро, чтобы убедиться, что я в курсе.
В итоге я использовал существующую структуру, которую предоставляет Laravel, а это означает, что я хранил свои файлы в основном в виде Model, View и Controller. У меня также есть папка «Библиотеки» для повторно используемых компонентов, которые на самом деле не являются моделями.
Я не оборачивал свои модели в услуги / библиотеки . Все приведенные причины не на 100% убедили меня в пользе использования услуг. Хотя я могу ошибаться, насколько я вижу, они просто приводят к множеству дополнительных почти пустых файлов, которые мне нужно создавать и переключаться между ними при работе с моделями, а также действительно уменьшают преимущества использования eloquent (особенно когда речь идет о ПОЛУЧЕНИИ моделей). например, с использованием нумерации страниц, областей и т. д.).
Я поставил бизнес - логику в моделях и доступ красноречивых непосредственно из моих контроллеров. Я использую несколько подходов, чтобы убедиться, что бизнес-логика не обойдется:
Решение проблем людей с использованием моделей:
Дополнительное примечание: мне кажется, что оборачивать ваши модели в сервисы - это все равно, что иметь швейцарский армейский нож с большим количеством инструментов и строить вокруг него еще один нож, который в основном делает то же самое? Да, иногда вы можете захотеть скотчить лезвие или убедиться, что два лезвия используются вместе ... но обычно есть другие способы сделать это ...
КОГДА ИСПОЛЬЗОВАТЬ УСЛУГИ : В этой статье очень хорошо сформулированы ОТЛИЧНЫЕ примеры того, когда пользоваться услугами ( подсказка: это не очень часто ). Он говорит, что в основном, когда ваш объект использует несколько моделей или моделей в странных частях их жизненного цикла, это имеет смысл. http://www.justinweiss.com/articles/where-do-you-put-your-code/
источник
То, что я использую для создания логики между контроллерами и моделями, - это создание сервисного уровня . По сути, это мой поток для любых действий в моем приложении:
Вот как я это делаю:
Это метод контроллера для создания чего-либо:
Это класс обслуживания, который выполняет логику, связанную с операцией:
И это моя модель:
Для получения дополнительной информации об этом способе я использую, чтобы организовать свой код для приложения Laravel: https://github.com/rmariuzzo/Pitimi
источник
$congregation->save();
возможно, вам не понадобятся репозитории. Однако вы можете заметить, что ваши потребности в доступе к данным со временем возрастут. Вы можете начать нуждаться в$congregation->destroyByUser()
или$congregationUsers->findByName($arrayOfSelectedFields);
и так далее. Почему бы не отсоединить ваши услуги от потребностей доступа к данным. Позвольте остальной части вашего приложения работать с объектами / массивами, возвращенными из репозиториев, и просто обрабатывать манипуляции / форматирование / и т.д ... Ваши репозитории будут расти (но разбить их на разные файлы, в конечном итоге сложность проекта должна где-то находиться).На мой взгляд, у Laravel уже есть много вариантов для хранения вашей бизнес-логики.
Короткий ответ:
Request
объекты laravel для автоматической проверки вашего ввода, а затем сохраните данные в запросе (создайте модель). Поскольку все входные данные пользователей непосредственно доступны в запросе, я считаю, что имеет смысл выполнить это здесь.Job
объекты laravel для выполнения задач, требующих отдельных компонентов, а затем просто отправляйте их. Я думаю, чтоJob
включает в себя классы обслуживания. Они выполняют задачу, такую как бизнес-логика.Длинный (er) ответ:
Использовать репозитории, когда это необходимо: репозитории обязательно переполнены, и большую часть времени просто используются в качестве
accessor
модели. Я чувствую, что они определенно имеют какое-то применение, но если вы не разрабатываете массивное приложение, которое требует такой гибкости, чтобы вы могли полностью избавиться от лишнего, оставайтесь в стороне от репозиториев. Вы поблагодарите себя позже, и ваш код будет намного проще.Спросите себя, есть ли вероятность того, что вы собираетесь менять фреймворки PHP или использовать тип базы данных, который laravel не поддерживает.
Если ваш ответ «Наверное, нет», не используйте шаблон репозитория.
В дополнение к вышесказанному, пожалуйста, не бейте шаблон поверх превосходного ORM, такого как Eloquent. Вы просто добавляете сложность, которая не требуется, и она не принесет вам никакой пользы.
Используйте сервисы экономно: для меня классы сервисов - это просто место для хранения бизнес-логики для выполнения конкретной задачи с учетом ее зависимостей. У Laravel они есть из коробки, они называются «рабочие места», и они обладают гораздо большей гибкостью, чем пользовательский класс обслуживания.
Я чувствую, что у Laravel есть всестороннее решение
MVC
логической проблемы. Это просто вопрос или организация.Пример:
Запрос :
Контроллер :
В приведенном выше примере входные данные запроса автоматически проверяются, и все, что нам нужно сделать, это вызвать метод persist и передать новую запись. Я думаю, что удобочитаемость и ремонтопригодность всегда должны превосходить сложные и ненужные шаблоны проектирования.
Затем вы можете использовать точно такой же постоянный метод для обновления сообщений, так как мы можем проверить, существует ли уже сообщение и выполнить чередующуюся логику при необходимости.
источник
ShouldQueue
которую предоставляет Laravel. Если вы хотите написать бизнес-логику в команде или событии, просто запустите задание внутри этих событий / команд. Рабочие места Laravels чрезвычайно гибки, но, в конце концов, они просто классы обслуживания.