Stop making bundles !
Think bundles and use the Components !
TLDR; In the Symfony full-stack framework, bundles are meaned to wrap php libraries inside the framework.
This blog post is focused for people starting building new php libraries or intend to create new bundles.
There is no bundle for that !
You have heard so many times there is a bundle for this, there is a bundle for that, that’s right, so many people have done an awesome job and we can’t argue about it, giants like FOS, Liip, Sonata etc.. have helped the community, but there is a point and don’t take my following words as a remark but as an opinion, they’ve helped only the Symfony full-stack framework community .
Symfony 2 has been a revolution in the past years and I think there is a high percentage of new applications that have been built around the framework.
When starting new projects, we did of course want to use the Symfony framework, it was and still is the high-tech of the php ecosystem. So we’ve built bundles, because it’s the fashion and everybody is saying to do it for reusability purpose.
YES it will be reusable, but only for the full-stack framework !!!
Think bundles but use the components !
Of course, there is a high percentage of use cases when doing a bundle is necessary, but not always.
If you’ve ever built a bundle, you know the principles. You define configuration in the config.yml file, you define your services in the services.yml file and the Dependency Injection folder do the job of mixing all of that and define it in the service container.
If you think in the same manner when building new php libraries, and use the Symfony Components for your configuration and service definitions, you’ll have a library that will be almost natively compatible with the full-stack framework.
The Config and Dependency Injection Components
When building new libraries, as small as it can be, chances are that you will deal with multiple responsibilities and configurations.
Use the components! It will avoid you all the burden of multiple arrays and if/else for configuration validation. And use the container to easily retrieve the multiple parts of your library.
A simple library directory structure that will for e.g. deal with connections to servers and multiple commands to execute on the servers could look like this.
You see, it is not a bundle but the directory structure is like a bundle.
In the “Application.php” file, you’ll create a new Container and a build method that will load the user configuration file and also load the Extension class from the DI folder.
In fact, in the build method, you are doing now exactly what is happening in the framework, you have a container, you load configuration, you pass this configuration to the extension class for merging and validation, and then you compile the container.
The service definitions in the Resources folder :
And your Extension class :
Ok it is really like a bundle, but you can use this library now simply by loading a user configuration file and building the container :
Think bundles but not too much !
If you need to use your awesome new php library inside the Symfony full-stack framework, you’ll say I need a bundle. Yes it could be an option but you already have 90% of the job done natively.
If you run the php app/console generate:bundle command, you’ll come with exactly the same structure and classes.
So let’s start the integration, create a folder Integration in src/Acme, and create your AcmeBundle class:
You can now declare your bundle in the AppKernel.php class of the framework,
new Acme\Integration\AcmeBundle();
The framework will complain because he do not find the Extension class, so let’s create it in the DependencyInjection folder of the Integration folder ☺
As all the job was already done in the primary Extension class, let’s just extend it :
Hey I have now a bundle !
You have now a library that you can use standalone, and also as a bundle in the framework, all in one repository. You can get your services as you would do with any other bundle.
If you do tests for the framework, any code change you’ll do that can break the framework integration will be automatically detected. No need to maintain two separated repositories for one feature. When your library grows up you’ll have an automatic result of reusability in the framework.
Conclusion
If you are at the point of creating a new php library, you should use these two components, and of course the HttpKernel component if you have to deal with Request-Response scheme.
With such method in mind, your library will be compatible for the framework and if another library using the same scheme want to benefit from your feature, she just need to locate your DependencyInjection folder and load the extension class by passing her proper container.
In a not so far future, maybe we will have the chance to see such Integration folders inside libraries :
As a conclusion note, I want to thanks all the people involved in making the php ecosystem better and better and want to show respect to FOS, Liip and Sonata work that I’ve mentionned in the beginning of this blog post.
I want also to invite people to use the components first, you’ll have a better understanding of the framework itself, but you’ll build strong libraries that are really reusable.