Using local packages as composer dependencies

Composer changed pretty much everything when it comes to including dependencies in PHP projects. No more SVN externals or copying large library folders into your project. This is really great, but there’s one thing I’ve been struggling to find a smooth process for; developing dependencies for your project.

When implementing your project, the need for some module, library, service provider or something else will arise, and sometimes you’ll have to implement it yourself. So, how to do that?

Possible solutions

  1. Implementing it inside your project, maybe in the library or source folder. Would work, but if you want to publish it [on packagist.org or somewhere else] as a separate package later on, you will make extra work for yourself.
  2. Publish the non-working package on packagist and push changes to you VCS. This is a really slow work process, as it requires you to push and do a composer update to see the changes.
  3. The other way™

The other way

I’ve found that setting up a repository with a relative file system reference is the easiest way. This way, you can have your dependency separate from the application and getting changes in the dependency is as simple as running composer update.

Example

Given the following folder structure;

/
    project/
        composer.json
    package/
        composer.json
        src/Foobar.php

Package/composer.json

{
    "name": "larapen/package",
    "description": "My test package",
    "license": "MIT",
    "authors": [
        {
            "name": "Your Name",
            "email": "you@domain.tld"
        }
    ],
    "autoload": {
        "psr-0": {
            "Larapen": "src" 
        }
    }
}

This simply defines a composer compatible package and is pretty straight forward. Now, let’s take a look at the composer.json file for the project, where the “magic” happens.

Project/composer.json

{
    "name": "larapen/project",
    "description": "Test project",
    "license": "MIT",
    "authors": [
        {
            "name": "Your Name",
            "email": "you@domain.tld"
        }
    ],
    "minimum-stability": "dev",
    "repositories": [
        {
            "type": "vcs",
            "url": "../package"
        }
    ],
    "require": {
        "larapen/package": "dev-master"
    }
}

The repositories part of the composer file is the only thing special. There are several repository types, but the VCS type refers to some sort of version control resource (locally or externally). The repository portion of the composer schema documentation notes that this could be svn, git or mercurial (hg).

For this example I’ve used a relative local path and git. As shown in the composer documentation, using absolute paths or external URLs is also possible.

NOTE: If your package is published on packagist, you need to add --prefer-source option to force installation from VCS.

Running composer

$ cd package
$ git init
Initialized empty Git repository in /development/package/.git/

$ git add *
$ git commit -m "Initial commit"

At this point, a local git repo exists in the package folder and is now ready for inclusion in the project with composer.

$ cd ../project
$ composer install
Loading composer repositories with package information
Installing dependencies (including require-dev) 
 - Installing larapen/package (dev-master 4a111b4)
 Cloning 4a111b483843e75a3cb0ee794c0b9eaf0b75b395

Writing lock file
Generating autoload files

That’s it! After this point, whenever a change is made to the package, commit your change and do a composer update. Like this:

$ cd ../project
$ git commit -am "Changes"
$ cd ../project
$ composer update

Source: bytes.schibsted.com

Other Links