David Rekowski's random stuff

Using git and symfony and composer


I set up git for use with symfony and composer


symfony, composer, symfony2, uberspace, git


What I want to achieve is to be able to push symfony vendor modules to git on a uberspace host and check it out via composer. The repo is supposed to be private, since it holds my custom application and probably content data. This is more of a reference for me for later use, but if it aids you, help yourself. Keep in mind this is for symfony versions >= 2.1 (in beta4, currently); older versions used a deps file and handled autoloading differently.

I also documented how I installed composer and how I installed symfony on uberspace.

Setting up the repositories

According to the uberspace git info page, I set up what repos I need. Then I move the files already existing (I ignore any previous git history they might have got) into the newly checked out repo (actually I need three, but for the purpose of this article, let's assume only one). The setup is pretty straightforward, only I put all repositories under ~/git to not clutter the home folder. Now I can git commit -a and git push the changes to the repository on the server.

Composer - lots of hours later...

I had some issues figuring out how to convince composer to correctly generate the autoloader. Part of the problem was that I used the vendor/<package> folder as part of the autoloader, which worked fine on my mac (case insensitive file system), but not so well on the uberspace CentOS box. Yeah, should've been obvious, but I figured the symfony autoloader would not be so PSR-0 strict as to demand case sensitivity. However, it helps to simply keep in mind to put the complete namespace/class structure below your package. Best of all: you can define the autoloader path in your package's composer.json; more on that further below.

Setup overview

By now the setup is like this: I have a local dev host, which I use to edit sources and test them directly. I symlinked the vendor/<my-packages> folders to my local git checkouts, which reside elsewhere, so I don't use composer for that part. Then there is a local staging host, which installs my packages via composer, just like the live system will do. This is to make sure the deployment works allright and I can test that without the risk of crashing the live system. Then there is the live system on uberspace. That's the setup, now on the deployment process...


Satis (don't mix it with Silex) is a tool to create a packages repository without requiring an own, full fledged packagist installation (I won't get into details of installing satis, it is straightforward).

Basically you give it a package definition json and it generates a packages.json which in turn can be used to load packages via composer. Let me elaborate:

First of all, all repositories we're referencing, need to have their own comopser.json file, which is evaluated by satis, an example looks like this:

{ "name": "myname/mypackage", "version": "0.1", "dist": { "url": "ssh://", "type": "vcs" }, "autoload": { "psr-0": { "Mypackage": "src/" } } }

Note the use of the autoload directive, which tells composer on installation, to set up the autoloader to look in vendor/mypackage/src for any classes starting with Mypackage (could also be a namespace, e.g. "Myvendorname\\Mypackage", make sure to escape any backslash).

In my case, I have a set of three git repositories I want to use. Thus my website-repositories.json I am going to pass to satis looks like this:

{ "name": "website-repos", "homepage": "http://mysite.tld", "repositories": [ { "type": "vcs", "url": "ssh://" }, { "type": "vcs", "url": "ssh://" }, { "type": "vcs", "url": "ssh://" } ], "require-all": true }

Note the use of ssh - you could use http:// for a public repo or IIRC also file:// for filesystem access.

This file resides on the webserver, since I need to be able to reference the packages.json remotely (remember local staging). I put the build call into a shell script for repeated execution:

#!/bin/bash ./satis/bin/satis -n build website-repositories.json /var/www/virtual/username/repo.hostname.tld/

This creates the packages.json and puts it into a subdomain I use for this purpose (this is nice with uberspace, since you can use a new subdomain simply by creating a folder). It also creates an index.html which I ignore here. The content of the packages.json looks something like this:

{ "packages": { "myname/mypackage": { "dev-master": { "name": "myname/mypackage", "version": "dev-master", "version_normalized": "9999999-dev", "time": "2012-08-02 14:50:20", "source": { "type": "git", "url": "", "reference": "789f557dede7b3926e400d3be51baf5112314567" }, "dist": { "type": "vcs", "url": "", "reference": null, "shasum": null }, "type": "library", "autoload": { "psr-0": { "Mypackage": "src/" } } } }, # # ... # repeated for other packages } }

Now I am all set up to use those packages in my symfony installation (local staging and on the live server). All I need to do is edit the composer.json and add the repositories and require statements:

# ... "require": { # ... # default vendors # ... "myname/mypackage": "dev-master", "myname/myotherpackage": "dev-master" }, "repositories": [ { "type": "composer", "url": "http://repo.mysite.tld" } ], # ...

Next I run composer update (expects composer to be in $PATH, otherwise use php composer.phar) and my dependencies are updated, installing my own packages as well.

I always empty the cache and refresh assets in order to be up to date, all in env=prod since I don't develop on staging or live. I also removed web/app_dev.php and app/config/*_dev.*

php app/console --env=prod cache:clear php app/console --env=prod assets:install --symlink php app/console --env=prod assetic:dump

And that's it. Thank you for reading. Any comments and corrections are welcome.