skip to Main Content

I have multiple projects that I work on.

Some are on php 7.3, most of 7.4 and a single one on 8.1

Having to switch php everytime when I switch projects is a solution I have now, but sometimes I need to do a quick check on another project, and that breaks code running in another project because the global php are updated.

All my projects are composer based, but composer doesn’t "spit out" what the most desired php version is.

How can I based on composer.json/lock detect the correct php version to use?

2

Answers


  1. Chosen as BEST ANSWER

    This script is made with php installed via ppa:ondrej/php. If your php versions are self compiled, and not linked in for example /usr/bin/php7.4 you'll need to modify the paths to the correct paths. This code however does assume the binaries are named php7.x or php8.x

    This also requires that there is a composer installed on your system.

    Add the following code to your .bashrc file.(nano ~/.bashrc) Explanations of what does what are in the comments in the code.

    function do_php() {
        # Path where to find the php binaries
        PHPPATH='/usr/bin'
        
        # PHP versions in order of most used
        declare -a phpversions=("7.4" "7.3" "8.1" "8.0" "7.2" "7.1" "7.0");
        # Get a direct path to composer
        composer_path="$(whereis composer | cut -d  ' ' -f 2)"
        # Loop through all php versions
        for phpversion in "${phpversions[@]}"
          do
            PHP=$PHPPATH/php$phpversion
            # If the given php version is installed
            if [ -f $PHP ]; then
              # Check if it matches the requirements
              SUCCESS=$($PHP $composer_path check-platform-reqs 2>/dev/null | grep php | tr -s ' ' | cut -d ' ' -f 3)
               # If we're matching
               if [ "$SUCCESS" == "success" ]; then
                  # Run command with given binary
                  $PHP "$@"
                  # exit function
                  return
               fi
             fi
        done
        
        #Nothing matched, just run with default php and let the programmer deal with the issue
        php "$@"
    }
    
    # Set the alias for php to do_php
    alias php='do_php'
    

  2. All my projects are composer based, but composer doesn’t "spit out" what the most desired php version is.

    How can I based on composer.json/lock detect the correct php version to use?

    Well composer itself can not magically tell you what your intend (per project) is, however you can configure this easily on a per-project basis with platform packages. For the PHP version it is the php package:

    {
        "config": {
            "platform": {
                "php": "7.0.3"
            }
        }
    }
    

    (Compare: Composer config platform, Run composer using different version of PHP without changing the environment variables)

    You can also add extensions and libraries. Now you have configured the information in your project and composer will use that version when installing and updating dependencies (e.g. for 7.0.3 above, package versions that require >= 7.0.4 won’t install).

    7.0.3 is a bad example (just copied the version from Composer docs), let’s say you’re in a PHP 7.4 project:

    $ composer config platform.php '7.4.30'
    

    It is also now easy to map on the Sury packages binary names, just keep the head:

    $ composer config platform.php | head -c3
    7.4
    

    For Composer invocations itself it won’t be necessary any longer, however you may want to do other things, so here some hints, that already work within Composer:

    • The @php script shortcut (Composer, see Executing PHP scripts)
    • The PHP_BINARY environment variable (Composer, see same)

    Those are all based on the php binary composer is running with. So if you need to inject it, call composer with the adequate php version:

    $ composer config platform.php '8.1.11'
    $ php$(composer config platform.php | head -c3) $(which composer) diagnose
    Checking composer.json: OK
    ...
    PHP version: 8.1.11 - Package overridden via config.platform, same as actual
    PHP binary path: /usr/bin/php8.1
    ...
    

    (Example: Composer invocation with Ondřej Surý php8.1 package on Ubuntu)

    So eventual composer scripts/hooks should be covered.

    For invocation in general I’d suggest to use a build manager to define targets, their dependencies and the rules how they are made. You should have the make utility already on your box and then it is just make and done for most of the time. You can add the php executable name to configuration there, control the platform version in composer.json and have this even re-useable across projects. no need to add it to the environment when you can have it in the project IMHO (Compare Automation and Make).

    When it comes the day you start to migrate your project to another php version, you have only one environment. With a build manager you can easily run the same setup with different php versions to check the upgrade path (and even can do this in parallel). Just for the outlook. Keep it simple and stupid, then you have the best options in the long run (and also portability across projects).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search