Run Composer Scripts in Parallel with veewee/composer-run-parallel

Nice addition to Composer by Toon Verwerft which allows you to run your custom commands in parallel

This composer plugin allows you to run the tasks inside your composer file in parallel. No more waiting on one specific task!

Say you have these two custom commands:

  "scripts": {
    "php1": "@php -r 'sleep(3); echo \"1\";'",
    "php2": "@php -r 'echo \"2\";'"

Then you can invoke them to run in parallel as follows:

$ composer run parallel php1 php2

Using @parallel it’s also possible to trigger the functionality from inside another custom command:

  "scripts": {
    "php1And2": "@parallel php1 php2"

Installation per Composer:

$ composer require --dev veewee/composer-run-parallel

You might want to install this one globally 😉


Composer Inline Aliases: Fake a PHP Package Version by Aliasing a Specific Commit to it

Great tip by Mattias:

You can alias directly when requiring a package:

composer require monolog/monolog:"dev-bugfix as 1.0.x-dev"

Surely comes in handy when locally adjusting a library. More info on Inline Aliases in the Composer Documentation.

“Composer require local package”: Working with symlinked Composer packages in PHP

When developing a PHP library/package, you most likely also have a project on disk that consumes said library. Take a WordPress plugin for example: to test it, you need a WordPress installation — both are linked but separate projects. To speed up development you can tell Composer to use the local version of the package, instead of having to copy files from folder to folder as you develop.


I’m assuming a folder structure like this:

bramus in ~/repos
$ tree -L 1
├── my-library
└── my-project

If my-project were to use the published version of my-library, you would run the following command:

bramus in ~/repos/my-project
$ composer require author/my-library

The ~/repos/my-project/composer.json would then look as follows:

    // …
    "require": {
        "author/my-library": "*"


During development of my-library you don’t want to be editing the copy of my-library which resides inside the my-project/vendor/… folder. What you want is to edit the local version of ~/repos/my-library directly, and make my-project use that version.

To do this, Composer allows you to configure the package sources using the repositories option of its configuration. To refer to the local copy adjust ~/repos/my-project/composer.json so that it has an entry pointing to ~/repos/my-library/:

    // …
    "require": {
        "author/my-library": "*"
    "repositories": [
            "type": "path",
            "url": "../my-library"

With this addition, re-run the composer require command, and it’ll symlink ~/repos/my-library/ into ~/repos/my-project/vendor/author/my-library/:

bramus in ~/repos/my-project
$ composer require author/my-library

- Installing author/my-library (dev)
Symlinked from ../my-library

🐛 Not seeing this output? Try removing your vendor/ folder first, and then re-require your package. You might also need to add :dev-branchname to your requirement, e.g. composer require author/my-library:dev-master

When you now edit code inside ~/repos/my-library/, the ~/repos/my-project will also be up-to-date 🙂

💁‍♂️ You can also use repositories to refer to privately published repositories. No need to fiddle with Satis or the like

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Overriding the PHP version to use when installing Composer dependencies

If you have a (legacy) PHP project running on a legacy server (running PHP 5.4.27 for example), but are locally developing with a more modern PHP version (PHP 7.4 for example), you might end up installing dependencies that are not compatible with the PHP version on the server.

To bypass this, you can tell Composer, via its config property, which PHP version that you’re using (on production).

    // …
    "config": {
        "platform": {
            "php": "5.4.27"

When you now run composer require package, it will only install dependencies that are compatible with that PHP version (instead of the PHP version that’s executing Composer)

💁‍♂️ You might also want to run that legacy application locally in a Docker container with said PHP version. The Docker West PHP Docker Images will come in handy, although versions prior to PHP 5.6 are supported.

🔐 Even better, of course, is to phase out the production server running that outdated/unsupported/insecure PHP version …

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Selling Composer Packages through “Private Packagist for Vendors”

Nice new addition by Packagist:

If you’re selling PHP packages, the easiest way to offer Composer package installation to your customers is now “Private Packagist for Vendors”. You get a unique URL and authentication token for each customer and they can use these in their composer.json file to install your packages. Especially if you’re still sending zip files to your customers, there is really no reason anymore not to to offer Composer installations.

You can use their our API to integrate “Private Packagist for Vendors” with your existing PHP package shop: Create a customer, grant the customer access to the package, and then get the info needed to send to the customer — all using their API.

// 1. Create Customer
$customer = $client
    ->create('Acme Web Inc.');

// 2. Grant access to package for customer
        'name' => 'my-vendor/cool-package',
        'versionConstraint' => '^1.0',
        'expirationDate' => strtotime('+1 year'),

// 3. Get info to send to user
$info = $client->customers()->show($customer['id']);

// …
//    'composerRepository' => [
//        'url' => '',
//        'user' => 'token',
//        'token' => 'a6addb89a67b2822d352d113',
// …

As you can see in the code above, customers their access can be locked to specific versions and also limited in time.

Packagist Blog: Introducing Private Packagist for Vendors →
Private Packagist for Vendors →

Bash/Shell Autocompletion for Composer

The other day I opened up a PHP project that I hadn’t worked on in a while. No longer remembering which Composer Scripts I had defined for it, I needed to take a peek inside composer.json to see which ones were available to me. Then it hit me: why is there no autocompletion for composer available?

Googling around a bit I eventually turned to creating my own Bash completion script for Composer. After installing it, it will autocomplete composer commands for you:

$ composer in[TAB][TAB]
info     init     install

💡 Want to build your own bash completion script? This very good tutorial has got you covered.

The code builds further upon this earlier work by Rob Allen. Key area where it differs from Rob’s work is that composer-autocomplete also provides autocompletion for composer run-script, listing which Composer Scripts are available to you (as I initially wanted).

    "name": "bramus/example-php-package",
    "description": "Example PHP Package",
    "type": "library",
    "license": "MIT",
    "scripts": {
        "test": "./vendor/bin/phpunit --colors=always",
        "lint": "php-cs-fixer fix --diff --dry-run --ansi",
        "fix": "php-cs-fixer fix"
$ composer run-script [TAB][TAB]
fix   lint  test

Bash/Shell Autocompletion for Composer →

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Private Packagist

Mid-December Nils Adermann – Co-Founder of Packagist Conductors & Creator of Composer for PHP – announced Private Packagist.

Being a hosted service, setting up your own Composer package repository on Private Packagist is done with a few clicks. No matter if your private source code is hosted on GitHub, GitLab, Bitbucket, any of their on-premise solutions, or in any other Git, Mercurial, or Subversion repository, Private Packagist can immediately access your code after setting up your credentials to make it available for installation through Composer.

A few years ago I tried setting up Satis, but that didn’t quite work out. Private Packagist would’ve been handy back then 🙂

Private Packagist →
Introducing Private Packagist →

PHP Roave Security Advisories

$ composer require roave/security-advisories:dev-master
$ # following commands will fail:
$ composer require symfony/symfony:2.5.2
$ composer require zendframework/zendframework:2.3.1

This package ensures that your PHP application doesn’t have installed dependencies with known security vulnerabilities.

This package does not provide any API or usable classes: its only purpose is to prevent installation of software with known and documented security issues. Simply add "roave/security-advisories": "dev-master" to your composer.json "require" section and you will not be able to harm yourself with software with known security vulnerabilities.

Differs from Sensiolabs’ Security Advisories Checker as Roave Security Advisories prevents you from installing known vulnerable packages. This is done in a rather simple – yet ingenious – way: the packages with known vulnerabilities are blacklisted using Composer’s conflict property.

Roave Security Advisories →


Heroku <3 PHP

Good news from Heroku: PHP is (finally) properly supported. Just add a composer.json file to your repo and Heroku will know your app runs PHP. Yes, you see that right: Composer is supported. Whenever you push your code to Heroku, it will install the dependencies if needed.

$ git add .
$ git commit -m "Add basic logging"
[master 4b42543] Add basic logging
 1 file changed, 14 insertions(+), 1 deletion(-)
$ git push heroku master
Fetching repository, done.
Counting objects: 15, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (12/12), 2.39 KiB | 0 bytes/s, done.
Total 12 (delta 3), reused 0 (delta 0)

-----> Fetching custom git buildpack... done
-----> PHP app detected
-----> Setting up runtime environment...
       - PHP 5.5.11
       - Apache 2.4.9
       - Nginx 1.4.6
-----> Installing dependencies...
       Composer version 1e4df0690a08c4653b5c932d51a337b10d6c19bf 2014-04-10 19:10:45
       Loading composer repositories with package information
       Installing dependencies from lock file
         - Installing psr/log (1.0.0)
           Downloading: 100%

         - Installing monolog/monolog (1.8.0)
           Downloading: 100%

       Generating optimized autoload files
-----> Building runtime environment...
       Loading composer repositories with package information
       Updating dependencies
         - Installing heroku/heroku-buildpack-php (dev-beta 20204c9)
           Loading from cache

       Writing lock file
       Generating optimized autoload files
-----> Discovering process types
       Procfile declares types -> web

-----> Compressing... done, 60.8MB
-----> Launching... done, v6 deployed to Heroku

To [email protected]:polar-chamber-3014.git
   bd24c74..4b42543  master -> master

Heroku PHP Support →
Getting Started with PHP on Heroku →

Related: TokenPhrase, a PHP class which generates unique phrases – comparable to Heroku’s generated hostnames – for you to use in your app as tokens