RSS

Blog

Installing and using Symfony2 with Composer

By Konstantin Kudryashov (everzet)
2 January 2012
In the Development category

Are you tired of managing the deps and deps.lock files? Want to install BehatBundle without editing 3 files simultaneously and reading a long list of Mink dependencies that you need to place in deps? Composer to rescue!

And if you're new to Composer, check out the free Composer Screencast over at KnpUniversity.com.

Composer is a shiny new tool from the Symfony community, which aims to fix the dependency hell that we have right now in Symfony2. Also, Composer will become the core dependency manager for Symfony 2.1 when it's released. But you don't need to wait until then - you can use it for your Symfony 2.0 projects too. And today we'll show you how.

First of all, you need to know that Composer consists of 2 tools:

  • dependency management tool (Composer itself)
  • central package repository (Packagist)

They work together. Packagist holds info about almost any community package and its dependencies and Composer knows how to install them. But the cool part? Even if a library you need hasn't been registered with Packagist or doesn't have a Composer package configuration yet, you can still install it from git, svn, hg or even via Pear.! Yep, that's right, one tool to rule all your project dependencies nevermind where and how they are hosted.

Of course, adding dependencies for libraries that don't have a proper Composer package configuration is not entirely trivial. But fortunately, almost all Symfony2 bundles and community libraries have proper Composer packages nowadays: packagist.org/packages/behat.

Ok, but how to start? We have a surprise for you! The Symfony 2.0 Standard Edition completely integrated with Composer. Just download it from here and put it under your webroot as you do with usual STD edition.

Let's see what we have there. It's the same old STD edition except with a couple of changes. First of all, all dependencies are now managed with a composer.json file:

{
    "require": {
        "php":              ">=5.3.2",
        "symfony/symfony":  ">=2.0.7,<2.1.0-dev",
        "doctrine/orm":     ">=2.1.0,<2.2.0-dev",
        "twig/extensions":  "*",

        "symfony/assetic-bundle":         "*",
        "sensio/generator-bundle":        "*",
        "sensio/framework-extra-bundle":  "2.0.0-dev",
        "sensio/distribution-bundle":     "2.0.0-dev",
        "jms/security-extra-bundle":      "1.0.x-dev"
    },

    "autoload": {
        "psr-0": {
            "Acme": "src/"
        }
    }
}

Secondly, we've updated the bin/vendors script to use Composer internally. It has same old install and update commands, but it calls Composer internally to do dependencies management under the hood.

The third major change is the app/autoload.php configuration:

<?php

use Symfony\Component\ClassLoader\UniversalClassLoader;
use Doctrine\Common\Annotations\AnnotationRegistry;

$loader = require_once __DIR__.'/../vendor/.composer/autoload.php';

// intl
if (!function_exists('intl_get_error_code')) {
    $universalLoader = new UniversalClassLoader();
    require_once __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs/functions.php';

    $universalLoader->registerPrefixFallbacks(array(__DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs'));
    $universalLoader->register();
}

...

As you might see, there's no bundles or libraries here, only a

require_once __DIR__.'/../vendor/.composer/autoload.php';

call. It's because Composer automatically generates all the needed autoloading routines for you. Yep, forget about editing this file manually... forever! Every bundle will manage its autoloading path on its own and you will just edit composer.json. Look at it once again:

...

    "autoload": {
        "psr-0": {
            "Acme": "src/"
        }
    },
}

see this "autoload" section? It tells Composer where to find your own classes, because it (Composer) already know where to find everything else ;-) So when you need to add another namespace path under src/ like your vendor name, just add it to the composer.json "autoload" section:

...

    "autoload": {
        "psr-0": {
            "Acme":           "src/",
            "YourVendorName": "src/"
        }
    },
}

Ok, enough talk, let's install the Standard Edition:

$ bin/vendors install

Easy, right? But you might say that you had this already with the old bin/vendors script. And you'd be right... NOT:

{
    "require": {
        "php":              ">=5.3.2",
        "symfony/symfony":  ">=2.0.7,<2.1.0-dev",
        "doctrine/orm":     ">=2.1.0,<2.2.0-dev",
        "twig/extensions":  "*",

        "symfony/assetic-bundle":         "*",
        "sensio/generator-bundle":        "*",
        "sensio/framework-extra-bundle":  "2.0.0-dev",
        "sensio/distribution-bundle":     "2.0.0-dev",
        "jms/security-extra-bundle":      "1.0.x-dev"

        "behat/behat-bundle":             "*",
        "behat/mink-bundle":              "*"
    },

    "repositories": {
        "behat/mink-deps": { "composer": { "url": "behat.org" } }
    }

    "autoload": {
        "psr-0": {
            "Acme": "src/"
        }
    },
}

Yep. We've just added MinkBundle and BehatBundle with ALL their dependencies by adding only a few lines of JSON:

    ...
        "behat/behat-bundle":  "*",
        "behat/mink-bundle":   "*"
    },

    "repositories": {
        "behat/mink-deps": { "composer": { "url": "behat.org" } }
    }

Now you might miss adding SahiClient or downloading entire ZendFramework just because of Goutte? Forget about it! Composer will only download needed packages. And when i say needed - i mean only 5 ZendFramework components (~700kb instead of ~20mb) instead of whole ZendFramework.

Just run:

$ bin/vendors update

And you're ready to use BehatBundle with MinkContext inside your project through Goutte/Sahi or Zombie.js. Want to use CommonContexts too? Add:

"behat/common-contexts": "*",

under composer.json / require. Want to use FOSRestBundle? Add:

"friendsofsymfony/rest-bundle": "2.0.0-dev",

Just don't forget to call

$ bin/vendors update

You can find other bundles through Packagist website.

Learn more about Composer and Packagist:

  • 2013-01-27 Thomas Decaux

    Yes true, now it's just amazing ! Stable, lot of good resources ... 

  • 2012-08-13 Shwetanka

    composer doesn't work. At least the download link provided here doesn't. Using deps is better. 

  • 2012-07-18 Vladimir Droznik

     I would say that your comment late at least for 3-4 monthes. Composer is stable enough today.

  • 2012-07-14 Thomas Decaux

    Composer is really not mature yet and should not use for "real projects". Prefer git submodule (which do same thing) in a simple bash file, you will not loose ur time....

    Also, bin folder doesnt exist any more, you should refresh this nice post

  • 2012-05-07 tweini

    @ Christian Fritsch  registering is done in app/autoload.php which is properly included. No need to use Symfony\Component\ClassLoader\UniversalClassLoader.It's all done by Composer.For me it's all fine :-)

  • 2012-03-12 Christian Fritsch

    Hi,
    to run the symfony2 configuration, you have to register the DoctrineAnnotations in the AnnotationRegistry like this: 

    https://gist.github.com/202283...

    Otherwise, the DistributionBundle wont work

  • 2012-03-06 ShurikAg

    Hmm...
    When I deleted the content of vendors and tried to reinstall, the response for that was:

    Installing dependenciesNothing to install/updateWriting lock fileGenerating autoload files

  • 2012-03-02 Vladimir Droznik

    Composer is not very stable yet. Consider deleting vendors directory completely and run "composer.phar install" or "bin/vendors update". This helped me once in situation similar to yours.

  • 2012-03-01 Shurikag

    Hi, thanks for the post. It is helpful, I think :)
    We have a problem though:
    Then I try to run bin/vendors install or even composer.phar install I am getting an error on doctrine/dbal. I know it have not much to do with the way you setup the deps management, but How do I fight it.
    The error is:
    Failed to execute git clone 'https://github.com/doctrine/db... '/workspace/dev/symfony2/vendor/doctrine/dbal' && cd '/workspace/dev/symfony2/vendor/doctrine/dbal' && git checkout '2.1.6' && git reset --hard '2.1.6'

    Thanks,

  • 2012-01-18 Vladimir Droznik

    This helped to me too

  • 2012-01-17 Flo

    Problem solved. In the composer.json packaged with the line for Doctrine should be changed from

    "doctrine/orm":     ">=2.1.0,<2.3.0-dev",to

    "doctrine/orm":     ">=2.1.0,<2.2.0-dev",Otherwise composer gets in an infinite loop.

  • 2012-01-15 Flo

    Same on OSX. 100% PHP no traffic no output.

  • 2012-01-13 Vladimir Droznik

    Can't get "bin/vendors update" work on my windows box. After adding behat libs to .json it just loads one CPU core 100% forever (actually I waited about 5 mins, no network traffic at this time happened)

  • 2012-01-11 Cordoval

      Repository type is not registered: behat/mink-deps  

  • 2012-01-11 Cordoval

    thanks for the quick intro, although it would be great to see an example of pure composer composer.json, I am having problems with target-dir and now i have removed them else the packages don't install but now they cannot be found because of the dir namespaces are wrong https://github.com/vespolina/v...

  • 2012-01-05 everzet

    Just try again. `security-extra-bundle` package haven't been properly updated on Packagist. It's fixed now.

  • 2012-01-04 Matías Montenegro

    Testing this example.... It didn't work out. It throws this exception when i run "bin/vendors install":

    Package jms/security-extra-bundle can not be installed, either because its version constraint is incorrect, or because one of its dependencies was not found.

    Maybe i forgot something

  • 2012-01-03 everzet

    Updated ;-)

  • 2012-01-03 everzet

    We're waiting for a PR ;-)

  • 2012-01-02 Stof

    just a remark about the autoload file. You don't need to create a UniversalClassLoader for the fallback. Composer now supports defining autoloading fallback (even through composer.json)