Подтвердить что ты не робот

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

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

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

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

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

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

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

4b9b3361

Ответ 1

Новый подход

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Прежде всего, у меня нет двух всеобъемлющих пакетов, таких как FrontendBundle и BackendBundle. Вместо этого у моих пакетов есть интерфейсные и бэкэнд-контроллеры, представления и т.д. Итак, если я отделяю все от моего 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. В зависимости от его сложности это может быть просто шаблон, macro или Twig extension.

Разметка является общей проблемой, поэтому я предлагаю вам использовать один из существующий bundles вместо того, чтобы изобретать колесо - если они соответствуют вашим потребностям, конечно.

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

Ответ 2

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

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

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

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

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

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