Symfony2, Tutorials

Using composer with Symfony2

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).

The 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:

  1. Check for an existing composer.lock file. If one is not found, generate it from the contents of the composer.json manifest
  2. Ensure that the dependencies in the vendor directory 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-install and 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.

6 thoughts on “Using composer with Symfony2

  1. Be extra careful on the use of upgrade!!!
    Upgrade will bypass your lock file. It seems great but is quite dangerous as well. The lock file should be touched carefully and stored in your VCS so that everybody in a team shares the same one.
    This means everybody works with the exact same versions of the dependencies.

    Think of the PR I did on ProblematicAclManagerBundle for example. It was a BC break of the API and there are no tagged versions on git for that bundle, so users of the bundle always pull from “master”. If I keep using “install” with my lock file, I’ll keep getting the same old commit as before and no BC break come ruining my day.

    If I use upgrade, I get the BC breaking version even if I was just fine using the previous one until the end of times!

    1. Thanks for pointing this out. I try to stay current with the master versions of all dependencies in the code that I write, so this has honestly never been an issue for me, but you’re absolutely right: using these commands without understanding exactly what they will do can be dangerous. Fortunately, your lock file should be versioned, so if you run up against a problem like this, you can revert (either fully or partially) back to the pre-breaking change.

  2. First off, thanks for taking the time to post about this. I have done a little digging and im trying to setup a “symfony2-assets” type that will basically install the repositories into the web directory in a symfony project. I cant seem to find any good documentation on creating a custom installer for a custom type. If you know of and good resources or know how to accomplish this any information that you provide will be greatly appreciated.

  3. I am trying to port an app to Symfony 2.1 from 2.0 in the hope that traits and the new array syntax (php 5.4) are finally accepted in entities and repositories. Perhaps I’m too optimistic, but thought I’d give that a try.

    What an ordeal. And they say that using a framework is supposed to save us development time. That’s bs. All the time that’s saved is wasted many times over whenever one needs to upgrade.

    I just can’t find a way to install problematic aclmanager properly using composer. It keeps saying that either there is a typo in the package name or etc etc.

    So I inserted it in the directory structure manually. Changed the kernel. And the ordeal continues. Namespaces related to the problematic module are not recognized. So I ‘require’d the aclmanager file directly in the kernel. But later in the app loading process, namespaces defined in the now successfully required Problematic files are still not found.

    The autoload.php is now claimed to be much simpler than before. It’s now just a few lines and I guess that’s supposed to mean it’s simpler. Problem is: before, we could change it when needed. Now, good luck.

    My frustration level is quite extreme. It seems that the only way to survive in the Symfony world is to be willing to reverse-engineer anything that’s thrown at us with no or scant documentation.

    Anyway… I fell better now that I’ve vented a bit…

    So the question remains: how to use Problematic acl-manager-bundle in S2.1, either with composer (preferred way of course) or manually????

  4. composer upgrade now seems to be called composer update (which is throwing one error after the next, here … this doesn’t seem en par with other package managers at all).

Leave a Reply