Комментарии 160
Вы советуете начинать изучение фреймворков с тех, что сложнее, и велика вероятность, что человек не осилит, и пойдет дальше говнокодить на коленке. Как по мне, то лучше сначала начать с простого, постепенно усложняя, чем сразу нырять в омут с головой.
И да, я более чем уверен что меня мало кто послушает. Проще «говнокодить на коленке» на Yii, чем задумываться над тем, почему же в шаблоне нельзя делать «SomeModel->listAll()» и многие другие славные вещи…
Yii не отвратителен, но изначально (в том числе в документации) он дает массу вредных советов и не запрещает разработчикам стрелять себе в ногу, там где им хочется.
Луше вложить немного усилий в самообразование и получить хороший старт для дальнейшего роста.
С этим я согласен, если бы я изначально по такому пути пошел, то сэкономил бы годы. Даже если бы я прочитал эту статью на заре становления своей карьеры, то вряд ли прислушался. Хочется же побыстрей, все и сразу.
Да вот те же самые фасады. Мало кто понимает, что их стоит использовать лишь в качестве хелперов, например в консольке или миграциях, а для бизнес-логики только DI. А потом открываешь какой-нибудь проект и видишь методы контроллеров по 500 строк каждый, которые при этом ещё и копипастятся. Хотя бы сервисный слой для этого? Какой сервисный слой? Не… не слышал =)
Кажется, что это «бич» любого решения с низким порогом входа, но склонен согласиться с тем, что в случае Yii — там на порядок сложнее вывести такой проект в адекватное состояние. Хотя тут я не слишком объективен.
Симфони самый развязанный в плане архитектуры
Ну… Вот тут я бы поспорил. Слишком много ограничений у симфони. Простой пример: Зарегистрировать UserInterface из секьюрити в контейнере, чтобы потом он мог резолвиться через автовайринг или парам резолвинг. Можно сделать, но это оверинжинеринг и проще сделать фектори (или дёргать токен сторадж).
В этом плане у ларки непосредственно архитектурных ограничений ещё меньше и возможностей больше. У Symfony другое преимущество — он более развязный с зависимостями. Т.е. сами компоненты на порядок гибче, но их и так же на порядок меньше.
Зарегистрировать UserInterface из секьюрити в контейнере, чтобы потом он мог резолвиться через автовайринг или парам резолвинг. Можно сделать, но это оверинжинеринг
А в чем именно оверинженеринг? Простенькая фэктори + строчка в конфиге
Symfony\Component\Security\Core\User\UserInterface:
factory: ['@App\UserProvider', 'get']
Ладно, другой пример. Надо для роутов добавить метаинформацию произвольного формата, при этом она должна мерджиться при наследовании (т.е. инклудах). Ну вот простой пример:
api.example:
resource: "@AppBundle/Resources/config/routing.yml"
prefix: /api
defaults:
_middleware:
- AppBundle\Middleware\QueryLogs
- AppBundle\Middleware\JsonResponsePrettifier
- AppBundle\Middleware\ExceptionsLogger
- AppBundle\Middleware\CrossOrigin
- AppBundle\Middleware\ThrowableToExceptionsTransformer
Проблемы:
1) Можно указывать только строки или массивы (т.е. нельзя скинуть ссыль на сервис)
2) Внутри подключаемого ресурса эти параметры не мержатся.
Только не надо говорить, что это не Symfony-way и надо на эвенты всё вешать, а конфиги выносить в другое место. Ну вот взбрело такое в голову, присобачить миддлвари. Мы же об архитектурной гибкости говорим.
symfony.com/doc/current/routing/custom_route_loader.html
Для
AppBundle\Middleware\JsonResponsePrettifier -> JMSSerializerBundle
AppBundle\Middleware\ExceptionsLogger -> Смотря что вы тут хотите, если ошибки фреймворка то symfony.com/doc/current/logging.html, если свои то делаете EventListener на событие kernel.request например, там можно получить метаинформацию из роута (да, текстовую, но вообще возможности роутинга позволяют создать свой загрузчик роутов который позволяет более гибко описать роутинг)
AppBundle\Middleware\CrossOrigin -> NelmioCorsBundle
AppBundle\Middleware\ThrowableToExceptionsTransformer -> Да это и так есть в symfony, для создания обработчика Exception можно создать контроллер и указать его в конфигурации. (https://symfony.com/doc/current/controller/error_pages.html)
P.S. Имхо, работа поверх кернел эвентов — это фатальная проблема архитектуры фреймворка, т.к. они ограничивают и возможности симфони и отказаться (задепрекейтить) от них невозможно, т.к. сам симфони не умеет как ларка — взять и поменять кусок ядра в новом мажоре, посчитав старый подход тупиковым.
как бы расположение папок в проекте очень далеко от понятия архитектураю И что в Yii что в Ларе любые пути можно переопределить
Большой функционал работает через фасады и IDE-системы не видят методов и свойств в некоторых классах, показывая предупреждения
Все «фасады» лежат в конфигах, в файле app.php. Первым делом при старте нового проекта — берёте и удаляете вообще всё, что там лежит. И никаких фасадов.
«Фасад» в терминах Laravel — это статический прокси + локатор на сервис внутри DI. Подчёркиваю, внутри DI. Каждый сервис может инжектиться (в том числе через автовайринг) по интерфейсу, такие интерфейсы в рамках Laravel называются «контрактами», так же как бины (bean) в Spring.
Механизм очень похож на symfony, только вместо аннотаций, используется отдельный файл и фасадный класс Route, с набором статических методов.
В классе роутов нет ни одного статического метода. Например: github.com/illuminate/routing/blob/master/Router.php#L139
Нет документации на русском языке.
UPD: Не увидел ссылки в футере. Всё ок =)
Увы, не могу оценить часть про Yii2, т.к. в основном использую другие фреймворки (в частности Symfony), но судя по части про Laravel — его вы знаете крайне поверхностно, что делает эту статью довольно субъективной, без попыток реального сравнения возможностей.
С другой стороны — могу подтвердить, что в Yii2 действительно генераторы кода мощнее, но ничего не мешает в Laravel так же указать ссылки на шаблоны для генерации кода.
поскольку ни в Yii2 ни в Symfony этого нет.
Сам механизм, который делает всё тоже самое и содержит точно такие же проблемы есть и в Yii и в Symfony.
\DB::xxx();
Yii:
Yii::$app->db->xxx();
Symfony:
$container->get('doctrine')->xxx();
Это называется сервис-локацией и порождает скрытые зависимости. В случае Laravel — это заменяется на обычный DI, в Symfony — точно так же на DI, при этом сейчас (в последних версиях) обращение к контейнеру через get — вызывает ошибку доступа. Надо явно прописывать что этот сервис публичный.
public function __construct(Connection $conn)
{
$conn->xxx();
}
Symfony:
public function __construct(EntitManagerInterface $em)
{
$em->xxx()
}
Yii2:
А тут я фиг знает как, т.к. не шарю Yii. Покажете пример?)
$connection=Yii::app()->db;
Но это как раз через фасады, которые в конфиге задаются. Либо расширением класса ActiveRecord, чем и являются модели. Тут просто не доктрина, поэтому сложно провести аналогию, принцип немного другой.
А в той же ларе или симфони, можно получить низкоуровневый объект PDO
Я не совсем об этом речь вел. Модели я чисто для примера взял. В Ларе например и в роутах используются методы Route::post(/***/), которые по факту не являются статичными. Я в общем о том, что такие явления есть
Как-то так:
Yii::$container->get('db');
vs
public function __construct(\yii\db\Connection $db)
Сложно сказать. Может я не знаю, но способ получить подключение к базе можно так же через сервис локацию
Вопрос как раз в другом. Как это делать не через эту самую сервис-локацию. Потому что, как я уже описал выше — это крайне плачевный подход для долгоживущих проектов.
Ну вот есть какой-то класс, например database query logger, зарегистрируем его в контейнер (можно же?) по имени "dbQueryLogger". Как сказать проекту, что получая Yii::app()->dbQueryLogger
(или как-то так, поправьте если ошибаюсь) нужно создавать этот объект и прокидывать туда соединение с базой + PSR LoggerInterface.
UPD: О, VolCh ответил на вопрос. Спасибо. А в методы прокидывать так же можно?
Что-то типа
$controller = new class
{
public function indexAction(\yii\db\Connection $db)
{
}
}
Yii::$container->invoke([$controller, 'indexAction']);
? Не уверен, что сработает с анонимным классом, хотя не вижу причин почему нет :)
По Yii 2 пример ровно такой же :) Инъекция через рефлексию в конструктор поддерживается.
В Yii2 есть yii\rest\ActiveController — который позволяет быстро настроить REST FULL API...
Вот как раз REST FULL API он и позволяет делать.
А вот RESTful все таки удобней разрабатывать используя функциональные возможности Laravel

С первой страницы официального сайта симфони. Означает, что используются не компоненты, а именно фремворк. А Вот Yii использует именно компоненты.
А низкоуровневый — это как аналогия языков программирования. Типа PHP, JAVA, PYTHON языки высокого уровня, а C, C++ или Асемблер низкоуровневые языки. Тут дело в доступности данных низкого уровня (дампы или ячейки памяти, отдельные биты в кластерах), а не в том, как роуты задаются
Symfony — это набор компонентов, который называется "фреймворком". Так же как, например, Illuminate — тоже "фреймворк".
Сборка приложения в симфони называется symfony flex или symfony standard. У Illuminate же называется Laravel. Что тоже называют фреймворками, хотя это только сборка.
https://github.com/symfony/framework-bundle — вот фреймворк симфони
https://github.com/laravel/framework — вот фреймворк ларавел
А github.com/symfony/framework-bundle — это FrameworkBundle использующийся в составе фремворка
Symfony более низкоуровневый фреймворк
Имхо автор не имеет реального опыта работы с симфони и краем глаза увидел что компоненты симфони используются в Laravel и т.д… Symfony фреймворк в том же смысле что и Laravel позволяющий реализовывать хотя бы тот же MVC паттерн
Так чем у симфони уровень ниже чем у ларавеля? какие, например, абстракции не предоставляет симфони?
Так каких "каких-то"? У каких типовых задач по разработке на PHP нет готовых решение в symfony и есть в yii/laravel?
В Symfony есть абстракции над http и сессиями, роутинг, шаблонизация, кеширование, работа с формами, валидация, работа с ФС, контроль доступа, DI, i18n, l10n и переводы, конфигурация, сериализация, работа с процессами ОС, свой http-клиент и работа с DOM, бридж к ORM, бридж к свифтмейлеру, бридж к пхпюнит, бридж к монолог, бридж к твиг, средства отладки и профилирования. Что ещё нужно от фреймворка?
Генераторы не в счёт, они не являются частью фреймворка как каркаса приложения, они часть экосистемы вокруг каркаса.
Но в плане разработки сайта на коленке с простой админкой — это очень сильная сторона Yii. По сути можно сделать на нем простой блог за 30 минут и это не преувеличение.
Интересно, с каких это пор в симфони стали отсутствовать инструменты для решения небольших типовых задач?
А если выбирать из 2х зол, я бы выбрал меньшую — Laravel.
В Симфони есть генератор готовых интерфейсов?
https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html
Встроенный удобный сборщик фронтенда как у Ларавел?
symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html
Это совсем не то, что делает Yii. Этот генерирует только php файлы с классами, а у Yii это и модели и контроллеры сразу с данными и готовое сверстанное представление
https://github.com/symfony/website-skeleton/blob/4.0/composer.json
"require": {
// ...
"symfony/webpack-encore-pack": "*",
// ...
},
"require-dev": {
// ...
"symfony/maker-bundle": "^1.0",
// ...
},
Не поймите меня не правильно. Симфони я очень уважаю. Но для типовых проектов, которые мне приходилось делать быстрее сделать на Ларе или Юии. Симфони лучше подходит для планирования хорошей архитектуры и мощных нагруженных проектов. Для толстых проектов, совмещающих в себе кучу мелких, я бы бесспорно выбрал Симфони. А если писать что-то типа Алибабы, Ебэя или Что-то еще более крупное. Лучше вообще избегать фреймворков, поскольку тут очень важно продумать свою разумную архитектуру, чего не делает один человек. Не думаю что Гугл или Яндекс пишут на каких-то фреймворках, скорее разрабатывают свои. Но это лично мое мнение
Сейчас большинство проектов делается согласно принципу “Api first”. А в нагружённом проекте вообще всегда зоопарк технологий а не фреймворк.
Нет. Большинство проектов делается и будет делаться с генерацией HTML. Потому что большинство — это совсем простые проекты где API не нужен.
В эпоху засилья ангуляров, реактов и примкнувшего к ним вью я бы так уверенно не говорил.
Это совсем не то, что делает Yii.
Laravel тоже так не умеет, на сколько я помню, но его вы почему-то включили в обзор
Было ли это хорошим решением — время покажет. Лично мне нравится, хоть и непривычно что Doctrine и Twig по умолчанию отсутствуют.
Что такое генератор интерфейса?
Для фронта — есть и любой вешний без проблем подключается. Что должны делать эти хелперы а главное зачем? Тот же вопрос про данные.
Помельче: хелперы для работы с конфигами, или какими-то данными.
Что вы под этим имеете в виду?
Где вы видели, что в проекте используется только то, что есть в самом фреймворке?
Тогда к чему такая привязка к инструментам из коробки?
Потому что если сравнивать. То возможности самих фреймов. А если говорить о различных надстройках, то вообще можно придти к выводу что все имеют одинаковые возможности с разной реализацией просто.
Как раз все дело в реализации, как по мне.
Сравнивать можно и нужно не то, что из коробки (особенно если коробок много по факту, скажем различные edition типа web-edition, api-edition и т. п. или full-edition, standard-edition, micro-edition), а то, что предоставляет вендор прежде всего. Если в доках фреймворка X написано про фичу Y "перед использованием подключите Y с помощью composer req x/y
", то это не повод исключать из сравнения.
Сразу предупрежу вопрос о том, почему не рассматриваем Symfony.Ерунда какая-то написана. Мы используем Symfony и в крупных и в мелких проектах и никаких костылей вроде собственных фреймворков не пишем.
Дело в том, что Symfony более низкоуровневый фреймворк, который чаще берут для основы в крупных проектах, например таких, как написание собственного фреймворка для разработки.
Вы вероятно имели в виду бандлы, а не сам фреймворк. Из отдельных бандлов/либ да, можно набросать свой собственный фреймворк (в этом собственно прелесть модульной архитектуры) если уж очень колется, но только зачем? :)
Его в принципе нельзя сравнивать с Laravel и Yii2, так как они используют его компоненты в своих реализациях.Ну вот вы сами ответили на свой вопрос.
На данный момент, не вижу в нем хотя бы одного плюса.
Правда я фанат Symfony DDD/CQRS/Bus/EQ… Потому мое мнение совершенно бесполезно.
На тему крупных проектов, видимо автор застрял в 2015-2016гг. и не знает о существовании Symfony 4.
Соответственно, считать данный пост серьезным, совершенно нельзя.
Но сейчас, выбор мой SF, но если смотреть на другие, то конечно laravel.
Причина проста — организация кода, архитектурный принцип и конечно ioc.
В добавок, удобно реализовать DDD. Хотя тоже надо будет поковыряться и написать обработчик для входящих данных, что бы использовать геттеры
IoC есть и в Yii и в Laravel. В Yii в основном практикуется ServiceLocator. например вызов Yii::$app->get(); или Instance::ensure() в init() или конструкуторе хуже классического внедрения только в том плане, что нельзя будет класс оторвать от фреймворка, а это не так уж нужно если не пишешь библиотеку.
Проектов настолько больших, чтобы DDD принес реальную пользу (ЧСВ не в счет) немного
хуже классического внедрения только в том плане, что нельзя будет класс оторвать от фреймворка
То есть возможность роста проекта настолько, что DDD начнёт приносить пользу вы априори исключаете, гвоздями прибивая классы проекта к фреймворку, на котором сложно работать с DDD?
Сначала реализуется бизнес-логика, которая не зависит от приложения, затем делается остальное.
Вот главная цель DDD.
Конечно, применять в мелких сайтах и петпроектах не имеет смысла.
Но я не говорю о таких проектах, их можно реализовать хоть на html и пару микросервисов. Я даже не считаю подобные проекты работой.
Т.е. вывод прост, вы не представляете что такое DDD и для чего.
Или просто не работали над серьезными бизнес-проектами с миллионными инвестициями.
По вашему серьезные проекты невозможны без DDD?) Большинство проектов на Yii не сделаны по DDD, их вы тоже не считаете работой?) Жгите дальше.
Можно написать хоть обычными функциями на PHP4 (делал банковскую CRM в 2007г.).
Вы мне напомнили людей с развлекательных сайтов, которые читают первую строчку, затем среднюю и последнюю.
Вообще — я не говорил, что YII нельзя использовать и это полное дерьмо.
Я не писал, что невозможны серьезные проекты без DDD.
Вы как западные политики, придумываете то что вам удобно.
Почему для слепых котят, надо все пояснять и выделять жирным текстом?
Конечно, применять в мелких сайтах и петпроектах не имеет смысла.
Но я не говорю о таких проектах, их можно реализовать хоть на html и пару микросервисов. Я даже не считаю подобные проекты работой.
Вообще — я не говорил, что YII нельзя использовать и это полное дерьмо.
Я не писал, что невозможны серьезные проекты без DDD.
Вы как западные политики, придумываете то что вам удобно.
Почему для слепых котят, надо все пояснять и выделять жирным текстом?
Извините, я неправильно понял ваш комментарий.
Доменый слой существует для реализации логики в отрыве от данных и приложения.
Вы пишите логику, основываясь на требованиях бизнеса. Домен, дает прекрасную возможность, подстраиваться под веяния бизнеса.
Но это к сожалению не дает возможности, быстро перестроить логику, если что то кардинально изменится.
Соответственно это время и деньги бизнеса.
Если вас смутила фраза
Вы пишите логику, основываясь на требованиях бизнеса.
То тут имелось ввиду, что в ДДД пишут, не именно вы =)
Пишу статью, образ речи сохраняется и в комментариях =)
Без DDD вы, грубо говоря, не выделяете бизнес-логику в отдельный слой, независимый ни от чего кроме бизнес-требований. Скажем, в типичном Yii/Laravel приложении бизнес-логика очень часто размазана между контроллерами (классами унаследованными от базового класса контроллера) и "моделями" (классами, унаследованными от базового класса ActiveRecord). И хорошо если бОльшая часть в "моделях", а не в контроллерах.
Выделение бизнес-логики в отдельный независимый слой в общем случае не только в случае DDD может применяться, но на практике если видишь такое выделение, то и другие технические паттерны DDD замечаешь почему-то.
Скажем, в типичном Yii/Laravel приложении бизнес-логика очень часто размазана между контроллерами (классами унаследованными от базового класса контроллера) и «моделями» (классами, унаследованными от базового класса ActiveRecord). И хорошо если бОльшая часть в «моделях», а не в контроллерах.
Ну в таком случае можно сказать, что в DDD-проекте она размазана между сущностями и сервисами, и хорошо, если большая часть в сущностях, а не сервисах, чтоб не получились анемичные сущности.
Существенное отличие между нашими фразами — в вашей нет слов "унаследованного от базового класса". В DDD бизнес-логика размазана по слою бизнес-логики и ни от чего не зависит. В типичном Yii/Laravel приложении бизнес-логика размазана между моделью, совмещающей по определению бизнес- и инфраструктурную логики, и контроллерами, реализующими по определению часть UI-логики. И, главное, и там, и там она зависит от классов, предоставляемых фреймворком. Захотите поменять фреймворк (ну или проапгрейдить на мажорную версию) — придётся разбираться где бизнес-логика, а где UI или инфраструктурная.
На актуальных версиях Yii/Laravel/Zend/Symfony можно писать как приложения в которых бизнес-логика отделена от всего остального, так и приложения в которых практически вся кастомная логика в контроллере, но почему-то на Zend и Symfony отделяют гораздо чаще, чем на Yii/Laravel. Как мне кажется, это не просто случайное стечение обстоятельств, а вполне сознательное поощрение того или иного стиля ведущими разработчиками того или иного фреймворка.
Я предпочитаю не закладывать наперед возможность смены фреймворка/мажорной версии, так как это порождает много абстракций, которые замедляют и усложняют разработку (надо больше думать для выделения хороших абстракций), чтобы потом облегчить гипотетическую смену фреймворка, которая может и не понадобиться вовсе. Некоторые проекты на Yii1 спокойно продолжают работать.
Фреймворконезависимость обходится дорого, она добавляет забот. Помимо реализации требований, приходится решать задачи по абстракции.
Да, иногда, она оказывается полезной, но я нахожу такие ситуации довольно редкими.
Правда я фанат Symfony DDD/CQRS/Bus/EQ…
Вот, сразу виден фанатизм. Он ослепляет.
Я пробовал применять DDD в проекте. Что получилось — то же самое что и было без DDD, только работы больше по абстракции домена. Кода стало реально больше. Оверхед был налицо, поэтому для себя я сделал вывод, что DDD нужно применять только тогда, когда есть проблемы коммуникации(!), домен реально сложный и нетиповой.
О недостатках DDD в википедии
Доработали доктрину, реализовали сериалайзер и маппинг бандлы.
На данный момент, проект полностью оторван от приложения. Т.е. домен можно использовать в любом другом месте, подгрузив только нужные зависимости.
Слой приложения, полностью отдельный и не зависит от домена.
Вместе же, это реализует API для HL++ проекта.
Оверхеда какого либо нет. Правда это заслуга хорошо продуманной архитектуре и то о чем я писал выше.
Я вам открою секрет, на текущий момент, я больше фанат Golang и laravel. Но это только в отрыве от бизнеса.
Несколько лет назад, мы потратили 4 месяца, на проектирование архитектуры доменого слоя для SF без кода.
4 месяца без кода, ну это большой риск. И что прототипов даже не писали?
На данный момент, проект полностью оторван от приложения. Т.е. домен можно использовать в любом другом месте, подгрузив только нужные зависимости.
Вот именно, что можно, но нужно ли? Вам это дало какой-то профит, если не секрет, какой? Повторно использовали домен в другом проекте? Так он же уникальный, разве нет? В чем именно получилась реальная выгода, если не секрет?
У нас было время, т.к. проект уже работал (кстати на YIi частично), но он не отвечал двум основным требованиям. Это нагрузка (на 50 обращениях уже не вытягивал именно PHP, не БД. До нас делали по доке проект), вторая проблема, это изменения поведения внешних клиентов которым поставляются данные (booking.com, trivago и др. букинг товарищи).
Время дали год для команды. Надо было придумать и реализовать проект с возможностью быстрой перестройки под тот или иной проект. Особенно это стало хорошо заметно на фоне санкций и нового закона о данных.
Профит — я уже сказал по сути. Быстрая смена работы под определенные бизнес-решения. Домен используется и в др. проекта, как вы верно заметили. Домен не совсем уникальный, он имеет модели, репозитории, логику для определенных вещей букинг бизнеса, что в 90% случаев одинаково.
Для использования домена в другом проекте (условие только SF), надо подменить для своих нужд хендлеры, если это требуется и/или объекты ответа заменить.
Слой приложения пишется свой, у каждого свои потребности.
В каком плане "то же самое"? Если работы по абстракции больше, то значит не то же самое, а абстракция сильнее, нет?
Сначала меня DDD увлек, я думал, он мне поможет упростить работу, а на практике оказалось нет. Проект не настолько сложный и большой, команда 3 человека в одном офисе.
Я так понимаю кроме жирной Сонаты и EasyAdmin больше вариантов нет?
Хотя я особо не искал.
SF в 99% используется для реализации API, остальное swagger + экспорт в postman.
Работа через фасады, большинства обширных классов Laravel. Такое сложное предложение, я поясню! Дело в том, что во многих классах фреймворка используется динамическое создание свойств и методов, в зависимости от каких-то условий.
Проще привести пример. Мы объявляем класс модели работы с базой данных, которая является расширением стандартного класса Illuminate\Database\Eloquent\Model, в котором нет статических методов where, select и т.п., но на самом деле они есть и ими можно пользоваться. Вот такие чудеса. Дело в том, что такие методы образуются из так называемых фасадов, которые считывают обычные методы класса и превращают их в статические. А свойства получаются путем обращения к базе данных.
Автор вообще не видит разницы между фасадами и магическими методами? Статью очень трудно воспринимать, так как автор явно поверхностно знаком с обоими фреймворками.
Плюс Yii2 — в том что он очень лоялен к новичкам, можно генерацию из интерфейсов делать, без консоли, можно минимум js знать, тонны виджетов на каждый чих; и он же — большой минус так как тормозит развитие и изучение сопутствующего стека, оставляя зацикленными на jquery-bootstrap
И очень не хватает для Yii2 аналога laracast
Сам работаю с Yii, очень удобно.
Про механизмы доступа к данным что-то ничего не написали.
Навскидку, по памяти:
- повсеместное, буквально в каждом типе функциональных модулей, использование синглтона sfContext — имплементация Registry. Например, поступает задача в некоторых случаях модифицировать поведение реакции на http-запрос. Добавляешь get-параметр в урл, проверяешь егов контроллее, модифицируешь поведение, поведение непредсказуемое, копаешься, копаешься, а потом оказывается что это параметр используется уже где-то в модели через sfContext::getInstance()->getRequest()->get('hold')
- "магическая" передача динамических свойств класса контроллера в шаблоны
- активное использование методов типа save() в "безобидных" сеттерах или методах типа calcBalance() инстансов ActiveRecord, а то и в геттерах.
Я раньше тоже был только за классическое внедрение через конструктор/методы, но сервис-локатор в конструкторах упрощает код и экономит время. К тому же зависимость можно прокинуть туда, куда ее через конструктор иногда не прокинешь (какая-нибудь библиотека требует, чтобы он был без параметров).
Безусловно, у классического внедрения свои плюсы — можно класс сделать независимым от локатора — максимально реюзабельным. Но это не всегда нужно.
А почему вызовы save() в методах-мутаторах (изменяющих состояние) AR считаете неправильным? И причем тут сильная связанность? Я как раз наоборот, ратую за это. Тем более в Yii, если ничего не поменялось, то к базе запросов не будет.
В конструкторе, да, не так страшно, особенно если DI нет и внедрить его затруднительно, а вот когда в коде обычного метода где-то, вот понадобилось и дернули реестр, то выявить что где повлияет очень сложно.
Неявное сохранение с одной стороны, если метод не назван как-то типа calcBalanceAnsSave() — когда просто calcBalance или getBalance, то как-то ожидаешь, что максимум чтение с базы может быть, но никак не запись, причём может быть каскадная. Множественные сохранения с другой, когда мутаций несколько. Ну а главное, именно сильная связанность — бизнес-логика получается сильно связанной с ActiveRecord. Ладно бы просто в конце сеттера вызывался save, так где-то в середине, а если в конец перенести, то или не работает вообще, или сохраняет лишнее.
Буквально под новый год проводили следственный эксперимент на тему «токсичности»: Взяли случайный вопрос с тостера, на который был дан ответ, вида «иди читать документацию» и «не надо вставлять код картинками, для этого есть соответствующий тег», с возражением «не хочешь помочь — не отвечай». Дальнейшая волна комментариев состояла из приперательств, на тему «не надо задавать вопросы, которые есть в документации, на темы, которые элементарно гуглятся».
Далее этот вопрос из под фейкового аккаунта был перемещён на стековерфлоу. При этом, для чистоты эксперимента — он был задан вообще в англоязычном сегменте (существует мнение, что на отечественных IT формуах/ресурсах — люди более «токсичные», а на зарубежных всё ок). В результате сам вопрос набрал "-2" за 2 или 3 часа, но, к слову сказать, один ответ там всё же был дан.
Вся эта история и сам эксперимент были проведены на стриме, часть которого был посвящён теме «почему подрастающее поколение так любит видеоуроки и не хочет учиться» и лежит в записи на ютубе, ссылку на которое, я могу кинуть в личку.
Я достаточно подробно расписал ответ?
Я достаточно подробно расписал ответ?
Да. Спасибо.
В частности вот слайды (возможно надо поскроллить анимацию)
ocramius.github.io/doctrine-best-practices/#/51
ocramius.github.io/doctrine-best-practices/#/56
С другой стороны Symfony Forms не оперируют чистыми полями сущности, она работает через публичные методы, а это значит, что имея корректную DDD сущность без сеттеров (а с бизнес-логичными методами) вы не сможете привести ее в невалидное состояние формой и проблема исчезает. Но там становится сильно сложней конфигурация самой формы в таком случае, надо навешивать на нее дата мапперы, события и прочие радости жизни
Вот пример, как работать с VO через формы
webmozart.io/blog/2015/09/09/value-objects-in-symfony-forms
Если убрать у сущности сеттеры, то выглядеть уже будет корректно, в этом случае форма сама будет выступать как DTO + трансформер, который правильным образом переложит данные (вызвав нужные методы в нужном порядке) в модель
Unless a property is public, it must have a «getter» and «setter» method so that the Form component can get and put data onto the property.
Хотя в действительности это не так обязательно, можно поменять дата маппер. Тянет на issue и PR
сам я начинал с Laravel но ушел на Yii2.
С уверенностью могу сказать, что наговнокодить можно в любом реймворке.
Прокомментирую эти плюсы ларавел
> Имеет встроенный сборщик скриптов и scss
в Yii тоже есть встроенный сборщик. Но по мне в ларе реально удобнее.
> Встроенный шаблонизатор Blade
Он конечно прост, и в какой-то степени ограничивает говнокод. Но PHP сам по себе шаблонизатор. Я лично против дополнительных надстроек.
> Очень гибкое формирование Роутов
За все время мне еще не разу не попадалась задача на yii где не хватало бы гибкости формирования роутов.
> Очень гибкие возможности для написания REST API
аналогично предыдущему пункту
> Быстро развивается
не быстро развивается а потостоянно изменяется. Каждая новая версия слабосовместима с предыдущей. Обновления вызывают опасения. Поэтому с ларавела и соскочил.
в Yii всё стабильно. Критичных обновлений за последние года полтора не было. Обратная совместимость почти всегда есть. Только вот сейчас готовится критичное обновление Yii2.1 и то делают всё, что бы переход был гладким. А то вместо работы над проектом получается постоянное латание дыр за обновлениями.
В общем я на yii из-за стабильности перешел. Но ларевел мне по красоте кода нравится :-)
не быстро развивается а потостоянно изменяется. Каждая новая версия слабосовместима с предыдущей. Обновления вызывают опасения. Поэтому с ларавела и соскочил.
Это было только два раза за всю историю, переход с 3.х на 4.х и с 4.х на 5.х. Можно было догадаться, почему эти версии мажорные.
ни фига, в 5.6 настройку логгинга поменяли, удалили интерфейс, переимновали пару классов, изменили порядочек в индексах, что может давать проблемы с откатом миграций, В 5.5 попереимновывали и поменяли логику в методах реквеста… bc в ларке ломают гораздо чаще… и это может быть не так критично на свежем проекте в разработке, но не на рабочем монстре.
Встроенный сборщик основан на WebPack
Очень жирный минус. Всюду таскать этого тормозного монстра… ну нафиг.
Ну и еще. Если планируется серьезное масштабное расширение с кучей фич и переход на микросервисную, я бы предложил смотреть в сторону минималистичных фреймворков, типа Silex (сейчас устарел) или Symfony 4, где все лишнее из коробочной сборки выпилино, даже doctrine. Все можно установить, но уже по раздельности. Для крупных растущих проектов самое оно, есть контроллеры и все, модели и остальную архитектуру организуй как хочешь!
На Yii3 переходить на планируете?
Я больше про архитектурные изменения. Если Yii2 для вас лучшее, что можно придумать, то Yii3 может оказаться разочарованием.
Важный момент — не менять при этом роуты. Стандартизация — наше все ))
В итоге, скорее всего, получится свой фреймворк или что-то что легко в него превращается.
Ну я например видел такой подход. Берут бибилиотеки готовые, например для маршрутизации и ORM для БД, и создают собственную архитектуру где это и как должно лежать. По сути да получается собственный фреймворк, при грамотной архитектуре лучше чем любой публичный, в том плане, что хорошо подходит под текущий проект, а минусы как правило в том, что не очень универсальный и документации мало)
Выбираем Yii2 или laravel