Composer for
Corporate Use

Stephan Hochdörfer // 04.10.2014

About me

  • Stephan Hochdörfer
  • Head of Technology, bitExpert AG
    (Mannheim, Germany)
  • @shochdoerfer

  • #PHP, #DevOps, #Automation

Our story: Diversity

Back in the days: Subversion

No fixed dependencies

How can Composer help?

Clear dependencies

Transitive dependencies?

Transitive dependencies?

Transitive dependencies?

Security issues?

Check composer.lock file

$ php security-checker.phar security:check ./composer.lock
Security Check Report

Checked file: composer.lock

  0 packages have known vulnerabilities

Check composer.lock file

$ curl -H "Accept: application/json" -F lock=@./composer.lock

Be aware of licensing issues

Tracking package licenses

$ composer.phar licenses
Name: customer/project
Version: 1.0.0
Licenses: proprietary

  phpoffice/phpexcel         1.8.0    LGPL
  pimple/pimple              v1.1.1   MIT
  psr/log                    1.0.0    MIT
  silex/silex                v1.2.1   MIT
  symfony/debug              v2.5.4   MIT
  symfony/event-dispatcher   v2.5.4   MIT
  symfony/http-foundation    v2.5.4   MIT
  symfony/http-kernel        v2.5.4   MIT
  symfony/routing            v2.5.4   MIT

Perspective change

Small problem domains

Choose the "perfect" toolset

Build your own packages

Package design challenges

Composer Use-Cases

1. Simplify your project setup

Set-up a new project

$ composer.phar create-project symfony/framework-standard-edition 
$ composer.phar create-project --repository-url=https://satis.loc 
  my/installer myproject

Custom project installer

    "name": "my/project-installer",
    "type": "project",
    "license": "MIT"
$ composer.phar create-project --repository-url=https://satis.loc 
  my/project-installer myproject

Speeds up your project setup

Customizing customers apps

Standardize package layout

2. Split app, maintain core lib

3. Custom package events

  • (pre|post)-install-cmd
  • (pre|post)-update-cmd
  • (pre|post)-status-cmd
  • (pre|post)-package-install
  • (pre|post)-package-update
  • (pre|post)-package-uninstall
  • (pre|post)-autoload-dump
  • ...

Create custom scripts

    "scripts": {
        "post-update-cmd": "My\\Composer\\PostUpdate::execute",
        "post-install-cmd": [

Manage assets

Vagrant Cachier Plugin

$ vagrant plugin install vagrant-cachier

Vagrant.require_version ">= 1.6.0"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

    if Vagrant.has_plugin?("vagrant-cachier")
       config.cache.scope = :box
       config.cache.enable :composer

    config.vm.define "wheezy" do |wheezy| = 'debian-wheezy-64'

Private packages?

Hosting your packages

Satis is a ultra-lightweight, static
file-based version of packagist.

Installing Satis

$ composer.phar create-project composer/satis --stability=dev

Running Satis

    "name": "My own repo",
    "homepage": "http://satis.mydomain.loc",
    "repositories": [
        { "type": "vcs", "url": "http://git.mydomain.loc/repo1.git" },
        { "type": "vcs", "url": "http://git.mydomain.loc/repo2.git" }
    "require-all": true,
    "archive": {
        "directory": "dist",
        "format": "zip",
        "skip-dev": false
$ php bin/satis build config.json web/
$ php bin/satis build config.json web/ mycompany/mypackage

Mirror packages

    "name": "My own repo",
    "homepage": "http://satis.mydomain.loc",
    "require-dependencies": true,
    "require-dev-dependencies": true,
    "repositories": [
        { "type": "vcs", "url": "" }
    "archive": {
        "directory": "dist",
        "format": "zip",
        "skip-dev": false

Your Satis Repository

Using Satis

    "require": {
        "php": ">=5.5.0",
        "zendframework/zend-mail": "2.2.*@stable",
        "mycompany/mypackage": "2.4.*@stable"
    "repositories": [{
            "type": "composer",
            "url": "http://satis.mydomain.loc/"
$ composer.phar install

Access Control?

Credential handling

$ composer.phar install
Loading composer repositories with package information
    Authentication required (satis.mydomain.loc):
      Username: myuser
Do you want to store credentials for satis.mydomain.loc in 
~/.composer/auth.json ? [Yn]

Credential handling

    "http-basic": {
        "satis.mydomain.loc": {
            "username": "myuser",
            "password": "mypassword"
        "git.mydomain.loc": {
            "username": "mygituser",
            "password": "mypassword"
        "svn.mydomain.loc": {
            "username": "mysvnuser",
            "password": "mypassword"

Toran Proxy

Toran Proxy Setup

$ wget
$ tar xvfz toran-proxy-v1.1.4.tgz
$ cp app/config/parameters.yml.dist app/config/parameters.yml
$ php app/console server:run --env=prod

Your Toran Proxy

Jenkins Node Config

Jenkins Node Environment

Jenkins Job Config

Push Config files to node

Validate composer.json

Installing dependencies

Running the build

Run satis build for package

Jenkins Satis Job Config

Define Job Parameters

Executing Satis

Notify users after build

Running the build


Thank you!

Do not forget to rate the talk: