This post ist partly a recap of the symfony life 2014 in Berlin where Toni (@havvg) and I did a "Lightning-Rant" on this topic. For some time now, we've been sporadically discussing the placement of models in the "VC-style-framework" symfony2. SFUGSTR did a whole meeting about that back in 2013 with great and controversial discussion :-) And since the new "Best Practices" book for development with symfony has emerged, I think it's time to write a little something myself.
As of now we've witnessed a lot of developers in projects using bundles to structure their applications, which - in itself - is no bad thing per se. Especially when starting to develop with symfony2 for the first time, it is not that easy to fully grasp the abstractness of the architecture and structure code accordingly. The basic idea of a bundle is having a container to put alle framework-related or -coupled stuff in a dedicated place where it can be found and interpreted. That's it! Framework stuff! A lot of people start packing "utilities", models, ... into a "CoreBundle" or "AppBundle" and that's not right (from an architectural point of view). To solve this misery there are a few approaches and I am going to discuss two of them.
I assume following scenario, which I think is most common:
- we have an application we know to most likely stay with symfony2 as framework
- we are likely to have a lot of business logic
- the application uses a database and therefore entities and repositories
The "one bundle to rule them all" approach
This is my preferred approach ;-)
We're using exactly one bundle, no vendor namespace - I love calling it the "CoreBundle" - and place a second folder into the
<project>src/ folder, called "Core" or whatever you want to name your business logic container. Within this container, I usually place every part of my business logic I do not get as an external library via packagist. To access this stuff, I create service definitions within the CoreBundle. Also I tend to place all controllers within the bundle, since they are also tightly coupled to the framework.
project_root |- app | |- ... | |- src | |- CoreBundle | |- Core | |- subnamespace1 | |- subnamespace2 | |- ... | ...
In my opinion this looks quite concise and also I love the extra part of the namespace, containing all my business logic (Core).
- The overall structuring directory-wise is easy to grasp for people working with sf2
- No changes concerning class-loading is needed, everything works out of the box
The "no bundle" approach
project_root |- app | |- ... | |- src | |- Controller | |- Entity | |- Repository | |- .... | ...
As you can see, this flattens the project structure in an immense way and also allows for nice DDD. Downside is: You have to overwrite e.g. the ApplicationKernel to be able to find Controllers and locate all the other stuff. For the people asking themselves "where are the templates and other files?!": They need to be placed in
What does this mean for my OSS bundles?
I know, there are loads of bundles around in symfony-world. And lots of them have business logic within their directory structure. If you want to de-clutter this mess, try following approach: Pack all the relevant business-logic into a framework-decoupled package (library!), promote it on packagist and then write a bundle to make the library easily accessible via frameworks like symfony. Read this article for a nice approach to make your bundle framework-interoperable!
More to read on this topic: