Ah, the AppBundle: my favorite part of the Symfony best practices.
RYAN, What are you an idiot!? That's a terrible idea!
Ok, not everyone agrees - it's cool :). But here's what's interesting: if you don't like the AppBundle, I bet I actually agree with your reasons.
What!?
Let's figure this out in 10 Steps.
I mean this with <3. We're using Symfony! This means you can do whatever you want. Nothing has changed in Symfony to prevent this, and nothing will. That's an awesome start.
A traditional Symfony project is made up of bundles that are coupled together. Ok, maybe you have some standalone bundles, but somewhere, there's a group that are really coupled. And that's great! We're building an app here, not an open-source library. These coupled bundles are your app.
But in this case, they aren't really bundles: they're just directories. There's no technical advantage to having 1 or 10: we're just trying to organize things to our subjective liking.
A true bundle is a standalone, reusable entity. These are just directories.
Now, if we decide to move everything into one bundle, it's nothing more than
a different directory structure. You can even keep the same amount of organization
by putting sub-directories in Controller
or anywhere else.
You might like this, or you might not. The point is: it's subjective, there's no technical benefit of having multiple bundles.
Your application is AppKernel, and it lives in app/
. It builds our
1 container, 1 compiled list of routes, 1 collection of translations, 1 group
of mapped entities and everything else. Even if you have these things spread
out across bundles, it's all loaded right here.
So why not move more things into app/
? Remember, we're not planning on
re-using this stuff somewhere else.
Since each kernel has only one container, it's logical to move service
config out of the bundle and into app/
.
But if I move my service configuration out of my bundle it's coupled to my app
That's right! But it probably already was coupled. And if you do need to re-use something, great! Put it in a true, standalone bundle. Here, I'm talking about moving pieces out of bundles that are truly a part of your app.
***TIP
Like with everything, if you have a lot of services, feel free to create
an app/config/services
directory with multiple files.
Next, let's move the templates into app/
. I know many people hate this,
because it puts the templates in a different directory than the controllers.
That's subjective, but fair - and I talk about that later.
This is a subjective change, but it has one hidden improvement: you no longer need to use the weird three-part colon syntax. As a Symfony expert, you know this syntax. But I give a lot of trainings, and these Symfony-isms give beginners a lot of trouble.
Instead, you just render the filename. The only rule you need to know is
that templates live in app/Resources/views
. This reduces complexity,
and that's huge.
You can keep doing this until AppBundle holds only PHP classes.
But wait, why do we need a bundle at all then? You don't! A bundle is just
a directory! And we can rename directories! We could rename this to Ryan
and even delete the bundle file.
***TIP You can start thinking of AppKernel as your one "bundle". It can do anything a bundle can, including complex stuff like registering compiler passes.
So why isn't this the Symfony best practice instead of AppBundle? A few reasons:
-
Without a bundle, you lose a few shortcuts, like the
_controller
shortcut and the automatic bundle aliasing for entities (e.g.AcmeDemoBundle:Post
). All of these are optional, but it's more work without them. -
It would be a big philosophical leap, and change needs to be done carefully. Having only one bundle was a big enough change.
But philosophically, I do hope you'll think of your AppBundle
as just
a directory for PHP classes. And for Symfony 3.0, maybe we'll get there!
The biggest complaint I've heard about the AppBundle is this: I don't like
that my controllers would live in src/
, but the templates they render
would live in app/
.
That's subjective, but totally fair (it hasn't bothered me).
To solve this, we could move our Ryan
directory (or AppBundle
, before
my rename) into app/
.
This works with no code changes except for a new autoload entry:
{
"autoload": {
"psr-4": { "Ryan\\": "app/src" }
}
}
I'm not recommending that everyone runs and does this, but logically, everything
is coupled to app/
, so it makes perfect sense. I hope it at least gets
you thinking!
***TIP
Still want the templates closer to the controllers? No problem, keep
them in AppBundle
:).
Sweet! Just create a directory in src/
and put your decoupled library
right there. It's ready to be re-used!
Nice! Just create the bundle in src/
(or vendor/
, etc) and treat
it like true, decoupled bundle.
Still feel like you need more bundles? No worries - create as many as you
want. But don't be afraid to choose one bundle that you really couple
to your app/
directory - it might just make your life simpler.
Multiple kernels? Sounds like a neat project :). You should have one super-coupled
bundle per kernel. For example, WebKernel
& WebBundle
, ApiKernel
and ApiBundle
. If you need to share things between kernels, put this
into proper, de-coupled bundles that are booted by each kernel.
One main argument against the AppBundle is that you should make your code modular. I agree! But having 1 directory or 10 doesn't make a difference. But these things do:
-
creating service classes, with minimal dependencies (+ skinny controllers);
-
(if applicable) identifying parts of your code that you truly need to re-use between projects/kernels and writing them as proper bundles or libraries;
-
potentially creating multiple, focused apps (e.g. backend API, frontend app, separate app for handling jobs, etc).
So even if you don't like the AppBundle, I hope you'll see that it has nothing to do with writing more or less modular code. That's still up to you :).
<3 Ryan