Symfony: 3 – Bundles

Bundles

In Symfony2, a bundle is like a plugin, except that all of the code in your application will live inside a bundle. A bundle is nothing more than a directory that houses everything related to a specific feature, including PHP classes, configuration, and even stylesheets and JavaScript files. Everything is a bundle in Symfony2, including both the core framework functionality and the code written for your application. This gives you the flexibility to use pre-built features packaged in third-party bundles (http://knpbundles.com) or to distribute your own bundles. It makes it easy to pick and choose which features to enable in your application and to optimize them the way you want. An application is made up of bundles as defined in the registerBundles() method of the AppKernel
class:

// app/AppKernel.php
public function registerBundles()
{
  $bundles = array(
    new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
    new Symfony\Bundle\SecurityBundle\SecurityBundle(),
    new Symfony\Bundle\TwigBundle\TwigBundle(),
    new Symfony\Bundle\MonologBundle\MonologBundle(),
    new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
    new Symfony\Bundle\DoctrineBundle\DoctrineBundle(),
    new Symfony\Bundle\AsseticBundle\AsseticBundle(),
    new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
  );
 
  if (in_array($this->getEnvironment(), array('dev', 'test'))) {
    $bundles[] = new Acme\DemoBundle\AcmeDemoBundle();
    $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
    $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
    $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
  }
 
  return $bundles;
}

A bundle is also a PHP namespace. The namespace must follow the technical interoperability standards (http://symfony.com/PSR0) for PHP 5.3 namespaces and class names: it starts with a vendor segment, followed by zero or more category segments, and it ends with the namespace short name, which must end with a Bundle suffix. A namespace becomes a bundle as soon as you add a bundle class to it. The bundle class name must follow these simple rules:

  • Use only alphanumeric characters and underscores
  • Use a CamelCased name
  • Use a descriptive and short name (no more than 2 words)
  • Prefix the name with the concatenation of the vendor (and optionally the category namespaces)
  • Suffix the name with Bundle

To create a bundle called TestHelloBundle, run the following command and follow the on-screen instructions (use all of the default options):

$ php app/console generate:bundle --namespace=Test/HelloBundle --format=yml
OR
$ php app/console generate:bundle --namespace=Test/HelloBundle

The bundle skeleton generates with a basic controller, template and routing resource that can be customized. Behind the scenes, a directory is created for the bundle at src/Test/HelloBundle. A line is also automatically added to the app/AppKernel.php file so that the bundle is registered with the kernel. Whenever creating a new bundle or using a third-party bundle, always make sure the bundle has been enabled in registerBundles(). When using the generate:bundle command, this is done for you.

Remove Symfony demo code

Before we start building remove the Symfony demo code. First remove the demo bundle /src/acme then remove the reference to this bundle in /app/AppKernel.php. Finally remove the demo routing from /app/config/routing_dev.yml. Now let’s setup our project for git. First remove the existing .git directory and initialise a new git project

rm -rf .git
git init
git add .
git commit

With Symfony, it is common practice to use app_dev.php as the entry page during development. In a production environment, app_dev.php would be omitted.

To start coding we need a route to determine what to do. In this example we will use annotations to create routes. When writing routes as annotations, you write them right above the action you will want to execute when a user enters the given route. Therefore, what we need now is a bundle, which will hold our controller and action. Open up a console and type the following to create a bundle with a namespace Demo and a bundlename DemoBundle, resulting in Demo/DemoBundle:

php app/console generate:bundle

The new bundle can be now found in the src directory of our project. You will see that a basic bundle structure has been created for you. Open DefaultController.php in controller/. If you look at the action, you will notice some annotations that look like this:

  /**
   * @Route("/hello/{name}")
   * @Template()
   */

The @Route annotation tells Symfony that we want to match the route /hello/{name} with the action \Demo\DemoBundle\Controller\DefaultController::indexAction() and that there is a variable called name in the URL. So if somebody enters www.demo.com/hello/yourName or www.demo.com/app_dev.php/hello/yourName. The @Template annotation tells Symfony which View to use. When left empty, Symfony will guess which view to use view based on the controller name and action name.

All of our views are inside our bundle in Resources/views/. The views are separated into directories based on the controller responsible for the view. Hence the naming convention Bundle:Controller:View. Your base layout view (the main template of your application) is in app/Resources/views/. Since this is not in any Bundle nor Controller directory it is simply referred to as ::base.html.twig. A view in your bundle, which is placed in the root bundle-views directory, is referred to as Bundle::View.


Leave a Reply