.gitignore /web/bundles/ /app/bootstrap.php.cache /app/cache/* /app/config/parameters.yml /app/logs/* /build/ /vendor/ /bin/ /composer.phar /data/uploads .idea should be in your global .gitignore
What should go into a Bundle • Bundles should be self-contained • Sets of Features • Examples: API, Worker Commands, Admin Panel… • Configured in /app/config
If not using Annotations… Nest your routing files # /app/config/routing.yml acme_conference: resource: @AcmeConferenceBundle/[…]/routing.yml prefix: /conference
Service Layers – where sensible class ConferenceHandler { public function __construct( ObjectManager $manager, EventDispatcherInterface $dispatcher ) { $this->manager = $manager; $this->dispatcher = $dispatcher; }
public function save(Conference $conference) { $this->manager->persist($conference); $this->manager->flush();
Using the BaseController? Wrap calls to the Container to clean up /** * @return GeocoderInterface */ private function getGeocoder() { return $this->get('geocoder'); }
Alternative: Providing the Request (< 2.4) class RequestProvider { public function __construct( ContainerInterface $container ) { $this->container = $container; }
public function getRequest() { $this->container->get('request'); } }
The Container as a Registry public function listAction() { $max = $this->container->getParameter( 'max_conferences' ); $conferences = $someStorage->getConferences($max);
Doctrine • Activate Metadata Cache • Activate Query Cache • Pro Level only: Use factory-service to register Repos & Managers as Services • Do NOT inject the EntityManager into your entities
Security • Make sure there are no leaks in the security.yml access_control section! • Better: Check Authorization in Controller, use the @Security annotation
Forms in Controllers public function createAction(Request $request) { $form = $this->createFormBuilder() ->add('name') ->add('startDate', 'date') ->add('endDate', 'date') ->add('location', 'textarea') ->getForm() ;
Always set the data_class public function setDefaultOptions( OptionsResolverInterface $resolver ) { $resolver->setDefaults( array( 'data_class' => 'Acme\Conference' ) ); }