Programster's Blog

Tutorials focusing on Linux, programming, and open-source

Composer - Specify Configuration Environment

The Problem

I develop and maintain many different projects of different ages simultaneously, which use different PHP versions and extensions. This means that keeping my development environment in-sync with the environment that the codebase is built to run against in production can be a bit of a pain. Luckily, I use Docker to programmatically specify and build our environments for deployment. I also mount my files using a volume inside the containers for development. However, this presents a problem for me with respect to installing PHP packages through composer. This is because composer will analyse the environment one is using, and will reject the installation of packages if the environment doesn't meet the requirements of the packages.

This results in a message like below when one's PHP version is not high enough:

Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires php ^7.4 but your php version (7.2.24) does not satisfy that requirement.

... or the following message when one doesn't have a required PHP extension:

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - aws/aws-sdk-php[3.137.0, ..., 3.158.22] require ext-simplexml * -> it is missing from your system. Install or enable PHP's simplexml extension.
    - Root composer.json requires aws/aws-sdk-php ^3.137 -> satisfiable by aws/aws-sdk-php[3.137.0, ..., 3.158.22].

To enable extensions, verify that they are enabled in your .ini files:
    - /etc/php/7.2/cli/php.ini
    - /etc/php/7.2/cli/conf.d/10-opcache.ini

Steps

Luckily, you can resolve these problems by specifying in a config section of your composer.json file, a specific php version, and/or extensions that composer should consider you to have:

{
    "config": {
        "platform" : {
            "php" : "7.4.0",
            "ext-simplexml" : "1",
            "ext-mbstring" : "1",
            "ext-mysqli" : "1",
            "ext-dom" : "1",
            "ext-xml" : "1",
            "ext-xmlwriter" : "1"
        },
    }
}

Now you can install packages without issue. Just remember that the code won't work in your local environment, but would if you injected the files into the environment you just described.

Why Not Just Run Composer Inside The Container?

You may be wondering why we don't just run composer inside the container to begin with. I believe this is actually a better solution as it ensures you can't make a mistake with installing packages your environment can't actually support, but the solution described above is a quick and easy solution if you are using private PHP packages, and want to use your local SSH keys/agent. Those problems can be dealt with, if you are willing to put in more effort. For example the composer dockerhub page has an example whereby one provides their SSH agent socket to the container to run docker compose:

eval $(ssh-agent); \
  docker run --rm --interactive --tty \
  --volume $PWD:/app \
  --volume $SSH_AUTH_SOCK:/ssh-auth.sock \
  --env SSH_AUTH_SOCK=/ssh-auth.sock \
  composer install

References

Last updated: 20th November 2020
First published: 8th November 2020