In this article we are going to discuss on how to structure your reusable bundle in Symfony2. Application bundles in general should be as simple as possible. As a result of this, the following steps might not be applicable/ suitable for application bundles. This article pertains to reusable bundles alone.
Symfony is a quite popular PHP framework, and there are justifiable reasons for it. With Symfony we can create PHP web applications. It contains a set of reusable PHP components/libraries and also a lot of predefined libraries to handle database management, users, etc…
What is Symfony Bundles?
Symfony has this great concept called bundles. A Symfony bundle is mostly like a plugin in a web CMS like WordPress, Drupal, etc. Symfony provides bundles that include many core functionalities, but you can also write your own custom bundle. Custom bundles are written to suit your application. The main advantage is that, a bundle gives flexible pre-build features. You can package them and thus distribute as your own third-party bundles. Thus, a reusable bundle in Symfony2 is created. This allows anyone to easily pick the bundle needed, based on their requirement.
Below, we explain about how we need to structure the reusable bundle in Symfony2.
First of all, let me describe a bundle name. It is actually a PHP namespace and therefore it has to follow the PSR-0 or PSR-4 interoperability standards. The rule is that it should start with a vendor segment, followed by sub-category segments, if any, and it should end with the word ‘Bundle’.
Following are the rules for the Bundle class name:
- Only alphanumeric characters and underscores
- Camel casing
- Use a descriptive yet short name (Preferably less than or equal to two words).
- The name should be prefixed with the vendor.
- As mentioned above, the suffix must be ‘Bundle’.
Here are some valid bundle naming examples:
The basic directory structure of an SchoolBlogBundle must read as follows:
In order for the automated tool to handle and manage the bundle, the below files are necessary:
SchoolBlogBundle.php: This file must contain “SchoolBlogBundle” class, since this class will convert the directory into a Symfony bundle.
README.md: Contains basic details of the bundle. It may have some examples and documentation for how to work with the bundle.
LICENSE: This contains content of the license for the code and third party bundles. It will be publish under MIT license.
Resources/doc/index.rst: Root file for the Documentations.
Note: For those classes and files which are used more frequently, the use of depth of sub-directories should keep to the minimum (as much as possible). This is necessary in order to avoid complexities.
Following classes and files have their own unique functionalities. Some of these are mandatory while some are not.
The above classes and files are used based on the requirements and needs. In the following section, I have given a brief description of the components of reusable bundles.
All the bundle classes should follow the Symfony namespace hierarchy. For example, a controller class ContentController should be stored as ‘School/Bundle/BlogBundle/Controller/ContentController.php’. Then, the namespace to use this class name is ‘School\Bundle\BlogBundle\Controller\ContentController’. Also, all classes and files should follow the Symfony coding standards.
Also we have some additional features like Commands, Helpers, Listeners and Controllers. If the classes connect to the event dispatcher, then it should be suffix with ‘Listener’. Similarly, exception classes should be suffix with ‘Exception’.
Reusable bundles should come with their own test suite. They should be stored under the Tests/ directory. Following are the rules that the Test Suite should adhere to:
- The test suite should be written with PHPUnit.
- It should be executable via a simple PHPUnit command.
- The functional tests should use test only response output.
- The test suite should cover at least 95% of features.
- Lastly, it should not contain the AllTests.php.
All bundle classes and functions should have proper documentation. It should be written in PHPDoc.
In Symfony we can write specific routes for each bundle. The bundle routes must be prefix with bundle alias. For example, if the bundle name is ‘SchoolBlogBundle’, all routes should be prefix with ‘school_blog_’.
In Symfony we can write our own templates, which should use the Twig extension. Also this template should provide main layout.
We can provide configurable settings to our own reusable bundle in Symfony2. Configuration parameters should be key/value pairs and the value should be valid PHP values. For identification purposes, all parameters should be prefix with bundle alias name. This is to be follow by period (.) in order to separate those parameters (e.g. school_blog.author.email).
The end user can overwrite values in any configuration file, as follows:
# app/config/config.yml parameters: school_blog.author.email: 'firstname.lastname@example.org' <!-- app/config/config.xml --> <parameters> <parameter key="school_blog.author.email">email@example.com</parameter> </parameters> // app/config/config.php $container->setParameter('school_blog.author.email', 'firstname.lastname@example.org');
In order to retrieve the configuration:
For proper version management, you should follow the Semantic Versioning Standard.
The following metadata should include in the composer.json file:
name – It contains the vendor and the short bundle name (e.g. johndoe/school-blog-bundle).
description – Brief description about the bundle.
type – Use the symfony-bundle value.
license – Any third-party license. The preferred license is MIT.
autoload – This information is used by Symfony to load the classes. The PSR-4 autoload standard is recommend.
To finish the article,
In order to make the bundle easier to use for developers, we can register the bundle to Packagist. This is the official repository for PHP Libraries in composer.
This article should suffice you to create your own reusable bundle in Symfony2. I hope this has been useful. Happy Coding…