¿Todo debería ser un paquete en Symfony 2.x?

Estoy al tanto de preguntas como esta , en las que las personas tienden a discutir el concepto general de paquete de Symfony 2.

El asunto es, en una aplicación específica, como, por ejemplo, una aplicación tipo twitter, ¿debería estar todo dentro de un paquete genérico, como dicen los documentos oficiales ?

La razón por la que estoy preguntando esto es porque cuando desarrollamos aplicaciones, en general, no queremos unir nuestro código a un framework de pegamento completo.

Si desarrollo una aplicación basada en Symfony 2 y, en algún momento, decido que Symfony 2 no es realmente la mejor opción para continuar el desarrollo , ¿será un problema para mí?

Entonces, la pregunta general es: ¿por qué todo es un paquete es algo bueno?

EDIT # 1

Hace casi un año que hice esta pregunta y escribí un artículo para compartir mi conocimiento sobre este tema.

He escrito una publicación de blog más exhaustiva y actualizada sobre este tema: http://elnur.pro/symfony-without-bundles/


No, no todo tiene que estar en un paquete. Podrías tener una estructura como esta:

  • src/Vendor/Model – para modelos,
  • src/Vendor/Controller – para controladores,
  • src/Vendor/Service – para servicios,
  • src/Vendor/Bundle – para paquetes, como src/Vendor/Bundle/AppBundle ,
  • etc.

De esta forma, pondrías en el AppBundle solo esas cosas que son realmente específicas de Symfony2. Si decide cambiar a otro marco más adelante, se desharía del espacio de nombre Bundle y lo reemplazará con el material del framework elegido.

Tenga en cuenta que lo que sugiero aquí es para el código específico de la aplicación . Para paquetes reutilizables, aún sugiero usar las mejores prácticas .

Mantener entidades fuera de paquetes

Para mantener las entidades en src/Vendor/Model fuera de cualquier paquete, he cambiado la sección de doctrine en config.yml de

 doctrine: # ... orm: # ... auto_mapping: true 

a

 doctrine: # ... orm: # ... mappings: model: type: annotation dir: %kernel.root_dir%/../src/Vendor/Model prefix: Vendor\Model alias: Model is_bundle: false 

Los nombres de las entidades, para acceder desde repositorys de Doctrine, comienzan con el Model en este caso, por ejemplo, Model:User .

Puede usar espacios de subnombres para agrupar entidades relacionadas, por ejemplo, src/Vendor/User/Group.php . En este caso, el nombre de la entidad es Model:User\Group .

Mantener los controladores fuera de los paquetes

En primer lugar, debe decirle a JMSDiExtraBundle que busque los servicios en la carpeta src al agregar esto a config.yml :

 jms_di_extra: locations: directories: %kernel.root_dir%/../src 

A continuación, define los controladores como servicios y los coloca bajo el espacio de nombres Controller :

 userService = $userService; } /** * @Route("/user/add", name="user.add") * @Template * @Secure("ROLE_ADMIN") * * @param Request $request * @return array */ public function addAction(Request $request) { $user = new User; $form = $this->formFactory->create('user', $user); if ($request->getMethod() == 'POST') { $form->bind($request); if ($form->isValid()) { $this->userService->save($user); $request->getSession()->getFlashBag()->add('success', 'user.add.success'); return new RedirectResponse($this->router->generate('user.list')); } } return ['form' => $form->createView()]; } /** * @Route("/user/profile", name="user.profile") * @Template * @Secure("ROLE_USER") * * @param Request $request * @return array */ public function profileAction(Request $request) { $user = $this->getCurrentUser(); $form = $this->formFactory->create('user_profile', $user); if ($request->getMethod() == 'POST') { $form->bind($request); if ($form->isValid()) { $this->userService->save($user); $request->getSession()->getFlashBag()->add('success', 'user.profile.edit.success'); return new RedirectResponse($this->router->generate('user.view', [ 'username' => $user->getUsername() ])); } } return [ 'form' => $form->createView(), 'user' => $user ]; } } 

Tenga en cuenta que estoy usando mi ElnurAbstractControllerBundle para simplificar la definición de controladores como servicios.

Lo último que queda es decirle a Symfony que busque plantillas sin paquetes. Lo hago anulando el servicio del adivinador de plantillas, pero dado que el enfoque es diferente entre Symfony 2.0 y 2.1, proporciono versiones para ambos.

Anulando el adivinador de plantillas de Symfony 2.1+

Creé un paquete que hace eso por ti.

Sobreescribiendo el oyente de plantilla de Symfony 2.0

Primero, define la clase:

 getBundleForClass(get_class($controller[0])); return new TemplateReference( $bundle ? $bundle->getName() : null, $matchController[1], $matchAction[1], $request->getRequestFormat(), $engine ); } /** * @param string $class * @return Bundle */ protected function getBundleForClass($class) { try { return parent::getBundleForClass($class); } catch (InvalidArgumentException $e) { return null; } } } 

Y luego dile a Symfony que lo use agregando esto a config.yml :

 parameters: jms_di_extra.template_listener.class: Vendor\Listener\TemplateListener 

Usar plantillas sin paquetes

Ahora puede usar plantillas de paquetes. Guárdelos en la carpeta de la app/Resources/views . Por ejemplo, las plantillas para esas dos acciones del controlador de ejemplo anterior se encuentran en:

  • app/Resources/views/User/add.html.twig
  • app/Resources/views/User/profile.html.twig

Cuando se refiere a una plantilla, simplemente omita la parte del paquete:

 {% include ':Controller:view.html.twig' %} 

Por supuesto, puedes desacoplar tu aplicación. Simplemente desarrollelo como una biblioteca e integrelo en el vendor/ carpeta de Symfony (ya sea usando deps o composer.json , dependiendo de si usa Symfony2.0 o Symfony2.1). Sin embargo, necesita al menos un paquete, que actúa como el “frontend” de su biblioteca, donde Symfony2 encuentra el controlador (y tal).

Una distribución de Symfony habitual puede funcionar sin ningún paquete adicional (aplicación), dependiendo de la cantidad de funcionalidades que desee utilizar del marco de stack completo.

Por ejemplo, sus controladores pueden ser cualquier llamativo que pueda colocarse en cualquier lugar de la estructura de su proyecto, tan pronto como se carguen automáticamente.

En un archivo de definición de enrutamiento, puede usar:

 test: pattern: /test defaults: { _controller: Controller\Test::test } 

Puede ser cualquier objeto antiguo php simple, solo vinculado al marco por el hecho de que tiene que devolver un objeto Symfony\Component\HttpFoundation\Response .

Las plantillas twig (u otras) se pueden poner como app/Resources/views/template.html.twig y se pueden representar con el nombre lógico ::template.html.twig .

Todos los servicios DI se pueden definir en app / config / config.yml (o importados desde app/config/services.yml por ejemplo, y todas las clases de servicio pueden ser cualquier objeto php antiguo y no relacionado con el framework).

Todo esto lo proporciona de manera predeterminada el marco de stack completo de Symfony.

Donde tendrá problemas es cuando querrá usar archivos de traducción (como xliff), ya que se descubren solo a través de paquetes.

La distribución de Symfony-light tiene como objective resolver este tipo de problemas descubriendo todo lo que normalmente se descubriría solo a través de paquetes.

Podría usar KnpRadBundle , que intenta simplificar la estructura del proyecto.

Otro enfoque es usar src/Company/Bundle/FrontendBundle por ejemplo para los paquetes y src/Company/Stuff/Class.php para las clases que son independientes de Symfony y que podrían reutilizarse fuera del marco

Ya pasaron 5 años, aquí hay algunos artículos más sobre Symfony Bundles.

  1. ¿Qué son los paquetes en Symfony? por Iltar van der Berg.

TLDR:

¿Necesita múltiples paquetes en su aplicación directamente? Probablemente no. Es mejor escribir un AppBundle para evitar un espagueti de dependencias. Simplemente puede seguir las mejores prácticas y funcionará bien.

  1. Symfony: Cómo agrupar por Toni Uebernickel.

TLDR:

Cree solo un paquete llamado AppBundle para su lógica de aplicación. Un AppBundle – ¡pero no pongas tu lógica de aplicación allí!

El framework de Symfony es muy bueno para lanzar rápidamente una prueba de concepto y todo el código puede ingresar dentro de la aplicación del paquete predeterminado en src /

En este paquete puede estructurar su código como lo desee.

Después, si desea utilizar otra tecnología para desarrollar su POC, puede traducir fácilmente eso porque no estructura todo su código en la concepción del paquete.

Por todo concepto, no extremismo esto. El paquete es bueno pero incluye todo y todos los días no es bueno.

Quizás pueda usar un Silex (Symfony micro framework) para desarrollar su Prueba de concepto para reducir el impacto del paquete de terceros.