BeastCoding
By Tobias Kriebisch
on

When developing with PHP in a Nix environment, you may encounter inconsistencies between the PHP versions used by the CLI and Composer. This issue typically arises due to the way Nix manages dependencies and packages, which can result in Composer and the CLI referring to slightly different PHP paths, even when they’re intended to use the same version. In my case I need the composer PHP to have the redis extension so it can be used by a post-update script.

Problem: Inconsistent PHP Paths in Nix

The initial setup for PHP in our shell.nix file specified PHP 8.3 with several extensions.

let
  pkgs = import <nixpkgs> { };
  php = pkgs.php83.withExtensions (
    { enabled, all }:
    with all;
    [
      ctype
      dom
      fileinfo
      filter
      mbstring
      openssl
      pdo
      session
      tokenizer
      zlib
      curl
      imagick
      redis
      opcache
      pdo_pgsql
      gd
      xdebug
      pcntl
      zip
    ]
  );
  packages = pkgs.php83Packages;
in
pkgs.mkShell {
  nativeBuildInputs = [
    php
    packages.composer
    packages.phpinsights
    packages.phpmd
  ];
}

However, upon inspecting the environment, it was apparent that Composer and the CLI were using different PHP binaries, even though both pointed to PHP 8.3. This led to potential confusion, especially in managing the redis extension.

For instance:

$ which php
/nix/store/dl7q2888a2m0b32mzy9qs5hmjh992jiy-php-with-extensions-8.3.12/bin/php
$ composer -V
PHP version 8.3.12 (/nix/store/n7zg8vq3gf10s0jjkw5vv7f55iyck2mc-php-with-extensions-8.3.12/bin/php)

Here, which php and the Composer PHP path led to different binaries and the Composer PHP binary does not have the redis extension for some reason.

Solution: Unified PHP Configuration in `shell.nix`

To solve this, we needed a way to specify PHP in shell.nix so that both the CLI and Composer use the same binary.

Updated shell.nix:

Basicly we reuse the configured PHP from the Composer package as the main PHP package

let
  pkgs = import <nixpkgs> { };
  php = (pkgs.php83.withExtensions (
      { all, enabled }:
      enabled
      ++ (with all; [
        redis
      ])
    ));
in
pkgs.mkShell {
  nativeBuildInputs = [
    php.packages.composer
    php
  ];
}

This approach to defining PHP and Composer in shell.nix ensures consistent, predictable behavior in your PHP development setup. Happy coding!