Концептуальная проблема Symfony2: общие пакеты против конкретных - PullRequest
35 голосов
/ 04 ноября 2011

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

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

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

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

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

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

Ответы [ 2 ]

79 голосов
/ 05 ноября 2011

Новый подход

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

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

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

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

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

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

  • Не знаю, куда поместить 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

My 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 расширение .

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

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

4 голосов
/ 04 ноября 2011

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

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

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

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

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

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

...