Dev Notes

Software Development Resources by David Egan.

Initial Workflow for Composer Package Development


Composer, PHP, Workflow
David Egan

During the initial stages of developing a Composer package, you probably don’t want to go to the trouble of setting up an empty Packagist package. You probably also shouldn’t be developing in the vendor directory.

I haven’t done much research on the best workflow for this solution - but the method described in this article, which utilises a Composer path repository - seems to work pretty well. I heard Taylor Otwell (creator of Laravel) talk at Laracon Online last week and he uses this approach.

Initial Setup

In your project root directory, create a ‘packages’ directory. This in turn should contain a ‘vendor-name’ directory which shouild contain a ‘package-name’ directory:

cd /path/to/project/root
mkdir -p packages/vendor-name/project-name

I think it’s best to name directories according to Packagist naming conventions.

Composer Init in the New Project

Move into your project and run composer init:

cd packages/vendor-name/project-name
composer init

Composer will prompt you to set important metadata like the package name. This will be needed later when Composer (at the parent project level) attempts to auto-load your new project files.

Set Up Path Repository

In the main project composer.json, you need to create a path reference for your package within the “repositories” section. The following fragment from the parent project composer.json defines two Composer path repositories, sage-blade-data and wp-metadata-accessor. In this particular case, the parent project is cloned from the Sage WordPress starter theme - which comes already set-up for Composer.

{
    "repositories": [
        {
            "type": "path",
            "url": "./packages/carawebs/sage-blade-data"
        },
        {
            "type": "path",
            "url": "./packages/carawebs/wp-metadata-accessor"
        }
    ]
}

Require Local Packages in composer.json

Once the repositories have been set up with the correct path, you can add them to the project dependencies, as shown in this extract:

{
    "require": {
        "php": ">=5.6.4",
        "composer/installers": "~1.0",
        "illuminate/view": "~5.4.0",
        "illuminate/config": "~5.4.0",
        "carawebs/sage-blade-data": "dev-master",
        "carawebs/wp-metadata-accessor": "dev-master"
    }
}

Important: if you have a local repo without releases (maybe you haven’t even run git init yet), you need to specify "dev-master" for the required local packages. "*" won’t work.

Autoloading

Within the new project composer.json, set up autoloading paths:

{
    "name": "carawebs/sage-blade-data",
    "description": "Data controllers for Sage 9 WordPress theme - insert data into Blade templates.",
    "type": "library",
    "license": "GPL",
    "authors": [
        {
            "name": "David Egan",
            "email": "david@carawebs.com"
        }
    ],
    "autoload": {
        "psr-4": {
            "Carawebs\\SageBladeData\\": ""
        }
    },
    "require": {}
}

This sets the new project’s namespace. Once you’ve run composer update, your project classes will be autoloaded.

Run:

composer update

In the parent project root directory. Composer will then create a new vendor-name directory with the project vendor directory. The package files will be symlinked here. For example:

cd /path/parent-project/vendor/carawebs

david@david-desktop:/path/parent-project/vendor/carawebs$ ls -la
total 8
drwxrwxr-x  2 david david 4096 Mar 16 18:27 .
drwxrwxr-x 11 david david 4096 Mar 16 18:27 ..
lrwxrwxrwx  1 david david   39 Mar 16 15:21 sage-blade-data -> ../../packages/carawebs/sage-blade-data
lrwxrwxrwx  1 david david   44 Mar 16 18:27 wp-metadata-accessor -> ../../packages/carawebs/wp-metadata-accessor

This allows you to work on your new package from within your packages directory, but still have your project included within Composer (with dependencies, autoloading, etc).

Composer Update Problems

I recently hit a snag when setting up a package for development in a Laravel project:

Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - The requested package carawebs/repositories dev-master exists as carawebs/repositories[dev-repo-pattern] but these are rejected by your constraint.

This happens because if the path-repository project that you’re requiring is not a VCS repository, you need to explicitly define the version in the package composer.json file:

If the package is a local VCS repository, the version may be inferred by the branch or tag that is currently checked out. Otherwise, the version should be explicitly defined in the package’s composer.json file. If the version cannot be resolved by these means, it is assumed to be dev-master.

Composer documentation on path repositories.

In my case, I solved the issue simply by running git init in the package directory.

References


comments powered by Disqus