Комментарии 104
Ждем-с статей с техническими подробностями.
В ларавеле можно использовать инъекцию зависимостей по интерфейсу, заменить ущербный Eloquent на Doctrine (или вообще обойтись без готовой ORM), можно запилить структуру проекта согласно принципам «гексагональной архитектуры» или DDD, да и вообще много чего можно сделать.
Но, по факту, официальная документация и туториалы предлагает вместо этого использовать статические фасады для доступа к чему угодно (начиная с 5 версии — так и вообще просто глобальные функции типа app(), dispatch() и т.д. Забавно, что сам Тейлор аргументирует тем, что, мол, «под капотом» фасадов и функций на самом-то деле DI-контейнер инстанцирует объекты, как будто это что-то меняет)
Макаки, разумеется, в восторге — можно говнокодить безо всяких ограничений не включая мозг. Напрямую обратиться к БД в темплейте? Легко! Вызвать какой-либо сервис прямо из модели? Запросто! И именно поэтому ларавел так популярен! На западе уже, фактически, это «новый вордпресс». Да, казалось бы, дело в макаках, а не в ларавеле, но почему тогда документация учит «плохим» практикам, даже толком не упоминая о «хороших»?
А про «экосистему» и говорить не хочется — с каких пор привязка к вендорским инструментам стала благом?
Фреймворк позволяет нам ускорить процесс разработки и имеет очень обширный готовый функционал, не говоря уже о дополнительных пакетах.
Чтобы полностью создать веб-проект, необходимо знать множество вещей, не только PHP.
Почему начинающие пишут код в шаблоне? Потому что им кажется, что так проще.
Просто люди не знают как правильно, им никто этого не объяснил, именно для этого и существуют обучающие материалы.
Проблема в том, что все знания необходимо собирать из разных источников, их надо искать.
А как найти то, не зная что искать?
В статье я попытался рассказать, что именно необходимо искать и в каком порядке.
Безусловно, опытному разработчику мягко говоря неудобно поддерживать код, который писал начинающий, хочется взять всё и переписать, но виноват в этом заказчик.
Именно заказчик и обязан проверять квалификацию исполнителя, но зачастую заказчику важна стоимость разработки, а не качество и красота кода.
А грамотных заказчиков столько же, сколько и грамотных исполнителей — мало.
Фреймворк очень быстро развивается, улучшается всё, в том числе и документация.
Как писать чистый и понятный код? Только опыт, общение с другими разработчиками, участие в Open Source проектах.
Попробуйте реализовать проект именно так, как рекомендует документация, посмотрите другие похожие проекты на Laravel и следуйте их практикам.
Главное, не пытайтесь всё переделать, в 99% люди уже решали те же задачи. Зачем изобретать велосипед.
Мы все стараемся всё усложнять, а необходимо упрощать. Самое трудное сделать из сложного — простое.
Технологии развиваются, люди думают как лучше, как проще, появляются новые практики.
Кто-то скажет давайте напишем на asm веб-сервер, сегодня покрутят у виска, а 20 лет назад сказали бы да, давайте.
Laravel — это возможности. Это красивый код, если хотеть писать его красиво и да, этому надо учиться. До сих пор все спорят: табуляция или пробел =)
Посмотрите книгу «Refactoring to Collections», разве это неудобно? Collections
Сам фреймворк решает именно необходимые задачи, которые возникают у всех проектов.
Тот же IoC и Eloquent удобен, если решаешь его использовать.
Конечно, что-то сделать нельзя, но для этого и есть открытое сообщество, предлагайте идеи, ведь все хотят сделать лучше и удобнее.
Но мы то как привыкли — что-то не получается, тут же говорим, что фигня и возвращаемся к старому.
А если посмотреть с другой стороны, например, Вы хотите создать стартап.
- Вы быстро можете создать то, что необходимо. Создание кода, тестирование, деплой.
- Быстро запустить проект в работу, а с помощью сторонних вендоров ускорить весь процесс и качество кода.
- Быстро развернуть проект с балансировкой нагрузки в случае необходимости.
- Laravel Forge, например, экономит время при настройке сервера, не хотите платить, так или иначе Ваше время = деньги.
- Обновился фреймворк — легко обновляете, есть список изменений и инструкция по обновлению, если следовали общей практике, то вообще всё просто.
- Любой Laravel разработчик сможет разобраться в коде проекта.
Что Вы как владелец стартапа предпочтёте?
Нанимать PHP-разработчика и создавать свой функционал с нуля и надеяться, что стартап взлетит и другой разработчик в случае чего сможет в нём быстро разобраться.
Или же нанять Laravel-разработчика, который реализует то же самое, но дешевле, и Вы точно знаете, что можно найти ещё разработчика на Laravel, который легко разберётся в коде проекта.
И это всё при том, что стартапов как грибов. HH и в продашкн, как говорится, но если хотите грамотно и быстро, то Laravel даёт возможность это всё сделать.
Конечно, ни одному человеку неприятно осознавать, что он легко заменяем, НО грамотный разработчик всегда останется грамотным и такая у нас профессия — постоянно надо учиться.
Если Вы НЕ успеете запрыгнуть в этот поезд, где надо делать всё быстрее и дешевле, используя как преимущество свой опыт, то может случиться так, что Вы будете предлагать заказчику реализовать форму авторизации, регистрации и восстановления пароля на сайте за 2 недели, когда это всё делается одной командой: php artisan make:auth.
Конечно, обсуждать можно долго, аргументов множество, книжку можно написать.
Кому-то нравится, кому-то нет, но, безусловно, стоит обратить внимание и потратить время.
Когда-то я вообще думал, что мне не нужен фреймворк, я сам могу реализовать с нуля всё, что мне надо, но есть ньюанс — время, за него никто не хочет платить.
Информации сегодня настолько много, что её необходимо фильтровать, не то что читать, иначе жизни не хватит всё изучить и самое главное, не знаешь что тебе пригодится.
Именно поэтому начинающим и необходим какой-то план по изучению, а не крупицы из разных источников и чем проще будет подана информация, тем легче её осознать, а дальше уже приходит опыт и желание сделать код красивым.
Экосистема — позволяет не просто написать код и кинуть на FTP, а создать проект, тестировать, поддерживать. Люди решают те задачи, которые необходимы.
Никто не заставляет использовать какой-либо язык разработки или фреймворк: просто кто-то хочет использовать новые технологии, а кто-то нет.
Вы рекомендуете читать документацию, и следовать практикам, принятым в ларавел-сообществе, а я уже упомнянул, что документация и сообщество как раз таки поощряют писать говнокод, не рассказывая о том, что возможен другой путь (enterprise-like практики).
Хотя, конечно, для типового веб-приложения (== пачки примитивных крудов) этого более чем достаточно, и скорость разработки куда важнее. А до поддержки и наращивания функционала, скорее всего, даже и не дойдет — редкий мегасовременный хипстерский стартап живет больше года.
что документация и сообщество как раз таки поощряют писать говнокод
В документации указан самый простой вариант для использования. Если он не подходит по какой-то причине — давайте уже сами, это не CMS, где только кнопочки нажимать, тут ещё и думать надо.
И да, отвечайте за себя, пожалуйста. За всех не говорите, ок?
В поддержку enterprise — есть LTS релизы. Но фреймворк очень активно развивается и в каждой версии добавляется что-то хорошее.
Если мы говорим о балансировке нагрузки, работе нескольких разработчиков над проектом, то всё есть.
Я понимаю о чём Вы говорите, DevOps, QA, банковский сектор и т.д.
Документация позволяет изучить сам фреймворк, базовые возможности, что-то дополнительно, а как применять PHP в enterprise — это отдельная тема, точнее книга и не одна.
И давайте откровенно, на вскидку, проект с 30к онлайн фреймворк выдержит без особых сложностей, кластеров БД и т.д. Есть кеширование, балансировка, CDN, очереди, да всё есть.
Задача — просто грамотно спроектировать проект, а это выходит за рамки документации по фреймворку.
У большинства проектов если есть 30к за сутки, то можно считать стартап успешным.
А что такое пачка примитивных крудов? Весь интернет, не считая монстров типа google, — пачка примитивных крудов.
Я лично поддерживаю новостной проект на DLE с посещаемостью от 30к до 100к посетителей в сутки.
И никакой фреймворк тут вообще ни причём, только nginx с SSI кеширует всё грамотно, ещё и сам DLE пришлось модифицировать.
Вы можете представить чтобы DLE из коробки выдерживал нагрузку с пользователями и забивал канал в 3гбит? Там до сих пор apache mod_php.
Посмотрите конференции по Laravel, TDD и т.д. Мне кажется, это всё знания, которые невозможно сжато уложить в документацию к PHP-фреймворку.
Придет новичок-вчерашний сайтошлеп, который не слышал про SOLID, GRASP, сервисы, интерфейсы и прочие умные слова (а мы почти все такими были когда-то), и увидит ваши статические вызовы чего угодно откуда угодно, и подумает, что так и надо делать. Да, быдлокод на чем угодно можно писать, но ларавел к этому просто подталкивает.
Весь интернет, не считая монстров типа google, — пачка примитивных крудов.
Я говорю о всяких там SaaS, ERP-системах и прочем. Там бывает, что бизнес-логика не укладывается в модель крудов, изредка даже головой приходится подумать. Нравится нам это или нет, но PHP уже давно на полном серьезе пришел в enterprise-разработку.
Написал программист код: «ну, код как код».
Вернулся к нему на следующий «день: всё нормально».
Вернулся через неделю: «блин, что же делает этот метод?»
Вернулся через год: «руки б оторвать тому кто это всё писал»
Так и в ситуации каждого из разработчиков, когда с каждой строчкой кода приобретаем новый опыт.
Опыт приходит с опытом, как говорится. Так что сетовать на якобы «неадекватность» документации не надо — там всё просто и понятно написано. Разработчик, в первую очередь, работает головой, либо учится этому в доках да узкоспециализированных чатах.
ЗЫ: А, разве, по-вашему, на нативном пыхе или других фреймах не говнокодят?
Забавно, что сам Тейлор аргументирует тем, что, мол, «под капотом» фасадов и функций на самом-то деле DI-контейнер инстанцирует объекты, как будто это что-то меняет
То что вы не видите разнцицу между статистическими вызовами и фасадами, это не говорит, о том, что это ничего не меняет. И если бы вы капнули поглубже документация рекомендует программирование по контрактам, предпочтительнее использования фасадов.
что документация и сообщество как раз таки поощряют писать говнокод
Когда мне начинают рассказывать, что на Laravel говнокодят, что Eloquent нарушает принцип единой ответственности и показывают тру «enterprise-like практики»(что бы это ни были в вашем понимании), аля отделение репозитория от модели и показывают количество кода для создания простой записи в базе со связями… Что толку от ваших «enterprise-like практик» и строгого следования тем же SOLID принципам, если на Laravel я реализую ту же логику в разы изящнее и в нескольких строках кода, в отличии от десятка строк на том же Symfony. Что наоборот делает код более поддерживаемым и понятным.
Люди забывают, что все эти принципы и практики, придуманы для того, что бы упрощать код, а не просто им следовать.
То что вы не видите разнцицу между статистическими вызовами и фасадами, это не говорит, о том, что это ничего не меняет.
Ну так просветите, что это меняет для меня, как пользователя фреймворка? Фасады, пожалуй, даже хуже — работают на «магии» (помню, сильно удивился, когда в первый раз перешел к определению «фасадного» метода) и даже для автокомплита в IDE требуют костылей.
Когда мне начинают рассказывать, что на Laravel говнокодят, что Eloquent нарушает принцип единой ответственности и показывают тру «enterprise-like практики»
Вы, видно, не писали более-менее больших проектов с сотней хитрожопо взаимосвязанных сущностей. Да даже без этого — «чистая» модель как сущность бизнес-логики гораздо удобнее, чем ActiveRecord с магическими свойствами. Не говоря уж о том, что, даже безотносительно SRP, как правило таблица БД не полностью идентична сущности бизнес-процесса (за исключением самых простых случаев).
DB::something()
и Yii::$app->db->something()
. Только с переменными можно просто сделать Yii::$app->db2
, а с фасадами надо выкручиваться через DB::connection('db2')
. И выглядит нелогично, вроде вызов статический, а меняет состояние.Нанимать PHP-разработчика и создавать свой функционал с89 нуля и надеяться, что стартап взлетит и другой разработчик в случае чего сможет в нём быстро разобраться
Вот и получается у мигрирующих разработчиков тут у на с 2 касты, точнее три (первая не в счёт)
1. Я хозяин, модно, давайте всё ломать и строить заново. Просто модно.
2. Product Manager или Team Leader — давайте подумаем. Т.к. им надо принимать решение о выборе фреймворка под задачу. Потянет или нет? Платформы, удобства для Linux/Windows пользователей в команде.
3. TL набирает команду под проект. Если уже знаешь — почти всегда пройдёшь. Не знаешь — учись, сейчас это модно, всего полгода (и много разной шелухи), и сможешь стать джуном нашего проекта.
У меня религия, наверное, не позволяет использовать перегруженные фреймворки в простых задачах.
Может, я работаю именно с такими.
А теперь разрешите вставить пару (на самом деле, нет) слов о стилистике текста и об идеологии, которая в нём заключена:
Надо вкладываться в долгосрочные перспективы, а не сиюминутные веяния. Развиваться, а не ловить хайпы. Пока все, как нервно-поражённые истерички бегают тесной толпой то на руби, то на шарп, то на ноду и js, надо изучать алгоритмы, подходы и набирать опыт. Тихо, не особо спеша, медленно, но верно, успевая, при этом, заняться ещё и другими делами и увлечениями. Не пренебрегая старым — ведь качество продукта зависит не от фреймворка по большей части и не от языка даже, а от программиста. Эти хипстеры уйдут к чёрту из профессии, как только оно станет не модным или когда средняя ЗП поползёт вниз, вот тут-то вы и пригодитесь втройне. Да, я своими глазами видел, как непонятно откуда взявшийся человек запилил отличного демона для наших нужд на делфи, Карл! Я ненавижу делфи, но факт есть факт. Демон работает бесподобно, выполняет свои функции, и при этом, человек, его написавший, реализовал свой интерес — программирование на любимом ему языке.
Теперь про asm — ну, в коммерческом проекте, не связанном с железом и чипами никто и не будет писать на асме, а если интересно для собственного развития и интереса — можно запилить и веб-сервер. Всё польза. Ну, если времени у вас дохрена. Но вот на Си — пожалуйста — куча работы: низкий уровень, железо, что-то, что требует большой скорости, драйвера, движки и т.д — дерзайте. Я лично обожаю Си, и считаю, что он никогда не умрёт.
Про поезд: мне кажется, увы, с момента, когда я увлёкся программированием — а было это очень давно — система ценностей и взгляды в комьюнити (по крайней мере, русском) сильно поменялись. Если тогда, я помню, главным было качество кода, знания, страсть к профессии и вечное, типа актуальных всегда подходов, базовых знаний и умений, а щас всё упирается в рынок, моду, ноду и тенденции на языки. Никто не боится говнокодить, бегать по верхушечкам и кричать что-то про корабль современности более флегматичным людям, зато до смерти боятся «опоздать на поезд», «отстать» от моды, до сих пор сидеть на «древнем питоне», вместо прекрасной ультрамодной ноды, и так далее. При всём при этом, я нода и современный js — прекрасны по моему мнению, читаю материалы по ним, но от этой нервной риторики «скорее, скорее, опоздаем!!» уже так сильно тошнит, что хочется кому-нибудь врезать!
А в итоге-то — что там успевать? Если ты не работаешь на проекте, где тебя круглые сутки заваливают текучкой — ты в состоянии хотя бы раз-два в неделю освоить новую статью, новую либу или пошерстить на гитхабе, покопаться в чужом коде, почитать книжку часок и повелосипедить, не в ущерб свободному времени. А значит, ты успеваешь на этот самый «поезд», не нарушая свою и чужую психику. Если такой возможности нет, и ты сидишь, тянешь воз с 10 утра до 11 ночи — значит, что-то пошло не так: или берите ещё людей в штат, или увольняйтесь. Это просто решить.
Так что, фреймворк, язык, библиотеки — это чистая вкусовщина. Поверьте, не сильно они все отличаются, любой опытный адепт любого языка и фреймворка справится с задачами примерно одинаково, если это не что-то совсем уж специальное, подо что есть специальные языки. И гнобить людей за «неправильный выбор» фреймворка\языка — последнее дело.
Теперь про простоту: мой зад потихоньку поджаривается, как только я это слышу. Потому, что этот лозунг — любимая отмаза всех халявщиков, случайных людей, пришедших в программирование из-за ЗП и простоты трудоустройства. «Почему написал логику во вьюхе? Какого хрена ты скопипастил код, по что у тебя весь код в синглтонах, а в них всё залито толстым слоем хардкода?» Ответ один: «Так проще, упрощай, велели нам статьи на хабре» А написать лишние строк 100, зато правильно — это типа уже не тру. Моя кровь закипает. Каждый, кто пришёл в программирование из страсти к кодингу и разработке упрощает только тогда, когда это полезно и удобно ему, а не из принципа (из принципа можно и переменные a,b,c называть для краткости). Вот адепты с++ или джавы, к примеру, совершенно не обламываются писать длинные синтаксические конструкции, они привыкли, и хорошо в них ориентируются, значит ли это, что они хуже питонистов? Вот ни разу, они тоже заворачивают всё в либы, и применяют передовые подходы.
Извините, накопилось)
Каждый раз я сначала мыслю, как бы я это сделал «там», а потом придумываю, как это перевести на лару.
Это проблема всех Yii'шников, которые переходят на любой другой нормальный фрейм. И это не было бы проблемой (например, используя Laravel можно использовать подходы Symfony, Zend или какой-нибудь Spring смело, и наоборот), если бы в Yii было бы сделано что-то грамотно, но увы.
Тем более, что особо разницы я не почувствовал, на вкатывание после yii мне понадобилась одна неделя сразу после устройства на новую работу.
А никто не говорит, что Yii не выполняет свою задачу. Выполняет. Только почти что каждую задачу можно решить проще и элегантнее с перспективами на вырост. В случае Yii этого не получится. Зато то, что умеет Yii — делает быстрее всех. Ну, примерно как JQuery среди React, Angular, Vue и прочих.
Если учитывать это, то утверждение "не надо переносить подходы Yii на другие фреймы" становится чуть менее радикальным, верно?
Может, я и не прав, но для тех задач, что у меня были — шо то, шо то, просто чуть разные подходы. Будь я евангелистом паттернов (вот чтоб прям не отходить от них никогда), я б бугуртил, конечно.
Угу, на Yii клепать бложики одно удовольствие, захреначил круд, гриды и вперёд. У ларки в этом случае надо чуть подумать, круд фигачится не одной, а двумя командами, вёрстку тоже сам, но зато этот сайт может через год запросто превратиться в реактивный самолёт, а от кода можно получать эстетический оргазм, которым даже Symfony не может похвастаться: Laravel vs Symfony (как минимум по той причине, что в симфони почти невозможно избавиться от сервис локации в контроллерах)
Покажите мне как заинджектить такую шляпу в сервис и считайте, что убедили, что DI у симфони невероятно крутой. Я обещаю молчать в тряпочку.
class MyService
{
public function getUsersFromDatabase(UserRepositoryInterface $users)
{
dump($users); // DoctrineRepository
}
public function getUsersFromFile(UserRepositoryInterface $users)
{
dump($users); // FileRepository
}
}
+)
P.S. Подсказка: Кажется это не DI, а надстройка над методами контроллеров (раньше по крайней мере так было, парам резолвер, если не путаю).
Вы можете привести пример, где без этого действительно нельзя было бы обойтись и не хватило бы, скажем, инъекции в конструктор?
И я, кстати, не утверждал, что в Symfony DI лучше, чем в Laravel. Речь вообще шла не о возможностях фреймворков, а о практиках, принятых в том или ином сообществе.
Вы можете привести пример, где без этого действительно нельзя было бы обойтись и не хватило бы, скажем, инъекции в конструктор?
Например сервис, отвечающий за предоставление доступа к внешнему ресурсу (например какой-нибудь синхронизатор данных БД и внешнего источника):
interface SomeServiceSyncrionyser
{
public function __construct(HttpClient $client);
public function get(string $uri, ...): void;
}
Который, например, должен легко расширяться и патчиться. Естественно ресурс в каждом методе будет требовать какие-то внешние зависимости, например репу пользователей для синхронизации пользователей или репу артиклов, для синхронизации статей.
Вариантов можно очень много придумать где нужна двойная диспатчеризация.
Да что далеко ходить, до недавнего времени не было даже инъекций в методы контроллера, все говорили делай инъекции в конструктор, а потом это всё превращалось либо в километр аргументов в оном, либо чувак забивал и вхреначивал весь контейнер (trait ContainerAware до сих пор через сеттер это делает), либо самые умные сквозь реквест это пробрасывали.
Я к тому, что бывает нужно, на практике столкнулся с таким и кроме фигачивания фектори от фектори (sic!) варианта не оказалось сделать удобно =\
Сервис отвечает за работу с пользователями, методы:
1) Синхронизировать список: Требует репу юзеров + конфиги юзеров
2) Синхронизировать текщего: Требует репу юзеров + инфу о текущем аутентифцированном + конфиги юзеров
3) Синхронизировать N: Репа + конфиги юзеров + сторонний юзер
4) И ещё можно тучу придумать.
Кажется, с этим сервисом что-то не так)
Я не посягаю на вашу любовь к ларавелю, просто увеличиваю присутствие любителей других фреймов в данном треде. Вот любители Ларавеля очень агрессивно зачастую пытаются доказать, что yii не нужон, и что «только лв», некоторые откровенно окатывают говном из ушата его сторонников, заявляя, что на всё сообщество там пять нормальных программистов (в другом треде), ещё один писал статью, что не сладил с yii, и для него он превратился в ад. Забавно это всё. Я же не говорю таких вещей, просто — мне норм, у меня всё на нём получается. В том числе и в проектах, выходящих за рамки крудоты и бложиков.
Я вам больше скажу: Laravel поднялся за счёт хайпа и агрессивного маркетинга. До третьей версии об этом фреймворке мало что было слышно. Тем не менее мне самому он, в принципе, нравится. Многие вещи сделаны довольно «сахарно».
Про DDD и гексогоналку. Мне казалось, что суть этих технологий как раз в отсутствии привязки к стораджам и всяким eloquent или doctrine. Мне кажется вторая даже вреднее, так как люди тешат себя иллюзией о правильной архитектуре, а по сути вместо спагетти кода пишут лазанью.
Про документацию вы правы, там примеры демонстрируют ТОЛЬКО конкретный инструмент и не связаны друг с другом. Но так везде, в доке по php даже есть приписка про этот момент. Но есть laracast демонстрирующий хорошие практики. В доке был ещё пример полноценного приложения, но его найти не могу.
Ну а в остальном ваши придирки субьективны и зависят от разработчика. У меня за спиной десяток проектов с laravel и пяток с symfony, в ларавеле ниже порог входа и куча говнокода от авторов не осилевших доку до конца, в симфони же беспощадная слоёная архитектура от авторов не осилевших php и в поддержке они на порядок сложнее, даже хуже битрикса.
Про DDD и гексогоналку. Мне казалось, что суть этих технологий как раз в отсутствии привязки к стораджам и всяким eloquent или doctrine. Мне кажется вторая даже вреднее, так как люди тешат себя иллюзией о правильной архитектуре, а по сути вместо спагетти кода пишут лазанью.
Безусловно Вы правы, но Doctrine (если использовать ее правильно) — это единственная ORM на PHP, которая позволяет приблизиться к принципу persistence ignorance. В конечном счете, для доменного слоя репозиторий — это только интерфейс, и его может в инфраструктурном слое имплементировать класс, наследующий в то же время EntityRepository. В случае же с другими ORM придется вручную «пересыпать» данные внутри репозитория в доменную сущность.
Но есть laracast демонстрирующий хорошие практики.
Помню, долго смеялся, когда автор ларакаст запилил курс с примерами по DDD в ларавеле. Команды у него в себе носили модели, а репозиторий возвращал экземпляр Eloquent'а. Называется — «слышал звон, да не знаю, где он».
Сам по себе DDD тут ни при чем. Штука в том, что PHP иногда — как российская глубинка: до него и его разработчиков некоторые вещи доходят с опозданием) В Java/.NET разговоры о DDD идут уже лет 15. Например есть хороший блог Александа Бындю на эту тему. Я думаю, это обусловлено, прежде всего, сферой применения.
Мы спорили о том, что DDD убьёт PHP ещё во время бет symfony 2, с тех пор практически все перешли к javascript или devops. При этом в большом мире начали уходить от энтерпрайзщины и спрингов, появился котлин.
Сейчас очередная волна, которая загнала язык в могилу, так как мы утратили преимущества — быстро, дешево, легкое в поддержке и маштабировании.
Почему и когда мы их утратили?
Мы спорили о том, что DDD убьёт PHP ещё во время бет symfony 2, с тех пор практически все перешли к javascript или devops.
Практически все — это кто?
При этом в большом мире начали уходить от энтерпрайзщины и спрингов, появился котлин.
Ну и что, что появился. Все уже взяли и переписали всю свою кодовую базу на него?
В Симфони есть компонент для работы с кешем.
Мне кажется вторая даже вреднее, так как люди тешат себя иллюзией о правильной архитектуре, а по сути вместо спагетти кода пишут лазанью.
Примеры лазаньи есть? Не сочтите за рекламу, но у меня есть пример того, как можно отделить бизнес-логику от хранилища: https://github.com/franzose/symfony-ddd-wishlist. Не знаю, насколько хорошо или плохо это вышло (вы можете оценить), но это можно сделать. И мапится на сущности/value object'ы всё прекрасно. На фронтенде только пока не вся логика, заложенная в «бизнес», реализована.
Symfony Microkernel и грядущий Symfony 4 — шаги в очень правильном направлении.
Я не хочу вдаваться в демагогию и что-то развёрнуто объяснять, но вы сильно ошибаетесь. По-этому — кратко:
Как симфони-разработчик и неоднократный докладчик на всяких симфонёвых митапах/конференциях, заверяю, что Laravel превосходит по всем параметрам Symfony, начиная с возможностей, заканчивая гибкостью и качеством конечного кода (естественно не ньюби, а адекватного разраба).
В качестве пруфов просто предлагаю сравнить возможности хотя бы одного компонента, давеча даже статья была https://habrahabr.ru/post/331982 Ну а после осознания того, как сильно Symfony DI отстаёт от Laravel — не писать подобные глупые высказывания, вроде "И в следующий раз ты просто берешь Symfony, чтобы не переизобретать велосипед". Думаю хоть тот факт, что процентов 80% того, что появилось в Symfony, с версии 2.8 — это из Laravel (начиная с того же автовайринга, .env и заканчивая flex и encore) убедит вас пересмотреть свою позицию.
Думаю хоть тот факт, что процентов 80% того, что появилось в Symfony, с версии 2.8 — это из Laravel (начиная с того же автовайринга, .env и заканчивая flex и encore)
Тем не менее, это появилось и этим можно пользоваться. В Symfony 3.3 конфигурация DI стала проще.
Боюсь в данном случае именно Laravel задает тренды в PHP пусть даже заимствуя их из соседних языков.
Быть первопроходцем не значит задавать тренды :) Это как с современными смартфонами — не Эппл придумала подобный формат, но Эппл задала тренд :)
То есть если условный Samsung выпустит ноутбук без разъема для наушников и все начнут этому следовать в мире ноутбуков, то не Samsung задал этот тренд?
Laravel — это в принципе такой аналог Ruby on Rails, тогда как Symfony — что-то вроде Spring, наверное. Doctrine вдохновляется Hibernate.
backtrace из laravel — там же чёрт обе ноги сломит от вызовов callback и callable… День потратил чтоб разобраться почему laravel не смог в очередность инициализации зависимостей (при первом запуске, до создания кэша).
Про Eloquent выше всё сказали.
Laravel берёт не качеством а хайпом, но всё таки хорошо что он есть — конкуренция, это стимул к улучшениям.
1) То что вам хватало — это замечательно. Целью было сравнение возможностей только одного компонента, а их, как известно, чуть более одного и у каждого возможностей и удобства больше. Даже у тривиального http-kernel, который, напоминаю, взят из Symfony.
// Обычное определение типа тела запроса:
// Symfony
$contentType = $request->headers->get('CONTENT_TYPE', 'text/html');
$isJson = $contentType === 'application/json' || substr($contentType, -5) === '+json';
//Laravel
$isJson = $request->isJson();
// Его чтение:
$result = @json_decode($request->getContent(), true);
if ($result === false) { ... }
// Laravel:
$result = $request->json()->all();
1.1) А что говорить про PSR-11?
2) Создания какого кеша? Есть кеш вьюх, есть кеш провайдеров, есть кеш ПО, есть опкеш кода. В любом случае — какая-то глупость, по-моему. Трейс у ларки очевиден, а учитывая отсутсвие таких штук, как ocramius/proxy-manager — так вообще тривиален доне́льзя. Единственным исключением составляют ошибки в конфигах. Вот там если допустить ошибку, то без опыта работы с ларой не понять что происходит.
3) Исходники у Laravel, в целом, качественнее симфонёвых (были где-то сводные таблицы кохесижена и прочих штук, но что-то не гуглится, так что без пруфов, простите). Если говорить об архитектуре, то у симфони в ядре она получше. Тот же http пайплаин у лары — вообще трешак адовый, лучше туда не лезть.
Пара совершенно тривиальных примеров
Это можно один раз завернуть в ArgumentResolver
и получится почти то же самое.
А можно не заворачивать, т.к. всё уже и так сделано =)
А если запрос приходит в XML, что делать будем?)
Ну можно, например заэкстендить 3мя строчками:
Request::macro('isXml', function () {
return Str::lower($this->getContentType()) === 'xml';
});
$request->isXml(); // bool
И теперь есть поддержка xml запросов. Осталось вынести это всё в провайдер (в бандл) и вуаля. Симфони, увы, такое не доступно.
С одной стороны удобно, а с другой — такими макросами в классы можно понапихать любые методы, которые даже IDE не подхватит.
Прям дискриминация, для json стандартный метод есть, а для xml нет :)
1.1 там два метода, понятно что это минимум, но я не вижу проблемы в простом DI. Модули можно заменять, если не устраивают.
2. opcache и view cache — именно они! [/sarcasm]
Понятный трейс у ларки… работал с v5.2, если вы это называете понятным — то у нас разные представления о понятном. Уточню что речь идёт о trace самого FW, а не разрабатываемого приложения.
3. Когда заглядывал (v4 — v5.2) — разработчики явно не руководствовались: «Explicit is better than implicit.», читать код на досуге — желания не возникает.
Статические анализаторы это как статистика — всё зависит от того кем написано уравнение. В моём случае, реальное применение показало обратное — приложения на symfony работают стабильней и обновляться проще.
Отвечу про привязку к вендорским инструментам. Привязки нету, вы можете запускать лару как хотите, скачивать в зип архиве и тд и тп. Просто она позволяет в два клика использовать какой-то готовый пресет с помощью и без утилит. По итогу выбор за вами.
Laravel предлагает нам установить Homestead.
Можно еще сказать, что есть готовое окружение для Docker'a — http://laradock.io/
Очень понятная инструкция по настройке и установке, и как по мне это лучше чем качать целую VM для локального сервера.
Кажется вы забыли прочитать комментарий. Попробуйте ещё раз первое предложение, в котором явно написано про то, что не надо ни ставить VM, ни ставить ничего локально, потому что докер — это ни то (на линуке, под виндой это всё же виртуалка), ни другое.
Тогда инфа для таких чайников как я: Докер — среда виртуализации, которая работает на одном ядре с ОС, тогда как Vagrant работает на отдельной виртуальной машине, что в свою очередь жрет дополнительную производительность.
А под линуком докер не под KVM пашет что ли? Я просто тоже чайник =)
Докер — не система виртуализации в принципе. Грубо говоря, это продвинутый chroot, система предоставляющая исполняемым файлам изолированное окружение, но не изолированную машину.
1. Если я правильно понял, на фасады ругань из-за «магии». Вопрос: какое вам дело до «магии», если вы все равно точно знаете, какой будет результат при их использовании? Ну или объясните, в чем проблема, если я неправильно понял.
2. Объясните про энтерпрайз-стиль. Что это такое, конкретно? Что он дает (какие плюсы)? И почему на Ларе нельзя писать в этом стиле?
- Один из признаков энтерпрайз-стиля — разделение приложения на слабосвязанные слои. Дефолтная для Laravel ORM предлагает свою реализацию паттерна ActiveRecord, который по определению сильно связывает уровень бизнес-логики с уровнем хранения данных. Возможно, при должной дисциплине и(или) абстракциями поверх ORM можно отделить бизнес-логику от уровня хранения данных, вроде бы относительно легко прикрутить Doctrine для замены дефолтной, но в документации, постах и т. п. я не встречал такого подхода, а ровно наоборот подается как преимущество тесная свзяанность. Типа всего нужно написать $order = new Order(); $order.save(); и новая запись сохранена. В Doctrine это займёт минимум на строку больше.
Я не понял, где связанность уровня бизнес-логики с уровнем данных в строчке "$order = new Order(); $order.save();". Именно в классе/модели Order? Если так, то что предлагает энтерпрайз стиль? Я вижу тут только удобство, не связанность. Модель не знает, как она хранится, в какой СУБД. Последняя, в свою очередь, ничего не знает о модели.
Да, имеено. ActiveRecord подразумевает две области отвественности у класса — сущность бизнес-логики и реализация персистентности (абстрагированной от конкретной СУБД через несколько уровней абстракции или прямо с SQL-кодом в классе — детали реалзиации). Сущность (модель) может и не знать в какой СУБД она хранится, но она знает, что она хранится, что может сохранить свое текущее состояние вызовом своего метода save().
DataMapper+Repository (обычно ещё некоторый набор паттернов для оптимизации удобства и целостности) же предлагают полную абстракцию от механизма хранения. Сущность — обычный класс, абсолютно ничего не знающий о том, что есть где-то СУБД или иное хранилище, у него нет методов типа save или delete. Репозиторий — класс, предоставляющий интерфейс коллекции, массива объектов этой сущности. Для всего остального приложения, кроме слоя хранения, есть по сути "вечный" массив простых объектов в ОЗУ, откуда оно может их брать, удалять и помещать им созданные.
$em->flush()
чтобы сохранить изменения.$order->save()
вызывает только инфраструктурный слой. Я не защищаю ActiveRecord, если что, просто в обоих случаях надо знать, как сохранить объект.А если он используется только в инфраструктурном, то это уже не ActiveRecord, а Row Gateway. А если использовать его таким образом, то зачем тем более нужен Eloquent, можно обойтись и Doctrine\DBAL или Zend\Db.
Ну так и $order->save() вызывает только инфраструктурный слой.
Это только при полном административном запрете дергать save() из других мест, прежде всего из самой сущности, что в целом нонсенс. На практике такого запрета либо вообще нет, либо он часто нарушается по принципу: "сейчас так сделаем, потому что дедлайн, а потом поправим", "потом" никогда не наступает.
просто в обоих случаях надо знать, как сохранить объект
В нашем случае нет такого понятия как "сохранить объект", есть "добавить объект в репозиторий". Всё. На уровне реализации репозитория add(SomeEntity $entity) как минимум дергается $em->persist($entity). И где-то по заверешнию бизнес-транзакции автоматически дергается $em->flush();
Да, в некоторых случаях надо где-то вручную дергать $em->flush(), но это где-то точно не на уровне бизнес-логики, а либо в уровне инфраструктуры, либо в уровне сервисов приложения. И всё равно это не "сохранить объект", а "сохранить все изменения".
Но надо знать, что он есть, следить, чтобы он где-то вызывался после изменений. Потому что если незнакомый с фреймворком программист просто добавит объект в репозиторий и всё, то сущность не сохранится.
прежде всего из самой сущности
Ни разу не встречал, чтобы кто-то писал $this->save()
в модели. Административный запрет дергать save()
это примерно то же самое, что административный запрет пробрасывать entity manager и дергать flush()
. Просто я к тому, что ActiveRecord создает не столько проблем, как принято считать, иначе бы давно все от него отказались, как от goto.
Потому что если незнакомый с фреймворком программист просто добавит объект в репозиторий и всё, то сущность не сохранится.
Именно, что сохранится. Нужно сильно постараться, чтобы не сохранилась.
Ни разу не встречал, чтобы кто-то писал $this->save() в модели.
Повезло. Мне встречалось и встречается постоянно.
Административный запрет дергать save() это примерно то же самое, что административный запрет пробрасывать entity manager и дергать flush().
Близко, но не одно и тоже. Проброс требует каких-то осозннанных действий, а $this->save можно получить просто по автодополнению в IDE.
Именно, что сохранится.
Возможно я плохо знаю Symfony, но разве там есть встроенный автоматический вызов flush()? В примерах в документации flush() вызывается вручную в действиях контроллера.
Проброс требует каких-то осозннанных действий
Так вызов save() тоже. Я не представляю, зачем мне надо вызывать save(), если я не хочу в этом месте алгоритма сохранить модель. А если хочу, то и persist() вызову.
Кстати, а приведите пожалуйста пример, где вызывается $this->save(). Просто интересно, в каких случаях так делают.
В примерах в документации flush() вызывается вручную в действиях контроллера.
Общая беда многих документаций — примеры по основам фреймворка плохо подходят для реальных задач :( А так можно настроить, например, вызов flush при возникновении события типа нормального конца работы контроллера.
Я не представляю, зачем мне надо вызывать save(), если я не хочу в этом месте алгоритма сохранить модель.
Вы можете захотеть вызвать save внутри сущности, чтобы не забыть потом вызвать её снаружи сущности, особенно в случае сложных алгоритмов, где вам надо либо сохранять на месте, либо передавать наружу информацию, о том что эту сущность надо потом сохранить, что какой-то метод $order->cancel() изменяет сущность в отличии от метода $order->validate(). Причём не просто изменяет, а изменяет так, что это нужно сохранить.
Либо просто захотите уменшить повторяемость кода. Напишите в десятке мест что-то вроде $order->cancel(); $order->save(); и решите объединить действия по отмене зааза и сохранения результатов этих действий в один метод. Может просто добавите $this->save() внутрь cancel, может создадите метод $cancel->save(); Не может такое желание возникнуть?
А если хочу, то и persist() вызову.
Для вызова persist() внутри сущности вам нужно будет инжектить менеджер в сущность обычно с высокого уровня, а $this->save всегда под рукой — соблазна больше :)
либо передавать наружу информацию, о том что эту сущность надо потом сохранить
В таких случаях обычно save() вызывается всегда. Если есть измененные поля, происходит UPDATE, если нет не происходит.
$order->cancel(); $order->save(); и решите объединить действия
Ага, понял о чем вы. Действительно, встречал такое пару раз. Но логичнее save() сущности вызывать там, где присходит валидация запроса на изменение — в контроллере или в методе save() класса формы с правилами валидации.
вам нужно будет инжектить менеджер в сущность
Не, я не о том. Если в алгоритме нужно сохранить модель, то в этот алгоритм надо обязательно пробросить менеджер. То есть нет никакой разницы, в одном случае у меня в алгоритме будет persist(), в другом save(), и в обоих случаях это осознанные необходимые действия.
Кстати, делал как-то UnitOfWork для ActiveRecord. Все save() вызываются внутри него в методе commit(). Получилось довольно удобно.
Если в алгоритме нужно сохранить модель, то в этот алгоритм надо обязательно пробросить менеджер
Тут вопрос куда и какими средствами его пробрасывать. Доктрина сопротивляется простым путям проброски менеджера внутрь сущности. Это возможно, но сложно в общем случае. В подавляющем большинстве случаев проще снаружи сущности вызвать методы менежера, чем инжектить их внутрь. Реализации же ActiveRecord делают всё, чтобы работа с менеджером была из сущности удобна, по крайней мере в кейсах типа $this->save()/$this->delete(), собственно это суть паттерна.
1. Нет, не столько из-за «магии», сколько из-за сильной связанности. Если мы, например, инъектируем сервис по интерфейсу, то можем легко подменить реализацию, вообще ничего не меняя в зависящих от него классах и прочем. Причем интерфейс может находиться именно в нужном слое, ничего не знающем о реализации. Таким образом достигается слабая связанность.
2. Hexagonal, DDD, CQRS/Event-sourcing и тому подобные архитектурные паттерны. Он дает возможность писать большие, поддерживаемые, слабосвязанные проекты, с бизнес-логикой сложнее, чем круды. Писать на ларавеле в этом стиле можно, но мало кто так делает — ведь это же так здорово — дергать фасады где хочешь.
Laravel — экосистема, а не просто PHP-фреймворк