How to Set Environment Variables in Composer Scripts

How to Set Environment Variables in Composer Scripts

Do you need to set environment variables for Composer scripts to work? Here’s how.

But first, a little story. Recently, I was working through a PR to upgrade oauth2-keycloak to use PHPUnit 9; no, not to version 10 for a couple of reasons. After making the required changes to the package, I went to run the test suite and noticed that there wasn’t a scripts property in the project’s composer.json file.

This seemed a little odd to me, as the scripts property has been common on numerous projects that I’ve worked with in the past. Why? Because they help automate so many aspects of common functionality, such as running tests, under a unified command interface.

Laravel, for example, has an excellent post-install script, and Mezzio projects generated with the Skeleton Installer come with the following scripts configuration:

    "scripts": {
        "post-create-project-cmd": [
        "development-disable": "laminas-development-mode disable",
        "development-enable": "laminas-development-mode enable",
        "development-status": "laminas-development-mode status",
        "mezzio": "mezzio --ansi",
        "check": [
        "clear-config-cache": "php bin/clear-config-cache.php",
        "cs-check": "phpcs",
        "cs-fix": "phpcbf",
        "serve": "php -S -t public/",
        "test": "phpunit --colors=always",
        "test-coverage": "phpunit --colors=always --coverage-clover clover.xml"

You can see that there are scripts for managing Mezzio’s development mode, running tests, and starting the application, among others.

Sadly, this project didn’t have one. So, as part of upgrading the package to PHPUnit 9, I wanted to make running its test suite a little easier and added the following section to composer.json:

    "scripts": {
        "test": "phpunit --colors=always"

By doing this, running tests would only require running the following command:

composer test

Sure, running the underlying command (./vendor/bin/phpunit --colors=always) isn’t much longer. However, scripts remove the need to remember a plethora of various options, arguments, and values, such as those supported by PHPUnit.

With the change made, I thought my work was done. Sadly, on running the command, I encountered the following warning.

Warning: XDEBUG_MODE=coverage or xdebug.mode=coverage has to be set

This was because I’d enabled code coverage reporting in phpunit.xml.dist yet hadn’t set XDEBUG_MODE appropriately.

At this moment, I found myself a little stuck, as I couldn’t assume anything about a user’s environment, when they were working with the package. I needed to ensure that the environment variable, XDEBUG_MODE, was set to coverage before the script was run.

However, I couldn’t see an obvious, Composer-specific, way to do so. Sure, I could set the environment variable when running the command, as in the example below.

XDEBUG_MODE=coverage composer test

However, that leaves room for mistakes to happen. For example, the same error will occur if the environment variable’s not set before or on running the command. Plus, it would only work for me, not any future users of the package.

Then, I tried to set the environment variable with the following configuration in phpunit.xml.dist.

    <ini name="xdebug.mode" value="coverage"/>

Unfortunately, that didn’t solve the problem.

I did a little digging into the Composer manual and found that it environment variables can be set in scripts. To do this, the script’s value needs to be an array of steps, where the environment variable is set with @putenv, before the command is called, as you can see in the example below.

    "scripts": {
        "install-phpstan": [
            "@putenv COMPOSER=phpstan-composer.json",
            "composer install --prefer-dist"

With that change made, the test suite ran successfully — with no broken tests as a result of the changes I’d made to upgrade to PHPUnit 9! What’s more, the script also provided an extra bit of project documentation.

That’s how to set environment variables in Composer scripts

If you find yourself in the same situation as I did, now you can set environment variables as part of your Composer scripts, and your scripts will work as expected.

The Composer logo is copyright the Composer project.

You might also be interested in these tutorials too...

Set Environment Variables in PHP with PHP dotenv
Fri, May 12, 2023

Set Environment Variables in PHP with PHP dotenv

There are a number of ways to set environment variables in PHP. But the approach I use most often in development is a wonderful package called PHP dotenv. In this tutorial, I’m going to step you through how to install and use it.

Build Your Own Software Packages
Thu, Apr 27, 2023

Build Your Own Software Packages

I recently refactored parts of a web application for an upcoming Twilio tutorial into three open source packages. Here’s what motivated the decision to do so, and why I think you should create them too.

The Composer Command-Line Essentials
Tue, Nov 29, 2016

The Composer Command-Line Essentials

How well do you really know Composer? Do you just know composer install, update, and require, and some of the composer.json configuration? Or do you really know it? In this series, you’re going to take your skills to the next level; starting with the command-line.

Install PHP's Imagick Extension on macOS
Tue, Jul 4, 2023

Install PHP's Imagick Extension on macOS

Homebrew makes installing PHP and so many other great tools on macOS a breeze; almost as easily as a Linux package manager. But how do you install the Imagick extension? In this short post, I’ll show you the shortest way to do so.

Want more tutorials like this?

If so, enter your email address in the field below and click subscribe.

You can unsubscribe at any time by clicking the link in the footer of the emails you'll receive. Here's my privacy policy, if you'd like to know more. I use Mailchimp to send emails. You can learn more about their privacy practices here.

Join the discussion

comments powered by Disqus