Distrakt
+44 (0) 121 212 9737 / team@substrakt.com
© 2019 Substrakt Registered in England. Company no. 5916054

Easy peasy composer local package symlink: composer-link

January 4, 2019

We utilize composer heavily for plugin development and versioning at Substrakt so when we need to add new features to a plugin it becomes a great big composer and git dance.

My preferred way to work with package development is to symlink the development version of the package I’m working on into the composer project that is being worked on. This also requires edits to composer.json and more composer command to correctly symlink it (process described here: Developing composer packages locally). Half the time though the symlink doesn’t work and I have to delete vendor and plugins.

JavaScript devs have it easy with npm link one command to link up their package and use it anywhere they need. This is what I want for composer. The author of ‘Developing composer packages locally’ also has a neat script described in Add composer-link command for local development which aims to do this but crucially does not support multiple repository definitions so still involves editing the composer.json manually for our use case.

Let’s improve the script.

Unfortunately we’re not able to do what we need with the commands available to us through the composer cli so we’ll need an extra tool to edit JSON files from the cli, JQ.

If you’re on a mac jq is available on brew: brew install jq

JQ will let us prepend a json object to the top of the repositories field in composer.json which is where we need to put our symlink info so that composer looks at our local package before requesting one from a different composer repository. The prepend operator in JQ is: |=

Using JQ our update command will look like:

jq '.repositories |= [{"type": "path", "url": "'$1'", "options": {"symlink": true}}] + . ' composer.json > composer.tmp.json && mv composer.tmp.json composer.json

The mv command at the end is required to capture the output of jq correctly.

That’s pretty good but we can do more. The original command requires you to also enter the package name when linking. We have jq at our disposal now though so we can use it to read the name of the package as we know the directory. We can therefore use JQ to read the composer.json in thepackage’s directory:

jq -r '.name' $1/composer.json

Adding this all together and we have a 1 argument command to instantly symlink a package for development.

*Bonus composer-unlink:

We can quickly unlink our change and fetch the latest change from the upstream repo by utilizing git. We already have our composer.json and lock files in version control so we can tell git to revert back to the base composer.json. Assuming we’ve updates and pushed our package to the composer repo composer update will now fetch the latest from the upstream repo.

Pandelis Zembashis