php - generate - Problema conceptual de Symfony2: paquetes generales vs. específicos
symfony framework bundle (2)
Editar: las mejores prácticas de Symfony responden la mayoría de mis preguntas.
Tengo varias preguntas sobre mi aplicación Symfony2.
Tendrá un frontend y un backend, y usarán algún código común (como un visualizador de fecha, paginador, algunas plantillas de uso frecuente, etc.).
Entonces, creé un FrontendBundle y un BackendBundle, cada uno conteniendo, por ejemplo, su diseño respectivo. Primera pregunta: ¿es una buena práctica crear paquetes para frontend y backend, que son paquetes "generales" que ni siquiera tendrán un controlador?
Segunda pregunta: leí en un libro de cocina que no debería poner mis diseños en paquetes, sino en el directorio de la aplicación / Resources / views /. Ya tengo un archivo base.html.twig y me pregunto si debería incluir mis diseños también, como un archivo frontend_layout.html.twig.
Creé un paquete llamado RootBundle, que contendría todo lo que mi aplicación necesita en frontend AND backend. ¿Es eso una buena práctica o no? ¿O debería crear un paquete dedicado para cada funcionalidad propuesta, como un PaginatorBundle, un DateDisplayerBundle, etc.? Suena extraño que tenga un paquete "misceláneo" que contenga todo lo que no sé dónde poner. ¿Cómo haces eso?
El nuevo enfoque
Después de varios meses desde que escribí esta respuesta, mi enfoque ha cambiado, así que lo estoy compartiendo con la comunidad. Esta respuesta todavía es bastante popular y puede llevar a los recién llegados al enfoque que ya no creo que sea el mejor. Asi que...
Ahora solo tengo un paquete específico para aplicaciones y lo llamo AppBundle
. Hubo varios problemas con el enfoque anterior y aquí están algunos de ellos:
Crear muchos paquetes es tedioso. Tienes que crear una clase de paquete y un grupo de carpetas estándar para cada paquete nuevo y luego activarlo y registrar sus rutas y DI y otras cosas.
Proceso de toma de decisiones difícil e innecesario. A veces no puedes decidir a qué paquete pertenece una cosa en particular porque es utilizado por más de un paquete. Y después de pasar medio día y finalmente tomar una decisión difícil sobre dónde colocarlo, descubrirá que en un par de días o semanas no podrá saber de inmediato qué paquete buscará esa cosa: porque la mayoría de las veces la decisión no se basaba en la lógica pura y tenías que elegir en función de un lanzamiento de moneda o cualquier otro medio que utilizas para obtener poderes superiores en busca de ayuda.
Sugerí usar
CommonBundle
para cosas comunes en el pasado, pero al hacer eso tendrás que hacer un montón de refactorizaciones innecesarias moviendo una cosa hacia y desdeCommonBundle
función de cuántos o pocos paquetes usarán esa cosa más adelante.Los paquetes específicos de la aplicación son interdependientes de todos modos. Cuando las personas se encuentran con la idea de paquetes por primera vez, uno de los pensamientos principales que pasa por sus mentes es algo así como "¡Yay! ¡Tendré un montón de paquetes reutilizables! "Esa idea es genial y no tengo nada en contra; el problema es que los paquetes específicos de aplicaciones no son tan reutilizables de todos modos, existen interdependencias. Olvídate de la reutilización en este caso.
No tengo idea de dónde poner Behat características de Behat y las definiciones de los pasos. Este problema está relacionado con los anteriores: tienes que repetir los mismos movimientos sin cerebro para cada paquete y luego tomar decisiones difíciles.
Cuando comencé a escribir las características de Behat, simplemente no podía decidir dónde poner muchas características y definiciones de pasos porque pertenecían a varios paquetes a la vez. Ponerlos en
CommonBundle
parecía ser aún peor, porque ese es el último paquete en el que buscaría esas cosas. Así que terminé creandoFeatureBundle
para eso.
Cambiar a un paquete único resolvió todos estos problemas.
También he visto a algunas personas tener un paquete separado para, digamos, todas las entidades. Tampoco me gusta este enfoque y, en realidad, sugiero que se mantengan las entidades y otros elementos no específicos de Symfony2 fuera de los paquetes .
Tenga en cuenta nuevamente que este nuevo enfoque se aplica a los paquetes específicos de la aplicación . Los documentos oficiales y otros lugares están llenos de excelentes consejos sobre cómo estructurar paquetes destinados a ser compartidos con otros y reutilizados en numerosos proyectos. También escribo paquetes de este tipo . Pero lo que descubrí después de meses de trabajar en proyectos de Symfony2 es que hay una diferencia entre los paquetes destinados a la reutilización y los específicos de la aplicación; un enfoque no sirve para todos.
Y, por supuesto, cuando vea que algo emergente emerge en su paquete específico de aplicaciones, simplemente extráigalo, póngalo en un repositorio separado e instálelo como proveedor.
También me he encontrado a mí mismo usando submemoria de espacios mucho más activamente como una forma de particionar el paquete lógicamente, en lugar de crear un montón de paquetes para eso y pasar por todos esos problemas.
El viejo enfoque
No hay reglas duras ni rápidas ni balas de plata, pero compartiré mi enfoque de hacer las cosas, tal vez te dé una idea o dos.
Antes que nada, no tengo dos paquetes BackendBundle
como FrontendBundle
y BackendBundle
. En cambio, mis paquetes tienen tanto controles frontend como back-end, vistas, etc. Por lo tanto, si UserBundle
todo de mi UserBundle
excepción de los controladores y las vistas, su estructura se vería así:
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
En segundo lugar, tengo CommonBundle
que uso para cosas compartidas por varios paquetes:
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
Mi app/Resources/views/base.html.twig
es casi la misma que viene con la distribución estándar de Symfony:
<!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
y CommonBundle/Resources/views/Admin/layout.html
extienden la app/Resources/views/base.html.twig
. Las plantillas de otros paquetes extienden uno de estos dos diseños, dependiendo de si son para frontend o back-end. Básicamente, así es como estoy usando el enfoque de Herencia de Tres Niveles .
Entonces, pondría su visualizador de fecha en CommonBundle
. Dependiendo de su complejidad, podría ser solo una plantilla, una macro o una extension Twig .
La paginación es un problema común, por lo que le sugiero que utilice uno de los bundles existing lugar de reinventar la rueda, si cumplen sus necesidades, por supuesto.
Y sí, está perfectamente bien tener paquetes sin controladores o vistas, etc.
Sugiero crear un DateDisplayerBundle y un PaginatorBundle en lugar de poner su código relacionado en un paquete más general. Hay algunas razones para esto:
- El papel de cada paquete es muy claro, y usted sabe dónde está su código.
- Compartir piezas de funcionalidad (visualizador de fecha, paginador) entre diferentes proyectos es más simple cuando tiene paquetes separados, en comparación con un paquete general que puede necesitar podar.
No hay una regla rígida que diga que los paquetes deben tener controladores. Los paquetes pueden tener cualquier combinación de lógica comercial, plantillas, controladores y configuración, pero no hay restricciones sobre lo que puede almacenar en ellos.
Por otro lado, si su funcionalidad no es muy compleja, es posible que no garantice su inclusión dentro de un paquete. En este caso, podría crear una biblioteca en /vendor
para ello. Symfony hace uso de varias bibliotecas de esta manera (ver Monólogo y Doctrina, por ejemplo).
En cuanto a su segunda pregunta, creo que la razón para mantener los diseños en la app/Resources/views
es porque es una forma conveniente de realizar un seguimiento de todos sus diseños. Cuando tiene un proyecto que tiene muchos paquetes, es posible que pierda de vista dónde se encuentra un determinado diseño. Pero si los mantiene a todos dentro de una ubicación centralizada, siempre sabrá exactamente dónde buscarlos. Al igual que con muchas cosas en Symfony2, esta no es una regla inamovible. Puede almacenar fácilmente sus diseños en un paquete, pero no creo que sea la práctica recomendada.
En cuanto a su pregunta sobre su paquete general de Root, diría que en la mayoría de los casos debe evitar calzar un montón de características diferentes en un solo paquete. Vea mis puntos anteriores sobre cómo mantener sus paquetes específicos. Cuando comencé a desarrollar con Symfony2, tuve algunos problemas para determinar qué código debería ir en qué paquete. No es como yo solía pensar en programación. Pero eventualmente comienzas a ver cómo encajan las piezas individuales del rompecabezas, y eso hace que sea más fácil determinar la estructura del paquete.