Most hosting control panels have the option to set a different PHP version per site. This great functionality is not that easy to replicate in a development local environment. I will explain here the method I have been using for recent years. It is based on preparing some tiny scripts which load and unload Apache modules and set cli defaults. This way, the change between PHP versions in a 3 seconds execution time one-liner command. This method only applies to Debian-based systems and changes PHP version for the whole system, not on a per-site basis as hosting control panels do. On the other hand, PHP is loaded as a module so its administration is the simplest available. No PHP-CGI or PHP-FPM. We keep these technologies for our production and integration environments where they are better needed.
The installation of the various PHP versions is done via the superb Sury repository. Install instructions can be found in the repository readme. Once the repository is added it’s just a matter of choosing the PHP versions you want. Nice thing of this repository is that its maintained by the same team than Debian PHP packages so they fit into your system very nicely, specifically in terms of:
sudo aptitude install php7.0 php7.0-cli php7.4 php7.4-cli php8.0 php8.0-cli php-xdebug
Each php version gets its configuration from
/etc/php/[version_num]/[apache2,cli] so you can drop your modifications to default configuration creating a new file at
/etc/php/7.4/apache2/conf.d/zz-local-custom.conf for Apache and
/etc/php/7.4/cli/conf.d/zz-local-custom.conf for cli.
Something like this might be useful on a dev environment:
memory_limit = 512M upload_max_filesize = 24M post_max_size = 24M max_execution_time = 60 xdebug.remote_enable=On xdebug.file_link_format = pstorm://%f:%l display_errors=1
Personally I prefer setting the first 4 items on a per site basis at the corresponding Apache virtual host but hey, you are free to set it here and forget.
You need to disable unwanted module and enable the new one, which can be done with
sudo a2dismod php7.4; sudo a2enmod php8.0;
It’s nice to understand how your system organizes its binaries for your day-to-day most used tool. It’s something like this:
$ ls -la /usr/bin/php* lrwxrwxrwx 1 root root 21 24 abr. 2019 /usr/bin/php -> /etc/alternatives/php -rwxr-xr-x 1 root root 4495400 26 ag. 18:06 /usr/bin/php7.0 -rwxr-xr-x 1 root root 4793272 26 ag. 18:09 /usr/bin/php7.3 -rwxr-xr-x 1 root root 4928688 26 ag. 18:06 /usr/bin/php8.0 lrwxrwxrwx 1 root root 28 16 febr. 2021 /usr/bin/php-config -> /etc/alternatives/php-config -rwxr-xr-x 1 root root 4243 26 ag. 18:09 /usr/bin/php-config7.3 lrwxrwxrwx 1 root root 6 21 juny 22:02 /usr/bin/php.default -> php8.0 lrwxrwxrwx 1 root root 24 16 febr. 2021 /usr/bin/phpize -> /etc/alternatives/phpize -rwxr-xr-x 1 root root 4984 26 ag. 18:09 /usr/bin/phpize7.3
/usr/bin in your PATH, you can call your scripts easily with php7.0, php7.3, php8.0 commands but usually you will spend some hours with a version so why not toggle your system defaults with update-alternatives so things like
symfony work out of the box for you?
That’s easily done with the command
sudo update-alternatives --config php
and choosing the right version for each moment.
And can’t we do the same
update-alternatives trick with Drupal command line super-tool?
Obviously the answer is yes, but it will take just an extra step for it. Debian brings the
drush command as a repository package but nobody has done the job Sury has been doing for the last years with PHP of packaging multiple versions and making them available to work together.
For this to work on first place we will need to install those multiple drush commands, for example at
$ mkdir my-drushes; mkdir my-drushes/drush8; mkdir my-drushes/drush9; mkdir my-drushes/drush10; $ cd my-drushes/drush8; composer require drush/drush ^8; vendor/bin/drush --version $ cd my-drushes/drush9; composer require drush/drush ^9; vendor/bin/drush --version $ cd my-drushes/drush10; composer require drush/drush ^10; vendor/bin/drush –version
Now we need to declare to our system those alternatives for the
sudo update-alternatives --install /usr/bin/drush8 drush /home/myuser/my-drushes/vendor/bin/drush 8 sudo update-alternatives --install /usr/bin/drush9 drush /home/myuser/my-drushes/vendor/bin/drush 9 sudo update-alternatives --install /usr/bin/drush10 drush /home/myuser/my-drushes/vendor/bin/drush 10
Last number is just the weight for
update-alternatives. You can set it as 10, 20, 30 or whatever you want. From this moment we can toggle between our drush versions with
sudo update-alternatives –config drush
and we will be asked for which version we want to use.
It’s not very comfortable writing down all those commands or at least it’s not what I promised at the beginning of a 3 seconds execution one liner. Funny part is to put it all together in a script and call it from whatever situation we find ourselves in. You usually need to change PHP versions for cli and Apache together. Usually Drush 8 or 9 will fit in your Drupal 7 websites which are currently fully compatible with PHP 7.4 but maybe you have some legacy code and still require 7.0. On the other side, your most recent projects work just fine with Drush 10 and PHP 8.0 so the scripts could be something like this:
#!/bin/bash sudo a2dismod php7.4 php8.0 sudo a2enmod php7.0 sudo systemctl restart apache2 sudo update-alternatives --set php /usr/bin/php7.0 sudo update-alternatives --set drush /home/myuser/my-drushes/vendor/bin/drush 8
#!/bin/bash sudo a2dismod php7.0 php8.0 sudo a2enmod php7.4 sudo systemctl restart apache2 sudo update-alternatives --set php /usr/bin/php7.4 sudo update-alternatives --set drush /home/myuser/my-drushes/vendor/bin/drush 9
#!/bin/bash sudo a2dismod php7.0 php7.4 sudo a2enmod php8.0 sudo systemctl restart apache2 sudo update-alternatives --set php /usr/bin/php8.0 sudo update-alternatives --set drush /home/myuser/my-drushes/vendor/bin/drush 10
Yes, those scripts are a bit verbose but you will set up them once and don’t change until a new version of PHP or major version of Drush is released so no more than once a year, and changing it is just a matter of issuing following command from whatever place you are in your machine, easily recoverable from your history via Ctrl+R shortcut:
~/php7.0.sh ~/php7.4.sh ~/php8.0.sh