A better way to work with Composer locally

Categories: Development

Working on a Composer package locally can be challenging. You don’t want to commit changes to Git just to test something, and constantly updating Composer to see changes isn’t ideal either.

Previously, I often used symlinks for local development, and I still occasionally do.

However, I’ve found an easier method for my core projects: using the Wikimedia Composer Merge Plugin. This approach simplifies working on projects without making significant changes to composer.json in situations where you don’t want to modify the file publicly.

The Wikimedia Composer Merge Plugin allows us to merge multiple composer.json files at runtime, offering flexibility for managing dependencies in complex projects.

Getting Started

Let’s pretend we’re developing a WordPress site and using Composer to install and manage themes. Our project includes the Axe and Handle themes from GitHub, and we also need to make updates to these themes locally before publishing.

Here’s an example of our composer.json setup:

{
  "require": {
    "adampatterson/axe": "dev-main",
    "adampatterson/handle": "dev-main"
  },
  "repositories": [
    {
      "type": "vcs",
      "url": "[email protected]:adampatterson/Axe.git"
    },
    {
      "type": "vcs",
      "url": "[email protected]:adampatterson/Handle.git"
    }
  ]
}

Folder Structure

/sites/
    /wordpress.test/
        composer.json
        composer.local.json
    /axe/
        composer.json
    /handle/
        composer.json

Install the Merge Plugin

First, install the Wikimedia Composer Merge Plugin in your project:

composer require wikimedia/composer-merge-plugin

Next, configure the plugin in your composer.json file to include a local configuration:

{
  "require": {
    "wikimedia/composer-merge-plugin": "^2.1"
  },
  "extra": {
    "merge-plugin": {
      "include": [
        "composer.local.json"
      ],
      "replace": true
    }
  }
}

Define Local Packages

Create a composer.local.json file to define your local packages. This file should also be added to .gitignore to prevent it from being committed.

{
  "repositories": [
    {
      "type": "path",
      "url": "/Users/adam/Sites/wordpress/Axe"
    },
    {
      "type": "path",
      "url": "/Users/adam/Sites/wordpress/Handle"
    }
  ]
}

Now, when you run composer install or composer update, your themes will be symlinked automatically.

Working with Published Packages

If you want to install only the published packages, you can run:

composer install --no-plugins

However, keep in mind that WordPress themes and plugins managed with composer require composer/installers, which will be ignored when using --no-plugins. To work around this, temporarily rename your composer.local.json file before running the command.

Could you use this with Laravel?

Absolutely!

If you create a new Laravel project then yes, you can modify your composer.json file as mentioned above except that we’re going to need to include laravel/framework in composer.local.json.

{
    "require": {
        "laravel/framework": "*"
    },
    "repositories": [
        {
            "type": "path",
            "url": "/Users/adam/Sites/forks/framework"
        }
    ]
}

If you’re working on laravel/laravel then I’d say no, since we don’t want to add the Wikimedia Composer Merge Plugin to the public repo.

Using the Wikimedia Composer Merge Plugin streamlines local development and testing for Composer projects, especially when working with themes or plugins in WordPress. It’s a flexible, efficient solution that avoids cluttering your Git history with unnecessary commits.\


Adam Patterson

Adam Patterson

User Interface Designer & Developer with a background in UX. I have spent 5 years as a professionally certified bicycle mechanic and ride year-round.

I am a husband and father of two, I enjoy photography, music, movies, coffee, and good food.

You can find me on Twitter, Instagram, and YouTube!