So it’s been on the radar for a while, but Symfony2 recently switched over to composer for package management, moving away from the homebrewed
bin/vendors install method. Playing around with it, a few things were non-obvious to me… and judging by the number of search engine hits on “symfony2 composer tutorial,” it’s apparently non-obvious to a few other people as well. So, I thought I’d just share some observations. Hope they’re helpful.
composer packages are not the same as git repos
The old dependency management system just cloned git repos, and locked them to a specific commit, tag or branch if you asked it to. It was simple, but it lacked functionality like dependencies of dependencies, version requirements, and so on. True, composer is a little more complicated, but it has all these features.
For example, if I tell composer to use the FOSRestBundle as a dependency in my project, but I don’t have the JMSSerializerBundle also listed, it will see that the RestBundle depends on the SerializerBundle, and download that as well. That lets you keep your composer manifest neat and tidy, without worrying about missing sub-dependencies.
You can search through available repos on packagist.org. Most of the well-maintained projects are available there (and I just condemned myself, because I don’t think my ACL manager bundle has a composer file yet. Oops).
install command may not work like you’d expect
At least, it didn’t for me. I cloned the Symfony2 Standard Edition project, added the FOSUserBundle as a dependency, and ran
php composer.phar install. It crunched a minute, said it was downloading some stuff… and I still didn’t end up with the user bundle in my
vendor directory. lolwut.
As it turns out, the steps that the
install command follows look something like this:
- Check for an existing
composer.lockfile. If one is not found, generate it from the contents of the
- Ensure that the dependencies in the
vendordirectory match the dependencies required in the lock file, by downloading, updating or deleting vendor bundles as necessary
Coming into a project that has an existing lock file (which the Standard Edition does), running the
install command will only ever operate against that lock file, no matter how much the manifest file is changed. The solution turned out to actually be quite simple: modify the manifest file, then run
php composer.phar upgrade… the
upgrade command will generate a brand spanking new lock file from the latest version of the manifest and update vendor dependencies against it. Simple, but non-obvious to me at first.
autoload.php just got a whole lot easier to manage
Easy as in, you don’t have to touch it at all most of the time. Symfony2 now uses composer’s autoloader, which quite magically knows how to load all of the dependencies that it has downloaded. Once you get all your dependencies in place (
php composer.phar upgrade if you’re having trouble, remember), everything should Just Work, and you should only need to modify
autoload.php if you have a library that needs special treatment.
script hooks are awesome
True story: you can provide composer with static methods on classes to handle certain events that happen during the composer lifecycle. For example, the Symfony2 Standard Edition calls methods in the SensioDistributionBundle on
post-update to build the bootstrap cache file, clear the cache and install assets. Check ’em out.
This move is a good thing
Yeah, it’s different, and different is scary. But it’s good. Trust me. Remember what I said about focusing your efforts on writing application logic? Yeah, that applies to framework developers, too. Using composer lets the Symfony2 team focus their attention on the framework and its components, and still have the benefit of a feature-rich package manager. Win, all around.
composer isn’t just for Symfony2
Composer was inspired by Ruby’s bundler and node’s npm… it’s not just for Symfony2, you can use it for any PHP project. As long as your naming conventions are PSR-0 compliant, the composer autoloader will hook you tha eff up, homeboy. So have fun.
That about wraps it up, hope it helped. Any questions, post in the comments or shoot me an email.