40

So I have Gentoo box with three PHP versions installed (nevermind the reasons):

  1. /usr/bin/php -> /usr/lib64/php5.4/bin/php
  2. /usr/bin/php5.5 -> /usr/lib64/php5.5/bin/php
  3. /usr/bin/php5.6 -> /usr/lib64/php5.4/bin/php

I want to install Laravel framework using composer:

$ composer create-project laravel/laravel --prefer-dist

This however throws an error because Laravel requires PHP > 5.5.9 and the default php interpreter is 5.4. So I issue another command:

$ /usr/bin/php5.6 /usr/bin/composer create-project laravel/laravel --prefer-dist

This takes me one step further, but then some post-install commands from Laravel's composer.json comes into play, and installation crashes.

This is due to the fact, that composer.json commands look like this:

"post-install-cmd": [
    "php artisan clear-compiled",
    "php artisan optimize"
],

As you can see, the "default" interpreter is used again!

Now, proper PHP files start with following shebang:

#!/usr/bin/env php

This is nice feature as PHP interpreter can be found under different locations on different systems. Unfortunatelly, in this case env command returns path to the first executable it finds in $PATH environmental variable.

How could I possibly alter current session environment or what kind of trick to perform so for the execution of whole Laravel installation process php command would invoke /usr/bin/php5.6 instead of /usr/bin/php?

I don't want to change $PATH variable or modify files like composer, composer.json or Laravel's CLI utility artisan.


Edit: also assume that I want to do this from regular user account (i.e. with no root permissions).

roomcays
  • 927
  • 1
  • 7
  • 22
  • How about creating a temporary symlink and restoring it later? Also look at `GNU stow` – Arkadiusz Drabczyk Jul 03 '15 at 12:45
  • You'll have to craft a custom wrapper script, which honors an exported `PHP_BIN` environment variable for example, or defaults to `/usr/bin/php` else. (See also [In Bash, when to alias, when to script, and when to write a function?](http://unix.stackexchange.com/q/30925)) -- Also, once you have more than three versions installed, you're officially a hoarder. – mario Jul 03 '15 at 12:50
  • About `alias`: sadly this does not work. Perhaps because `alias` does not work when `php` is invoked by `composer` _or_ by `/usr/bin/env`. – roomcays Jul 03 '15 at 13:50
  • Perfect answer. Thanks. – prog_24 Jan 04 '17 at 01:58

10 Answers10

46

Maybe you can try to fix the environnement!

$ php -v
PHP 5.4.x (cli) ...
$ set PATH="/usr/lib64/php5.6/bin:$PATH"
$ php -v
PHP 5.6.x (cli) ...

Or, if you don't want to modify the PATH for your shell session, you can scope the change for the current command only:

$ php -v
PHP 5.4.x (cli) ...
$ env PATH="/usr/lib64/php5.6/bin:$PATH" php -v
PHP 5.6.x (cli) ...
$ php -v
PHP 5.4.x (cli) ...
Guillaume Crico
  • 592
  • 4
  • 3
  • 2
    That is it! I have entered: `PATH="/usr/lib64/php5.6/bin:$PATH" php /usr/bin/composer create-project laravel/laravel --prefer-dist` and installation completed successfully! Setting `PATH` in one line with command does not change global PATH variable. Thanks a lot Guillaume Crico! – roomcays Aug 12 '15 at 10:15
  • Using Mac nothing changes with either method, where do you unset the path to the default php? – OZZIE Sep 12 '17 at 14:30
  • This is not working for me: `env PATH="/opt/php71/bin/php:$PATH" php -v` keeps telling php 5.x – mayid Sep 14 '17 at 15:25
  • Also tried this variant: `PATH="/opt/php71/bin/php:$PATH" sh -c 'php -v'` and it's the same. At least I can see the PATH is being modified if I run `PATH="/opt/php71/bin/php:$PATH" sh -c 'echo $PATH | grep php'` but even having php 7 in the PATH the following `php -v` command still executes php 5. – mayid Sep 14 '17 at 15:27
  • The first one, using 'set PATH' does not work for me on Debian. It does not change to 5.6.x. It is permanently 5.4.x. – Simon Oct 22 '17 at 09:30
  • same for me,too – Onur Demir Nov 22 '17 at 14:28
46

Default PHP executable can be found using:

$ which php

In most cases it is link to particular PHP version:

lrwxrwxrwx 1 root root      21 aug 15  2016 /usr/bin/php -> /usr/bin/php7.1

To change it to different version just relink it to another

$ sudo rm /usr/bin/php

$ sudo ln -s /usr/bin/php5.6 /usr/bin/php

Before relink you have to make sure target PHP version is installed.

Saleniex
  • 615
  • 5
  • 4
14

Identify where the current generic php command is and to which binary it points to with which php.

It will give you a path to a symlink like you mention in your question

/usr/bin/php -> /usr/lib64/php5.4/bin/php

Edit the symlink to point to which ever php version you want for now, see here https://unix.stackexchange.com/questions/88824/how-can-i-edit-symlinks

When you are done just reverse the process.

UPDATE: you can also add an alias for the current user by editing ~/.bashrc and adding the following

alias php='/usr/bin/php5.6'

see if this works out

Community
  • 1
  • 1
Alex Andrei
  • 7,315
  • 3
  • 28
  • 42
  • This answer and a comment from Arkadiusz Drabczyk would be valid, but I forgot to mention, that I can't modify system symlinks (`/usr/bin/*`) as whole operation is to be done from common user account (no root). – roomcays Jul 03 '15 at 13:38
  • updated answer, although i see @mario already hinted towards `alias` – Alex Andrei Jul 03 '15 at 13:45
  • Thanks, I have answered about `alias` in the comment to my question. – roomcays Jul 03 '15 at 13:50
  • I came from Google so I think it worth to say this has been the best solution for me. I tried the @Guillaume 's solution which is really usefull, but at least in my case, after the `composer update` the system was trying to do a `php artisan optimize` (using the wrong `php` version again). So I created an `alias` just for the current user and it worked like a charm. Please note you have to log out and log in, otherwise the alias does not take effect. Thanks Alex! – Kamae Feb 07 '18 at 17:37
10

Since PHP7 came around Debian Linux creates different executables for PHP versions 5 and 7 in /usr/bin by default (if you install both versions that is).

Calling those different versions from the command line is as simple as ever now:

kkarski@debian:~ $ php5 -v
PHP 5.6.26-0+deb8u1 (cli) (built: Sep 21 2016 12:37:50) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies


kkarski@debian:~ $ php -v
PHP 7.0.9-1~dotdeb+8.1 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.9-1~dotdeb+8.1, Copyright (c) 1999-2016, by Zend Technologies

This is obviously only good for simple scripts. For anything larger (composer, artisan etc.) you'll have to change the PATH variable.

To change the version your Apache server is using all you have to do is:

root@debian:~# a2dismod php5 && a2enmod php7.0
Module php5 disabled.
To activate the new configuration, you need to run:
  service apache2 restart
Considering conflict php5 for php7.0:
Enabling module php7.0.
To activate the new configuration, you need to run:
  service apache2 restart

and vice versa if you want to use the lower PHP version.

Mentioning it in case someone has similar problems on Debian.

Krzysztof Karski
  • 749
  • 1
  • 12
  • 19
  • I was struggling with changing the version entirely... But your solution saved my day... +1 from me.. Thanks a tonne... – Saiyan Prince Mar 30 '17 at 05:45
3

I find the easiest to achieve the same like just create a softlink like for example

ln -s /opt/php-7.0.32/bin/php /usr/bin/php7

ln -s /opt/php-7.1/bin/php /usr/bin/php71

ln -s /opt/php-5.6/bin/php /usr/bin/php56

then as you use your default version say it is php7.2 as just php for alternative version you can you php7 or php71 or php56

here ln -s /opt/php-7.1/bin/php /usr/bin/php71 is the source/orginal file and /usr/bin/php7 is the destination / link

Joshi
  • 2,730
  • 5
  • 36
  • 62
1

For anyone else who found no solution in the above, because they use composer update and somehow the wrong PHP version gets used. By using composer self-update I got some more info and eventually found out that in the composer.json you can specify a platform in the config section, which overrides what php version is used by composer. Simply changing this value or removing this config solved my issue.

composer.json "config": { "platform": { "php": "7.1" },

Rein Baarsma
  • 1,466
  • 13
  • 22
1

It's possible to do using alias, but keep in mind that aliases are not expanded by default.

You must also enable expanding of those.

$ shopt -s expand_aliases
$ alias php="/usr/local/bin/php-5.6"
$ ./some-script.sh
$ unalias php # back to previous version
roomcays
  • 927
  • 1
  • 7
  • 22
0

I worked on a "script + docker image" to make multiple php versions available whenever I want during development: https://github.com/jclaveau/docker-php-multiversion

You can use it this way:

$ php 5.6 -v
PHP 5.6.40-15+ubuntu18.04.1+deb.sury.org+1 (cli) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
    with Xdebug v2.5.5, Copyright (c) 2002-2017, by Derick Rethans

$ php 7.3 -v
PHP 7.3.13-1+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Dec 18 2019 14:48:49) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.13, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.13-1+ubuntu18.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies
    with Xdebug v2.9.0, Copyright (c) 2002-2019, by Derick Rethans

As it uses Docker.io, you do not need to alter any part of your system configuration.

Hoping it would help you

Jean Claveau
  • 1,101
  • 1
  • 13
  • 15
  • 1
    If its using Docker then you DO need to alter system configuration. First you need to install Docker, then you need to ensure security is correctly setup since Docker is known to have tons of security vulnerabilities. And last but not least, script will run in docker instead of on the machine itself which might cause some things to not work correctly depending on what you are trying to execute (eg. it will see a random string instead of hostname, you won't be able to connect to any services on the host machine, etc.). – HubertNNN Jul 06 '22 at 09:31
  • I did this project as an experiment and I now dropped it for a while for multiple reasons including the use of tools like Renovate or Dependabot. Btw, you not wrong at all but some of your points could be expected like not being able to connect to hosts services – Jean Claveau Jul 06 '22 at 13:00
0

I had this requirement for composer which required PHP to be a specific version on a multi-tenant system which would end up affecting other web applications. I could not update the symbolic link to PHP for the whole system, I needed to switch the PHP version for this specific execution only, so I ended up with the following.

php80 `which composer` install

Note: As long as you have different versions of PHP installed it would just work.

`which composer` - expands to the path of the composer binary, so you do not have to type the full path.
0

On Ubuntu, you don't have to make any changes to the filesystem, you can just execute:

$ php{version} {script}

and substitute the version for what you have installed. For example:

php7.4 script.php
php8.2 script.php

To see which PHP versions are installed, just do ls /usr/bin/php*.

Mike
  • 23,542
  • 14
  • 76
  • 87