After adding support for PHP 8.0, Arch news reported they are keeping legacy PHP7 packages available back in January. I was quite out of PHP scene for now, but recently, I had to test something.

The test obviously required the php core package, now the version 8.0 and a second hard requirement is a composer, a PHP's package manager.

sudo pacman -S php composer

Trying to run composer install in the software's root folder shown the following error:

Your lock file does not contain a compatible set of packages. Please run composer update.

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

The error means that, what I was testing was written for PHP7, but I had an incompatible PHP8 already.

PHP7 legacy package

I thought, no problem. Just install the legacy php7 core package mentioned in the news post and everything will be alright.

sudo pacman -S php7

I did not read the news post thoroughly so I was expecting that the pacman will offer me to remove the php package when installing the php7 package, assuming they would be in conflict. This did not happen. The php7 package installed gracefully, living happily alongside the base php package. Still not reading the post, I started poking around:

pkgfile --list --binaries php7

Yeah, it is obvious now why there was no conflicting files, specifically the /usr/bin/php binary:

extra/php7	/usr/bin/phar7
extra/php7	/usr/bin/phar7.phar
extra/php7	/usr/bin/php-config7
extra/php7	/usr/bin/php7
extra/php7	/usr/bin/phpize7

The packages are built in such a way, they do not collide with each other. The post even states that specifically:

PHP 7 binaries and configuration have the "7" suffix:

  • /usr/bin/php -> /usr/bin/php7
  • /etc/php -> /etc/php7
  • ...

What to do now?

Solving file conflicts

The first obvious way to introduce the symlink, as I was not sure if I could force all the software I was just trying and knew nothing about use php7 binary instead of just php it surely expected.

sudo ln -s /usr/bin/php7 /usr/bin/php

Not so fast, or in a terminal's own words:

ln: failed to create symbolic link '/usr/bin/php': File exists

So there were some solutions that I came up with that second:

  1. Keeping all packages, remove just the /usr/bin/php and do the symlink
  2. Remove the php package and then do a symlink
  3. Do some PATH environment variable magic

I did not consider the third option too vital for a short test that might even involve different system users. Making this work by changing PATH could also lead to some hard to explain errors and I had to make it run first, experiment later, so I considered symlinks.

Even though I do not like symlinking around the system files, I still did not find an absolutely best practice that would work out of the box in every possible scenario, so the second option seemed like a lesser of the two evils.

sudo pacman -Rnc php

No, this takes composer down with it as well.

Problematic composer dependency

Trying to install composer back brings the php as a dependency, so these two are unlikely to part ways. There are options, however:

  • Removing the dependency from the composer's PKGBUILD
  • Install composer without dependencies

Let's explore both.

Removing the dependency from the PKGBUILD

The php dependency is mentioned with keyword depends= in the PKGBUILD. We have to remove it from there, rebuild the package and install everything. The full command could look like this:

sudo pacman -S php7
sudo ln -s /usr/bin/php7 /usr/bin/php
yay -G composer # download the PKGBUILD file only
cd composer
sed "10s/'php'//" -i PKGBUILD
makepkg -sri
composer --version

Not entirely sure what happens during the upgrade, though. Looks very messy, but works.

Installing composer without dependencies

Pacman itself offers another option, but it's use is very discouraged, so use only when accepting the risk, that your system might break due to this:

sudo pacman -Sdd package_name

Using the -dd parameter while installing a package does not install it's dependencies. The full set of commands would then look like this:

sudo pacman -S php7
sudo ln -s /usr/bin/php7 /usr/bin/php
sudo pacman -Sdd composer
composer --version

Even I still have to fully understand the risks involved of solving this dependency problem like this, so use with caution.

Conclusion

After installing a php7 package and then composer without the php dependency, which automatically pulled version 8.0, symlinking the binary, the composer install in the software relying on PHP7 now works without complains. Have to understand the long-term consequences of this actions, but so far, so good. Definitely would love to see how different people solve this.