Концептуальная проблема Symfony2: общие пакеты по сравнению с конкретными

Изменить: лучшие ответы Symfony отвечают на большинство моих вопросов.

У меня есть несколько вопросов относительно моего приложения Symfony2.

Он будет иметь интерфейс и бэкэнд, и они будут использовать какой-то общий код (например, дисплей даты, пагинатор, некоторые часто используемые шаблоны и т. Д.).

Итак, я создал один FrontendBundle и один BackendBundle, каждый из которых содержит, например, их соответствующий макет. Первый вопрос: хорошая практика создания пакетов для интерфейса и бэкэнд, которые являются «общими» пакетами, в которых даже не будет контроллера?

Второй вопрос: я прочитал в поваренной книге, что не должен размещать свои макеты в пакетах, но в каталоге app / Resources / views /. У меня уже есть файл base.html.twig, и мне интересно, должен ли я помещать туда свои макеты, например файл frontend_layout.html.twig?

Я создал пакет с именем RootBundle, который будет содержать все, что нужно моему приложению в интерфейсе AND backend. Это хорошая практика или нет? Или я должен создать выделенный пакет для каждой предлагаемой функции, такой как PaginatorBundle, DateDisplayerBundle и т. Д.? Звучит странно, что у меня есть один «разный» комплект, содержащий все, что я не знаю, куда положить. Как ты это делаешь?

Related of "Концептуальная проблема Symfony2: общие пакеты по сравнению с конкретными"

Новый подход

Спустя несколько месяцев с тех пор, как я написал этот ответ, мой подход изменился, поэтому я делюсь с сообществом. Этот ответ по-прежнему довольно популярен и может привести новичков к подходу, который я больше не считаю лучшим. Так…

Теперь у меня есть только один пакет приложений, и я называю его AppBundle . Было несколько проблем со старым подходом, и вот некоторые из них:

  • Создание множества пучков утомительно. Вам нужно создать класс пакета и набор стандартных папок для каждого нового пакета, а затем активировать его и зарегистрировать его маршруты и DI и еще много чего.

  • Ненужный процесс принятия жестких решений. Иногда вы просто не можете решить, какой пакет принадлежит определенной вещи, потому что он используется более чем одним пакетом. И после того, как вы потратите пол дня и, наконец, решите свое решение о том, куда его поместить, вы обнаружите, что через пару дней или недель вы не сможете сразу сказать, какой пакет смотреть на эту вещь – потому что в большинстве случаев решение не основывалось на чистой логике, и вам приходилось выбирать, основываясь на броске монеты или на любом другом, что вы используете, чтобы принести более высокие полномочия для помощи.

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

  • Конкретные пакеты приложений в любом случае взаимозависимы. Когда люди впервые встречают идею пучков, одна из главных мыслей, которая проходит через их умы, – это что-то вроде «Yay! У меня будет куча многоразовых пакетов! »Эта идея велика, и я ничего не имею против нее; проблема в том, что приложения, связанные с пакетами, не так много, чтобы повторно использоваться – есть взаимозависимые. Забудьте о повторном использовании в этом случае.

  • Не знаю, где поставить функции Behat и определения шагов. Эта проблема связана с предыдущими: вы должны повторять те же безмозглые движения для каждого пакета, а затем принимать хардкорные решения.

    Когда я начал писать функции Behat, я просто не мог решить, где разместить множество функций и определений шагов, поскольку они принадлежали нескольким пакетам за раз. Кажется, что их размещение в CommonBundle было еще хуже, потому что это последний пакет, который я бы искал для этого. Итак, я закончил создание FeatureBundle для этого.

Переключение на один пакет решило все эти проблемы.

Я также видел, как некоторые люди имеют отдельный пакет для, скажем, всех сущностей. Мне не нравится этот подход и не предлагает поддерживать объекты и другие компоненты, отличные от Symfony2, из комплектов .

Заметим еще раз, что этот новый подход применяется к конкретным приложениям . Официальные документы и другие места полны больших советов о том, как структурировать пакеты, предназначенные для совместного использования с другими, и повторно использовать в многочисленных проектах. Я пишу также пакеты этого типа . Но то, что я обнаружил после нескольких месяцев работы над проектами Symfony2, заключается в том, что существует разница между пакетами, предназначенными для повторного использования, и приложениями – один подход не подходит всем.

И, конечно, когда вы видите что-то многоразовое, появившееся в вашем конкретном пакете приложений, просто извлеките его, поместите в отдельное репо и установите в качестве поставщика.

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

Старый подход

Нет никаких жестких правил или серебряных пуль, но я поделюсь своим подходом к тому, чтобы делать что-то – может быть, это даст вам представление или два.

Прежде всего, у меня нет двух всеобъемлющих пакетов, таких как FrontendBundle и BackendBundle . Вместо этого в моих пакетах есть интерфейсные и бэкэнд-контроллеры, представления и т. Д. Итак, если я UserBundle все из своего UserBundle кроме контроллеров и представлений, его структура будет выглядеть так:

 UserBundle ├── Controller │ ├── Admin │ │ └── UserController.php │ └── UserController.php ├── Resources │ └── views │ ├── Admin │ │ └── User │ │ ├── add.html.twig │ │ ├── delete.html.twig │ │ ├── edit.html.twig │ │ ├── form.html.twig │ │ └── index.html.twig │ └── User │ ├── edit.html.twig │ ├── sign-in.html.twig │ ├── sign-up.html.twig │ └── view.html.twig └── UserBundle.php 

Во-вторых, у меня есть CommonBundle который я использую для вещей, разделяемых несколькими пакетами:

 CommonBundle ├── Resources │ ├── public │ │ ├── css │ │ │ ├── admin.css │ │ │ ├── common.css │ │ │ └── public.css │ │ └── img │ │ ├── add.png │ │ ├── delete.png │ │ ├── edit.png │ │ ├── error.png │ │ ├── return.png │ │ ├── success.png │ │ └── upload.png │ └── views │ ├── Admin │ │ └── layout.html.twig │ └── layout.html.twig └── CommonBundle.php 

Мое app/Resources/views/base.html.twig почти такое же, как и в дистрибутиве Symfony Standard:

 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>{{ block('title') | striptags | raw }}</title> {% block stylesheets %}{% endblock %} </head> <body> {% block body %}{% endblock %} {% block javascripts %}{% endblock %} </body> </html> 

Оба CommonBundle/Resources/views/layout.html и CommonBundle/Resources/views/Admin/layout.html расширяют app/Resources/views/base.html.twig . Шаблоны других пакетов расширяют один из этих двух макетов, в зависимости от того, являются ли они интерфейсом или бэкэнд. В принципе, именно так я использую трехуровневый подход наследования .

Итак, я включил отображение даты в CommonBundle . В зависимости от его сложности это может быть просто шаблон, макрос или расширение Twig .

Пагинация – распространенная проблема, поэтому я предлагаю вам использовать один из существующих пакетов вместо того, чтобы изобретать колесо – если они удовлетворяют вашим потребностям, конечно.

И да, вполне нормально иметь пучки без контроллеров или просмотров и т. Д.

Я предлагаю создать DateDisplayerBundle и PaginatorBundle вместо того, чтобы помещать их связанный код в более общий набор. Для этого есть несколько причин:

  • Роль каждого пакета очень понятна, и вы знаете, где находится ваш код.
  • Разделение фрагментов функциональности (отображение даты, paginator) между различными проектами проще, когда у вас есть отдельные пакеты, по сравнению с одним общим комплектом, который вам может понадобиться сократить.

Нет жесткого правила, говорящего, что в пучках должны быть контроллеры. Связки могут иметь любое сочетание бизнес-логики, шаблонов, контроллеров и конфигурации, но нет никаких ограничений на то, что вы можете хранить в них.

С другой стороны, если ваша функциональность не очень сложна, она может вообще не содержаться в комплекте. В этом случае вы можете создать для него библиотеку в /vendor . Symfony использует несколько библиотек таким образом (см., Например, Monolog и Doctrine).

Что касается вашего второго вопроса, я думаю, что причина сохранения макетов в app\Resources\views заключается в том, что это удобный способ отслеживать все ваши макеты. Когда у вас есть проект с множеством пакетов, вы можете потерять информацию о том, где находится определенный макет. Но если вы держите их всех в одном централизованном месте, вы всегда будете знать, где искать. Как и в Symfony2, это не правило, установленное в камне. Вы можете легко сохранить свои макеты в комплекте, но я не думаю, что это рекомендуемая практика.

Что касается вашего вопроса о вашем общем корневом пакете, я бы сказал, что в большинстве случаев вам следует избегать подделки нескольких функций в одном комплекте. См. Мои предыдущие моменты, касающиеся того, чтобы ваши пакеты были конкретными. Когда я начал развиваться с помощью Symfony2, у меня возникли проблемы с определением того, какой код должен идти в комплекте. Я не привык думать о программировании. Но в конце концов вы начинаете видеть, как отдельные части головоломки подходят, и это упрощает определение структуры пучка.