generate create symfony architecture bundle

create - ¿Debería todo ser un paquete en Symfony 2.x?



symfony create project (6)

Soy consciente de preguntas como this , donde las personas tienden a discutir el concepto general de paquete de Symfony 2.

La cuestión es que, en una aplicación específica, como, por ejemplo, una aplicación similar a Twitter, ¿todo debería estar dentro de un paquete genérico, como dicen los documentos oficiales ?

La razón por la que pregunto esto es porque cuando desarrollamos aplicaciones, en general, no queremos acoplar nuestro código a un marco de pegamento de pila completa.

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

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

EDITAR # 1

Hace casi un año que hice esta pregunta, escribí un article para compartir mis conocimientos sobre este tema.


Como ya han pasado 5 años, aquí hay algunos artículos más sobre paquetes de Symfony.

  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 que escribas un AppBundle para evitar un espagueti de dependencias. Simplemente puede seguir las mejores prácticas y funcionará bien.

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

TLDR:

Cree solo un paquete llamado AppBundle para la lógica de su aplicación. Un AppBundle - ¡pero por favor no ponga la lógica de su aplicación allí!


He escrito una publicación de blog más completa 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 los modelos,
  • src/Vendor/Controller - para controladores,
  • src/Vendor/Service - para servicios,
  • src/Vendor/Bundle - para paquetes, como src/Vendor/Bundle/AppBundle ,
  • etc.

De esta manera, pondrías en el AppBundle solo las cosas que realmente son específicas de Symfony2. Si decides cambiar a otro marco más tarde, te Bundle espacio de nombres del Bundle y lo sustituirás por el marco elegido.

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

Mantener las entidades fuera de los paquetes

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

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 los repositorios de Doctrine, comienzan con Model en este caso, por ejemplo, Model:User .

Puede usar subnamespaces 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

Primero, debe decirle a JMSDiExtraBundle que escanee la carpeta src busca de servicios agregando esto a config.yml :

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

Luego, define los controladores como servicios y los coloca bajo el espacio de nombres del Controller :

<?php namespace Vendor/Controller; use Symfony/Component/HttpFoundation/Request; use Symfony/Component/HttpFoundation/RedirectResponse; use Sensio/Bundle/FrameworkExtraBundle/Configuration/Route; use Sensio/Bundle/FrameworkExtraBundle/Configuration/Template; use JMS/DiExtraBundle/Annotation/Service; use JMS/DiExtraBundle/Annotation/InjectParams; use JMS/SecurityExtraBundle/Annotation/Secure; use Elnur/AbstractControllerBundle/AbstractController; use Vendor/Service/UserService; use Vendor/Model/User; /** * @Service("user_controller", parent="elnur.controller.abstract") * @Route(service="user_controller") */ class UserController extends AbstractController { /** * @var UserService */ private $userService; /** * @InjectParams * * @param UserService $userService */ public function __construct(UserService $userService) { $this->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. Hago esto al anular el servicio de adivinanzas de plantillas, pero como el enfoque es diferente entre Symfony 2.0 y 2.1, estoy proporcionando versiones para ambos.

Anulando la plantilla de Symfony 2.1+

He creado un bundle que hace eso por ti.

Anulando la escucha de plantillas de Symfony 2.0

Primero, define la clase:

<?php namespace Vendor/Listener; use InvalidArgumentException; use Symfony/Bundle/FrameworkBundle/Templating/TemplateReference; use Symfony/Component/HttpFoundation/Request; use Symfony/Component/HttpKernel/Bundle/Bundle; use Sensio/Bundle/FrameworkExtraBundle/EventListener/TemplateListener as FrameworkExtraTemplateListener; use JMS/DiExtraBundle/Annotation/Service; class TemplateListener extends FrameworkExtraTemplateListener { /** * @param array $controller * @param Request $request * @param string $engine * @throws InvalidArgumentException * @return TemplateReference */ public function guessTemplateName($controller, Request $request, $engine = ''twig'') { if (!preg_match(''/Controller///(.+)Controller$/'', get_class($controller[0]), $matchController)) { throw new InvalidArgumentException(sprintf(''The "%s" class does not look like a controller class (it must be in a "Controller" sub-namespace and the class name must end with "Controller")'', get_class($controller[0]))); } if (!preg_match(''/^(.+)Action$/'', $controller[1], $matchAction)) { throw new InvalidArgumentException(sprintf(''The "%s" method does not look like an action method (it does not end with Action)'', $controller[1])); } $bundle = $this->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

Usando plantillas sin paquetes

Ahora, puedes usar plantillas de paquetes. Mantenlos en la carpeta de 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

Al referirse a una plantilla, simplemente omita la parte del paquete:

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


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

Otro enfoque es utilizar 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


Por supuesto que puedes desacoplar tu aplicación. Solo desarrollalo como una biblioteca e integralo en el vendor/ carpeta de Symfony (ya sea usando deps o composer.json , dependiendo de si usas Symfony2.0 o Symfony2.1). Sin embargo, necesitas al menos un paquete, que actúa como el "frontend" de tu biblioteca, donde Symfony2 encuentra el controlador (y tal).


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

En este paquete puedes estructurar tu código como quieras.

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

Por todo el concepto, no extremistas esto. El paquete es bueno, pero hazlo todo y todos los días no es bueno.

Tal vez puedas usar un Silex (marco micro de Symfony) para desarrollar tu Prueba de concepto para reducir el impacto del paquete de terceros.


Una distribución habitual de Symfony puede funcionar sin ningún paquete adicional (aplicación), dependiendo de la cantidad de funcionalidades que quieras usar desde el framework de pila completa.

Por ejemplo, sus controladores pueden ser invocables 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 utilizar:

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

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

Sus plantillas de ramitas (u otras) se pueden colocar como app/Resources/views/template.html.twig y se pueden representar usando 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 simple, sin ningún tipo de vinculación con el marco).

Todo esto es proporcionado por defecto por el framework de pila completa de Symfony.

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

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