summary refs log tree commit diff
diff options
context:
space:
mode:
authorElis Hirwing <elis@hirwing.se>2020-04-02 22:13:04 +0200
committertalyz <kim.lindberger@gmail.com>2020-04-05 16:45:17 +0200
commita2099156eca905ee0b7a232cb7ec07539eebd72c (patch)
tree271a1dea88a60f49f88cac39a7307f6bf87540f9
parenta4bc30c802d99bcc5c2f4c7bb84d40da14137c4c (diff)
downloadnixpkgs-a2099156eca905ee0b7a232cb7ec07539eebd72c.tar
nixpkgs-a2099156eca905ee0b7a232cb7ec07539eebd72c.tar.gz
nixpkgs-a2099156eca905ee0b7a232cb7ec07539eebd72c.tar.bz2
nixpkgs-a2099156eca905ee0b7a232cb7ec07539eebd72c.tar.lz
nixpkgs-a2099156eca905ee0b7a232cb7ec07539eebd72c.tar.xz
nixpkgs-a2099156eca905ee0b7a232cb7ec07539eebd72c.tar.zst
nixpkgs-a2099156eca905ee0b7a232cb7ec07539eebd72c.zip
php: split php.packages to php.packages and php.extensions
So now we have only packages for human interaction in php.packages and
only extensions in php.extensions. With this php.packages.exts have
been merged into the same attribute set as all the other extensions to
make it flat and nice.

The nextcloud module have been updated to reflect this change as well
as the documentation.
-rw-r--r--doc/languages-frameworks/php.section.md41
-rw-r--r--nixos/doc/manual/release-notes/rl-2009.xml6
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix6
-rw-r--r--pkgs/development/interpreters/php/default.nix19
-rw-r--r--pkgs/top-level/all-packages.nix5
-rw-r--r--pkgs/top-level/php-packages.nix1039
6 files changed, 563 insertions, 553 deletions
diff --git a/doc/languages-frameworks/php.section.md b/doc/languages-frameworks/php.section.md
index 9924946a45c..18d4ee83709 100644
--- a/doc/languages-frameworks/php.section.md
+++ b/doc/languages-frameworks/php.section.md
@@ -21,20 +21,12 @@ of a given NixOS release will be included in that release of
 NixOS. See [PHP Supported
 Versions](https://www.php.net/supported-versions.php).
 
-As for packages we have `php.packages` that contains a bunch of
-attributes where some are suitable as extensions (notable example:
-`php.packages.imagick`). And some are more suitable for command
-line use (notable example: `php.packages.composer`).
+For packages we have `php.packages` that contains packages related
+for human interaction, notable example is `php.packages.composer`.
 
-We have a special section within `php.packages` called
-`php.packages.exts` that contain certain PHP modules that may not
-be part of the default PHP derivation (example:
-`php.packages.exts.opcache`).
-
-The `php.packages.exts.*` attributes are official extensions which
-originate from the mainline PHP project, while other extensions within
-the `php.packages.*` attribute are of mixed origin (such as `pecl`
-and other places).
+For extensions we have `php.extensions` that contains most upstream
+extensions as separate attributes as well some additional extensions
+that tend to be popular, notable example is: `php.extensions.imagick`.
 
 The different versions of PHP that nixpkgs fetch is located under
 attributes named based on major and minor version number; e.g.,
@@ -43,23 +35,20 @@ attributes named based on major and minor version number; e.g.,
 
 #### Installing PHP with packages
 
-There's two different kinds of things you could install:
- - A command line utility. Simply refer to it via
-   `php*.packages.*`, and it automatically comes with the necessary
-   PHP environment, certain extensions and libraries around it.
- - A PHP interpreter with certain extensions available.  The `php`
-   attribute provides `php.buildEnv` that allows you to wrap the PHP
-   derivation with an additional config file that makes PHP import
-   additional libraries or dependencies.
+There's two majorly different parts of the PHP ecosystem in NixOS:
+ - Command line utilities for human interaction. These comes from the
+   `php.packages.*` attributes.
+ - PHP environments with different extensions enabled. These are
+   composed with `php.buildEnv` using an additional configuration file.
 
 ##### Example setup for `phpfpm`
 
-Example to build a PHP with `imagick` and `opcache` enabled, and
-configure it for the "foo" `phpfpm` pool:
+Example to build a PHP with the extensions `imagick` and `opcache`
+enabled. Then to configure it for the "foo" `phpfpm` pool:
 
 ```nix
 let
-  myPhp = php.buildEnv { exts = pp: with pp; [ imagick exts.opcache ]; };
+  myPhp = php.buildEnv { exts = pp: with pp; [ imagick opcache ]; };
 in {
   services.phpfpm.pools."foo".phpPackage = myPhp;
 };
@@ -68,8 +57,8 @@ in {
 ##### Example usage with `nix-shell`
 
 This brings up a temporary environment that contains a PHP interpreter
-with `imagick` and `opcache` enabled.
+with the extensions `imagick` and `opcache` enabled.
 
 ```sh
-nix-shell -p 'php.buildEnv { exts = pp: with pp; [ imagick exts.opcache ]; }'
+nix-shell -p 'php.buildEnv { exts = pp: with pp; [ imagick opcache ]; }'
 ```
diff --git a/nixos/doc/manual/release-notes/rl-2009.xml b/nixos/doc/manual/release-notes/rl-2009.xml
index db4b8df4a22..1618fc89477 100644
--- a/nixos/doc/manual/release-notes/rl-2009.xml
+++ b/nixos/doc/manual/release-notes/rl-2009.xml
@@ -134,8 +134,8 @@
 
        <programlisting>
 environment.systemPackages = [
-(pkgs.php.buildEnv { exts = pp: with pp.exts; [
-    pp.imagick
+(pkgs.php.buildEnv { exts = pp: with pp; [
+    imagick
     opcache
     pdo_mysql
   ]; })
@@ -144,7 +144,7 @@ environment.systemPackages = [
        The default <literal>php</literal> attribute hasn't lost any extensions -
        the <literal>opcache</literal> extension was added there.
 
-       All upstream PHP extensions are available under <package><![CDATA[php.packages.exts.<name?>]]></package>.
+       All upstream PHP extensions are available under <package><![CDATA[php.extensions.<name?>]]></package>.
      </para>
      <para>
        The updated <literal>php</literal> attribute is now easily customizable to your liking
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index c6c1cdadf02..33d35670029 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -7,12 +7,12 @@ let
   fpm = config.services.phpfpm.pools.nextcloud;
 
   phpPackage = pkgs.php74.buildEnv {
-    exts = pp: with pp.exts; [
+    exts = pp: with pp; [
       bcmath calendar curl exif ftp filter gd gettext gmp intl json ldap
       mysqlnd opcache openssl pcntl pdo pdo_mysql pdo_odbc pdo_pgsql
       pdo_sqlite pgsql readline session soap sodium sqlite3 zip zlib mbstring
-      posix ctype dom simplexml xmlreader xmlwriter pp.apcu
-      pp.redis pp.memcached pp.imagick
+      posix ctype dom simplexml xmlreader xmlwriter
+      apcu redis memcached imagick
     ];
     extraConfig = phpOptionsStr;
   };
diff --git a/pkgs/development/interpreters/php/default.nix b/pkgs/development/interpreters/php/default.nix
index 7daf32e5127..514c2070886 100644
--- a/pkgs/development/interpreters/php/default.nix
+++ b/pkgs/development/interpreters/php/default.nix
@@ -149,14 +149,21 @@ let
   generic' = { version, sha256, self, selfWithExtensions, ... }@args:
     let
       php = generic (builtins.removeAttrs args [ "self" "selfWithExtensions" ]);
-      packages = callPackage ../../../top-level/php-packages.nix {
+
+      packages = (callPackage ../../../top-level/php-packages.nix {
         php = self;
         phpWithExtensions = selfWithExtensions;
-      };
+      }).packages;
+
+      extensions = (callPackage ../../../top-level/php-packages.nix {
+        php = self;
+        phpWithExtensions = selfWithExtensions;
+      }).extensions;
+
       buildEnv = { exts ? (_: []), extraConfig ? "" }:
         let
           getExtName = ext: lib.removePrefix "php-" (builtins.parseDrvName ext.name).name;
-          extList = exts packages;
+          extList = exts extensions;
 
           # Generate extension load configuration snippets from
           # exts. This is an attrset suitable for use with
@@ -190,7 +197,7 @@ let
             inherit version;
             nativeBuildInputs = [ makeWrapper ];
             passthru = {
-              inherit buildEnv packages;
+              inherit buildEnv packages extensions;
             };
             paths = [ php ];
             postBuild = ''
@@ -206,7 +213,7 @@ let
     in
       php.overrideAttrs (_: {
         passthru = {
-          inherit buildEnv packages;
+          inherit buildEnv packages extensions;
         };
       });
 
@@ -238,7 +245,7 @@ let
   };
 
   defaultPhpExtensions = {
-    exts = pp: with pp.exts; ([
+    exts = pp: with pp; ([
       bcmath calendar curl ctype dom exif fileinfo filter ftp gd
       gettext gmp iconv intl json ldap mbstring mysqli mysqlnd opcache
       openssl pcntl pdo pdo_mysql pdo_odbc pdo_pgsql pdo_sqlite pgsql
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 1bb373ad633..2aa5696d86c 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -9377,6 +9377,11 @@ in
   php73Packages = recurseIntoAttrs php73.packages;
   php74Packages = recurseIntoAttrs php74.packages;
 
+  phpExtensions = php74Extensions;
+  php72Extensions = recurseIntoAttrs php72.extensions;
+  php73Extensions = recurseIntoAttrs php73.extensions;
+  php74Extensions = recurseIntoAttrs php74.extensions;
+
   inherit (callPackages ../development/interpreters/php {
     stdenv = if stdenv.cc.isClang then llvmPackages_6.stdenv else stdenv;
   }) php74 php73 php72 php74base php73base php72base;
diff --git a/pkgs/top-level/php-packages.nix b/pkgs/top-level/php-packages.nix
index b3a3fe699c4..bb4a5a946c1 100644
--- a/pkgs/top-level/php-packages.nix
+++ b/pkgs/top-level/php-packages.nix
@@ -20,654 +20,665 @@ let
 
   isPhp73 = pkgs.lib.versionAtLeast php.version "7.3";
   isPhp74 = pkgs.lib.versionAtLeast php.version "7.4";
+
+  pcre' = if (lib.versionAtLeast php.version "7.3") then pcre2 else pcre;
 in
 {
   inherit buildPecl;
 
-  apcu = buildPecl {
-    version = "5.1.18";
-    pname = "apcu";
+  # Packages are an attribute set meant for for human interaction and not
+  # extensions for the language itself.
+  packages = {
+    box = mkDerivation rec {
+      version = "2.7.5";
+      pname = "box";
 
-    sha256 = "0ayykd4hfvdzk7qnr5k6yq5scwf6rb2i05xscfv76q5dmkkynvfl";
+      src = pkgs.fetchurl {
+        url = "https://github.com/box-project/box2/releases/download/${version}/box-${version}.phar";
+        sha256 = "1zmxdadrv0i2l8cz7xb38gnfmfyljpsaz2nnkjzqzksdmncbgd18";
+      };
 
-    buildInputs = if isPhp73 then [ pkgs.pcre2 ] else [ pkgs.pcre ];
-    doCheck = true;
-    checkTarget = "test";
-    checkFlagsArray = ["REPORT_EXIT_STATUS=1" "NO_INTERACTION=1"];
-    makeFlags = [ "phpincludedir=$(dev)/include" ];
-    outputs = [ "out" "dev" ];
-  };
+      phases = [ "installPhase" ];
+      buildInputs = [ pkgs.makeWrapper ];
 
-  apcu_bc = buildPecl {
-    version = "1.0.5";
-    pname = "apcu_bc";
+      installPhase = ''
+        mkdir -p $out/bin
+        install -D $src $out/libexec/box/box.phar
+        makeWrapper ${phpWithExtensions}/bin/php $out/bin/box \
+          --add-flags "-d phar.readonly=0 $out/libexec/box/box.phar"
+      '';
 
-    sha256 = "0ma00syhk2ps9k9p02jz7rii6x3i2p986il23703zz5npd6y9n20";
+      meta = with pkgs.lib; {
+        description = "An application for building and managing Phars";
+        license = licenses.mit;
+        homepage = https://box-project.github.io/box2/;
+        maintainers = with maintainers; [ jtojnar ];
+      };
+    };
 
-    buildInputs = [
-      php.packages.apcu
-      (if isPhp73 then pkgs.pcre2 else pkgs.pcre)
-    ];
-  };
+    composer = mkDerivation rec {
+      version = "1.9.3";
+      pname = "composer";
 
-  ast = buildPecl {
-    version = "1.0.5";
-    pname = "ast";
+      src = pkgs.fetchurl {
+        url = "https://getcomposer.org/download/${version}/composer.phar";
+        sha256 = "VRZVwvyB9BBlCPQrvEsk6r00sCKxO8Hn2WQr9IPQp9Q=";
+      };
 
-    sha256 = "16c5isldm4csjbcvz1qk2mmrhgvh24sxsp6w6f5a37xpa3vciawp";
-  };
+      dontUnpack = true;
+
+      nativeBuildInputs = [ pkgs.makeWrapper ];
 
-  box = mkDerivation rec {
-    version = "2.7.5";
-    pname = "box";
+      installPhase = ''
+        mkdir -p $out/bin
+        install -D $src $out/libexec/composer/composer.phar
+        makeWrapper ${phpWithExtensions}/bin/php $out/bin/composer \
+          --add-flags "$out/libexec/composer/composer.phar" \
+          --prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.unzip ]}
+      '';
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/box-project/box2/releases/download/${version}/box-${version}.phar";
-      sha256 = "1zmxdadrv0i2l8cz7xb38gnfmfyljpsaz2nnkjzqzksdmncbgd18";
+      meta = with pkgs.lib; {
+        description = "Dependency Manager for PHP";
+        license = licenses.mit;
+        homepage = https://getcomposer.org/;
+        maintainers = with maintainers; [ globin offline ];
+      };
     };
 
-    phases = [ "installPhase" ];
-    buildInputs = [ pkgs.makeWrapper ];
+    php-cs-fixer = mkDerivation rec {
+      version = "2.16.1";
+      pname = "php-cs-fixer";
 
-    installPhase = ''
-      mkdir -p $out/bin
-      install -D $src $out/libexec/box/box.phar
-      makeWrapper ${phpWithExtensions}/bin/php $out/bin/box \
-        --add-flags "-d phar.readonly=0 $out/libexec/box/box.phar"
-    '';
+      src = pkgs.fetchurl {
+        url = "https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v${version}/php-cs-fixer.phar";
+        sha256 = "1dq1nhy666zg6d4fkfsjwhj1vwh1ncap2c9ljplxv98a9mm6fk68";
+      };
 
-    meta = with pkgs.lib; {
-      description = "An application for building and managing Phars";
-      license = licenses.mit;
-      homepage = https://box-project.github.io/box2/;
-      maintainers = with maintainers; [ jtojnar ];
-    };
-  };
+      phases = [ "installPhase" ];
+      buildInputs = [ pkgs.makeWrapper ];
 
-  composer = mkDerivation rec {
-    version = "1.9.3";
-    pname = "composer";
+      installPhase = ''
+        mkdir -p $out/bin
+        install -D $src $out/libexec/php-cs-fixer/php-cs-fixer.phar
+        makeWrapper ${php}/bin/php $out/bin/php-cs-fixer \
+          --add-flags "$out/libexec/php-cs-fixer/php-cs-fixer.phar"
+      '';
 
-    src = pkgs.fetchurl {
-      url = "https://getcomposer.org/download/${version}/composer.phar";
-      sha256 = "VRZVwvyB9BBlCPQrvEsk6r00sCKxO8Hn2WQr9IPQp9Q=";
+      meta = with pkgs.lib; {
+        description = "A tool to automatically fix PHP coding standards issues";
+        license = licenses.mit;
+        homepage = http://cs.sensiolabs.org/;
+        maintainers = with maintainers; [ jtojnar ];
+      };
     };
 
-    dontUnpack = true;
-
-    nativeBuildInputs = [ pkgs.makeWrapper ];
+    php-parallel-lint = mkDerivation rec {
+      version = "1.0.0";
+      pname = "php-parallel-lint";
+
+      src = pkgs.fetchFromGitHub {
+        owner = "JakubOnderka";
+        repo = "PHP-Parallel-Lint";
+        rev = "v${version}";
+        sha256 = "16nv8yyk2z3l213dg067l6di4pigg5rd8yswr5xgd18jwbys2vnw";
+      };
+
+      buildInputs = [
+        pkgs.makeWrapper
+        php.packages.composer
+        php.packages.box
+      ];
+
+      buildPhase = ''
+        composer dump-autoload
+        box build
+      '';
 
-    installPhase = ''
-      mkdir -p $out/bin
-      install -D $src $out/libexec/composer/composer.phar
-      makeWrapper ${phpWithExtensions}/bin/php $out/bin/composer \
-        --add-flags "$out/libexec/composer/composer.phar" \
-        --prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.unzip ]}
-    '';
+      installPhase = ''
+        mkdir -p $out/bin
+        install -D parallel-lint.phar $out/libexec/php-parallel-lint/php-parallel-lint.phar
+        makeWrapper ${php}/bin/php $out/bin/php-parallel-lint \
+          --add-flags "$out/libexec/php-parallel-lint/php-parallel-lint.phar"
+      '';
 
-    meta = with pkgs.lib; {
-      description = "Dependency Manager for PHP";
-      license = licenses.mit;
-      homepage = https://getcomposer.org/;
-      maintainers = with maintainers; [ globin offline ];
+      meta = with pkgs.lib; {
+        description = "This tool check syntax of PHP files faster than serial check with fancier output";
+        license = licenses.bsd2;
+        homepage = https://github.com/JakubOnderka/PHP-Parallel-Lint;
+        maintainers = with maintainers; [ jtojnar ];
+      };
     };
-  };
 
-  couchbase = buildPecl rec {
-    version = "2.6.1";
-    pname = "couchbase";
+    phpcbf = mkDerivation rec {
+      version = "3.5.3";
+      pname = "phpcbf";
 
-    buildInputs = [
-      pkgs.libcouchbase
-      pkgs.zlib
-      php.packages.igbinary
-      php.packages.pcs
-    ];
+      src = pkgs.fetchurl {
+        url = "https://github.com/squizlabs/PHP_CodeSniffer/releases/download/${version}/phpcbf.phar";
+        sha256 = "1mrsf9p6p64pyqyylnlxb2b7cirdfccch83g7yhfnka3znffq86v";
+      };
 
-    src = pkgs.fetchFromGitHub {
-      owner = "couchbase";
-      repo = "php-couchbase";
-      rev = "v${version}";
-      sha256 = "0jdzgcvab1vpxai23brmmvizjjq2d2dik9aklz6bzspfb512qjd6";
-    };
-
-    configureFlags = [ "--with-couchbase" ];
-    internalDeps = [ php.packages.exts.json ];
-    patches = [
-      (pkgs.writeText "php-couchbase.patch" ''
-        --- a/config.m4
-        +++ b/config.m4
-        @@ -9,7 +9,7 @@ if test "$PHP_COUCHBASE" != "no"; then
-             LIBCOUCHBASE_DIR=$PHP_COUCHBASE
-           else
-             AC_MSG_CHECKING(for libcouchbase in default path)
-        -    for i in /usr/local /usr; do
-        +    for i in ${pkgs.libcouchbase}; do
-               if test -r $i/include/libcouchbase/couchbase.h; then
-                 LIBCOUCHBASE_DIR=$i
-                 AC_MSG_RESULT(found in $i)
-        @@ -154,6 +154,8 @@ COUCHBASE_FILES=" \
-             igbinary_inc_path="$phpincludedir"
-           elif test -f "$phpincludedir/ext/igbinary/igbinary.h"; then
-             igbinary_inc_path="$phpincludedir"
-        +  elif test -f "${php.packages.igbinary.dev}/include/ext/igbinary/igbinary.h"; then
-        +    igbinary_inc_path="${php.packages.igbinary.dev}/include"
-           fi
-           if test "$igbinary_inc_path" = ""; then
-             AC_MSG_WARN([Cannot find igbinary.h])
-      '')
-    ];
-
-    meta.broken = isPhp74; # Build error
-  };
+      phases = [ "installPhase" ];
+      nativeBuildInputs = [ pkgs.makeWrapper ];
 
-  event = buildPecl {
-    version = "2.5.3";
-    pname = "event";
+      installPhase = ''
+        mkdir -p $out/bin
+        install -D $src $out/libexec/phpcbf/phpcbf.phar
+        makeWrapper ${php}/bin/php $out/bin/phpcbf \
+          --add-flags "$out/libexec/phpcbf/phpcbf.phar"
+      '';
 
-    sha256 = "12liry5ldvgwp1v1a6zgfq8w6iyyxmsdj4c71bp157nnf58cb8hb";
+      meta = with pkgs.lib; {
+        description = "PHP coding standard beautifier and fixer";
+        license = licenses.bsd3;
+        homepage = https://squizlabs.github.io/PHP_CodeSniffer/;
+        maintainers = with maintainers; [ cmcdragonkai etu ];
+      };
+    };
 
-    configureFlags = [
-      "--with-event-libevent-dir=${pkgs.libevent.dev}"
-      "--with-event-core"
-      "--with-event-extra"
-      "--with-event-pthreads"
-    ];
+    phpcs = mkDerivation rec {
+      version = "3.5.3";
+      pname = "phpcs";
 
-    postPhpize = ''
-      substituteInPlace configure --replace 'as_fn_error $? "Couldn'\'''t find $phpincludedir/sockets/php_sockets.h. Please check if sockets extension installed" "$LINENO" 5' \
-                                            ':'
-    '';
+      src = pkgs.fetchurl {
+        url = "https://github.com/squizlabs/PHP_CodeSniffer/releases/download/${version}/phpcs.phar";
+        sha256 = "0y4nhsifj4pdmf5g1nnm4951yjgiqswyz7wmjxx6kqiqc7chlkml";
+      };
 
-    nativeBuildInputs = [ pkgs.pkgconfig ];
-    buildInputs = with pkgs; [ openssl libevent ];
-    internalDeps = [ php.packages.exts.sockets ];
+      phases = [ "installPhase" ];
+      buildInputs = [ pkgs.makeWrapper ];
 
-    meta = with pkgs.lib; {
-      description = ''
-        This is an extension to efficiently schedule I/O, time and signal based
-        events using the best I/O notification mechanism available for specific platform.
+      installPhase = ''
+        mkdir -p $out/bin
+        install -D $src $out/libexec/phpcs/phpcs.phar
+        makeWrapper ${php}/bin/php $out/bin/phpcs \
+          --add-flags "$out/libexec/phpcs/phpcs.phar"
       '';
-      license = licenses.php301;
-      homepage = "https://bitbucket.org/osmanov/pecl-event/";
-    };
-  };
-
-  igbinary = buildPecl {
-    version = "3.0.1";
-    pname = "igbinary";
 
-    sha256 = "1w8jmf1qpggdvq0ndfi86n7i7cqgh1s8q6hys2lijvi37rzn0nar";
+      meta = with pkgs.lib; {
+        description = "PHP coding standard tool";
+        license = licenses.bsd3;
+        homepage = https://squizlabs.github.io/PHP_CodeSniffer/;
+        maintainers = with maintainers; [ javaguirre etu ];
+      };
+    };
 
-    configureFlags = [ "--enable-igbinary" ];
-    makeFlags = [ "phpincludedir=$(dev)/include" ];
-    outputs = [ "out" "dev" ];
-  };
+    phpstan = mkDerivation rec {
+      version = "0.12.14";
+      pname = "phpstan";
 
-  imagick = buildPecl {
-    version = "3.4.4";
-    pname = "imagick";
+      src = pkgs.fetchurl {
+        url = "https://github.com/phpstan/phpstan/releases/download/${version}/phpstan.phar";
+        sha256 = "JAq1/+bVhTgKRR7oFusqZ/yBOYewaOM38ZoiCjirsTg=";
+      };
 
-    sha256 = "0xvhaqny1v796ywx83w7jyjyd0nrxkxf34w9zi8qc8aw8qbammcd";
+      phases = [ "installPhase" ];
+      nativeBuildInputs = [ pkgs.makeWrapper ];
 
-    configureFlags = [ "--with-imagick=${pkgs.imagemagick.dev}" ];
-    nativeBuildInputs = [ pkgs.pkgconfig ];
-    buildInputs = [ (if isPhp73 then pkgs.pcre2 else pkgs.pcre) ];
-  };
+      installPhase = ''
+        mkdir -p $out/bin
+        install -D $src $out/libexec/phpstan/phpstan.phar
+        makeWrapper ${php}/bin/php $out/bin/phpstan \
+          --add-flags "$out/libexec/phpstan/phpstan.phar"
+      '';
 
-  mailparse = buildPecl {
-    version = "3.0.3";
-    pname = "mailparse";
-    sha256 = "00nk14jbdbln93mx3ag691avc11ff94hkadrcv5pn51c6ihsxbmz";
+      meta = with pkgs.lib; {
+        description = "PHP Static Analysis Tool";
+        longDescription = ''
+        PHPStan focuses on finding errors in your code without actually running
+        it. It catches whole classes of bugs even before you write tests for the
+        code. It moves PHP closer to compiled languages in the sense that the
+        correctness of each line of the code can be checked before you run the
+        actual line.
+      '';
+        license = licenses.mit;
+        homepage = "https://github.com/phpstan/phpstan";
+        maintainers = with maintainers; [ etu ];
+      };
+    };
 
-    internalDeps = [ php.packages.exts.mbstring ];
-    postConfigure = ''
-      echo "#define HAVE_MBSTRING 1" >> config.h
-    '';
-  };
+    psalm = mkDerivation rec {
+      version = "3.9.3";
+      pname = "psalm";
 
-  maxminddb = buildPecl rec {
-    pname = "maxminddb";
-    version = "1.6.0";
+      src = pkgs.fetchurl {
+        url = "https://github.com/vimeo/psalm/releases/download/${version}/psalm.phar";
+        sha256 = "KHm2n06y/yxN5B2rCVxT5ja7HxkyxAMsjZ5HLb3xr4M=";
+      };
 
-    src = pkgs.fetchFromGitHub {
-      owner = "maxmind";
-      repo = "MaxMind-DB-Reader-php";
-      rev = "v${version}";
-      sha256 = "0sa943ij9pgz55aik93lllb8lh063bvr66ibn77p3y3p41vdiabz";
-    };
+      phases = [ "installPhase" ];
+      nativeBuildInputs = [ pkgs.makeWrapper ];
 
-    buildInputs = [ pkgs.libmaxminddb ];
-    sourceRoot = "source/ext";
+      installPhase = ''
+        mkdir -p $out/bin
+        install -D $src $out/libexec/psalm/psalm.phar
+        makeWrapper ${php}/bin/php $out/bin/psalm \
+          --add-flags "$out/libexec/psalm/psalm.phar"
+      '';
 
-    meta = with pkgs.lib; {
-      description = "C extension that is a drop-in replacement for MaxMind\\Db\\Reader";
-      license = with licenses; [ asl20 ];
-      maintainers = with maintainers; [ ajs124 das_j ];
+      meta = with pkgs.lib; {
+        description = "A static analysis tool for finding errors in PHP applications";
+        license = licenses.mit;
+        homepage = https://github.com/vimeo/psalm;
+      };
     };
-  };
 
-  memcached = buildPecl rec {
-    version = "3.1.5";
-    pname = "memcached";
+    psysh = mkDerivation rec {
+      version = "0.9.12";
+      pname = "psysh";
 
-    src = fetchgit {
-      url = "https://github.com/php-memcached-dev/php-memcached";
-      rev = "v${version}";
-      sha256 = "01mbh2m3kfbdvih3c8g3g9h4vdd80r0i9g2z8b3lx3mi8mmcj380";
-    };
+      src = pkgs.fetchurl {
+        url = "https://github.com/bobthecow/psysh/releases/download/v${version}/psysh-v${version}.tar.gz";
+        sha256 = "0bzmc94li481xk81gv460ipq9zl03skbnq8m3rnw34i2c04hxczc";
+      };
 
-    internalDeps = [
-      php.packages.exts.session
-    ] ++ lib.optionals (lib.versionOlder php.version "7.4") [
-      php.packages.exts.hash ];
+      phases = [ "installPhase" ];
+      nativeBuildInputs = [ pkgs.makeWrapper ];
 
-    configureFlags = [
-      "--with-zlib-dir=${pkgs.zlib.dev}"
-      "--with-libmemcached-dir=${pkgs.libmemcached}"
-    ];
+      installPhase = ''
+        mkdir -p $out/bin
+        tar -xzf $src -C $out/bin
+        chmod +x $out/bin/psysh
+        wrapProgram $out/bin/psysh
+      '';
 
-    nativeBuildInputs = [ pkgs.pkgconfig ];
-    buildInputs = with pkgs; [ cyrus_sasl zlib ];
+      meta = with pkgs.lib; {
+        description = "PsySH is a runtime developer console, interactive debugger and REPL for PHP.";
+        license = licenses.mit;
+        homepage = https://psysh.org/;
+        maintainers = with maintainers; [ caugner ];
+      };
+    };
   };
 
-  mongodb = buildPecl {
-    pname = "mongodb";
-    version = "1.6.1";
-
-    sha256 = "1j1w4n33347j9kwvxwsrix3gvjbiqcn1s5v59pp64s536cci8q0m";
-
-    nativeBuildInputs = [ pkgs.pkgconfig ];
-    buildInputs = with pkgs; [
-      cyrus_sasl
-      icu
-      openssl
-      snappy
-      zlib
-      (if isPhp73 then pcre2 else pcre)
-    ] ++ lib.optional (pkgs.stdenv.isDarwin) pkgs.darwin.apple_sdk.frameworks.Security;
-  };
 
-  oci8 = buildPecl {
-    version = "2.2.0";
-    pname = "oci8";
 
-    sha256 = "0jhivxj1nkkza4h23z33y7xhffii60d7dr51h1czjk10qywl7pyd";
-    buildInputs = [ pkgs.oracle-instantclient ];
-    configureFlags = [ "--with-oci8=shared,instantclient,${pkgs.oracle-instantclient.lib}/lib" ];
+  # Extensions are an attribute set meant for for PHP extensions that extend the
+  # language rather than human interaction.
+  extensions = {
+    apcu = buildPecl {
+      version = "5.1.18";
+      pname = "apcu";
 
-    postPatch = ''
-      sed -i -e 's|OCISDKMANINC=`.*$|OCISDKMANINC="${pkgs.oracle-instantclient.dev}/include"|' config.m4
-    '';
-  };
-
-  pcov = buildPecl {
-    version = "1.0.6";
-    pname = "pcov";
+      sha256 = "0ayykd4hfvdzk7qnr5k6yq5scwf6rb2i05xscfv76q5dmkkynvfl";
 
-    sha256 = "1psfwscrc025z8mziq69pcx60k4fbkqa5g2ia8lplb94mmarj0v1";
+      buildInputs = [ pcre' ];
+      doCheck = true;
+      checkTarget = "test";
+      checkFlagsArray = ["REPORT_EXIT_STATUS=1" "NO_INTERACTION=1"];
+      makeFlags = [ "phpincludedir=$(dev)/include" ];
+      outputs = [ "out" "dev" ];
+    };
 
-    buildInputs = [ (if isPhp73 then pkgs.pcre2 else pkgs.pcre) ];
-  };
+    apcu_bc = buildPecl {
+      version = "1.0.5";
+      pname = "apcu_bc";
 
-  pcs = buildPecl {
-    version = "1.3.3";
-    pname = "pcs";
+      sha256 = "0ma00syhk2ps9k9p02jz7rii6x3i2p986il23703zz5npd6y9n20";
 
-    sha256 = "0d4p1gpl8gkzdiv860qzxfz250ryf0wmjgyc8qcaaqgkdyh5jy5p";
+      buildInputs = [
+        php.extensions.apcu
+        pcre'
+      ];
+    };
 
-    meta.broken = isPhp74; # Build error
-  };
+    ast = buildPecl {
+      version = "1.0.5";
+      pname = "ast";
 
-  pdo_oci = buildPecl rec {
-    inherit (php) src version;
+      sha256 = "16c5isldm4csjbcvz1qk2mmrhgvh24sxsp6w6f5a37xpa3vciawp";
+    };
 
-    pname = "pdo_oci";
-    sourceRoot = "php-${version}/ext/pdo_oci";
+    couchbase = buildPecl rec {
+      version = "2.6.1";
+      pname = "couchbase";
+
+      buildInputs = [
+        pkgs.libcouchbase
+        pkgs.zlib
+        php.extensions.igbinary
+        php.extensions.pcs
+      ];
+
+      src = pkgs.fetchFromGitHub {
+        owner = "couchbase";
+        repo = "php-couchbase";
+        rev = "v${version}";
+        sha256 = "0jdzgcvab1vpxai23brmmvizjjq2d2dik9aklz6bzspfb512qjd6";
+      };
+
+      configureFlags = [ "--with-couchbase" ];
+      internalDeps = [ php.extensions.json ];
+      patches = [
+        (pkgs.writeText "php-couchbase.patch" ''
+          --- a/config.m4
+          +++ b/config.m4
+          @@ -9,7 +9,7 @@ if test "$PHP_COUCHBASE" != "no"; then
+               LIBCOUCHBASE_DIR=$PHP_COUCHBASE
+             else
+               AC_MSG_CHECKING(for libcouchbase in default path)
+          -    for i in /usr/local /usr; do
+          +    for i in ${pkgs.libcouchbase}; do
+                 if test -r $i/include/libcouchbase/couchbase.h; then
+                   LIBCOUCHBASE_DIR=$i
+                   AC_MSG_RESULT(found in $i)
+          @@ -154,6 +154,8 @@ COUCHBASE_FILES=" \
+               igbinary_inc_path="$phpincludedir"
+             elif test -f "$phpincludedir/ext/igbinary/igbinary.h"; then
+               igbinary_inc_path="$phpincludedir"
+          +  elif test -f "${php.extensions.igbinary.dev}/include/ext/igbinary/igbinary.h"; then
+          +    igbinary_inc_path="${php.extensions.igbinary.dev}/include"
+             fi
+             if test "$igbinary_inc_path" = ""; then
+               AC_MSG_WARN([Cannot find igbinary.h])
+        '')
+      ];
+
+      meta.broken = isPhp74; # Build error
+    };
 
-    buildInputs = [ pkgs.oracle-instantclient ];
-    configureFlags = [ "--with-pdo-oci=instantclient,${pkgs.oracle-instantclient.lib}/lib" ];
+    event = buildPecl {
+      version = "2.5.3";
+      pname = "event";
 
-    internalDeps = [ php.packages.exts.pdo ];
+      sha256 = "12liry5ldvgwp1v1a6zgfq8w6iyyxmsdj4c71bp157nnf58cb8hb";
 
-    postPatch = ''
-      sed -i -e 's|OCISDKMANINC=`.*$|OCISDKMANINC="${pkgs.oracle-instantclient.dev}/include"|' config.m4
-    '';
-  };
+      configureFlags = [
+        "--with-event-libevent-dir=${pkgs.libevent.dev}"
+        "--with-event-core"
+        "--with-event-extra"
+        "--with-event-pthreads"
+      ];
 
-  pdo_sqlsrv = buildPecl {
-    version = "5.8.0";
-    pname = "pdo_sqlsrv";
+      postPhpize = ''
+        substituteInPlace configure --replace 'as_fn_error $? "Couldn'\'''t find $phpincludedir/sockets/php_sockets.h. Please check if sockets extension installed" "$LINENO" 5' \
+                                              ':'
+      '';
 
-    sha256 = "0z4vbyd851b4jr6p69l2ylk91iihndsm2qjb429pxcv8g6dqzqll";
+      nativeBuildInputs = [ pkgs.pkgconfig ];
+      buildInputs = with pkgs; [ openssl libevent ];
+      internalDeps = [ php.extensions.sockets ];
 
-    internalDeps = [ php.packages.exts.pdo ];
+      meta = with pkgs.lib; {
+        description = ''
+          This is an extension to efficiently schedule I/O, time and signal based
+          events using the best I/O notification mechanism available for specific platform.
+        '';
+        license = licenses.php301;
+        homepage = "https://bitbucket.org/osmanov/pecl-event/";
+      };
+    };
 
-    buildInputs = [ pkgs.unixODBC ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.libiconv ];
-  };
+    igbinary = buildPecl {
+      version = "3.0.1";
+      pname = "igbinary";
 
-  php-cs-fixer = mkDerivation rec {
-    version = "2.16.1";
-    pname = "php-cs-fixer";
+      sha256 = "1w8jmf1qpggdvq0ndfi86n7i7cqgh1s8q6hys2lijvi37rzn0nar";
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v${version}/php-cs-fixer.phar";
-      sha256 = "1dq1nhy666zg6d4fkfsjwhj1vwh1ncap2c9ljplxv98a9mm6fk68";
+      configureFlags = [ "--enable-igbinary" ];
+      makeFlags = [ "phpincludedir=$(dev)/include" ];
+      outputs = [ "out" "dev" ];
     };
 
-    phases = [ "installPhase" ];
-    buildInputs = [ pkgs.makeWrapper ];
+    imagick = buildPecl {
+      version = "3.4.4";
+      pname = "imagick";
 
-    installPhase = ''
-      mkdir -p $out/bin
-      install -D $src $out/libexec/php-cs-fixer/php-cs-fixer.phar
-      makeWrapper ${php}/bin/php $out/bin/php-cs-fixer \
-        --add-flags "$out/libexec/php-cs-fixer/php-cs-fixer.phar"
-    '';
+      sha256 = "0xvhaqny1v796ywx83w7jyjyd0nrxkxf34w9zi8qc8aw8qbammcd";
 
-    meta = with pkgs.lib; {
-      description = "A tool to automatically fix PHP coding standards issues";
-      license = licenses.mit;
-      homepage = http://cs.sensiolabs.org/;
-      maintainers = with maintainers; [ jtojnar ];
+      configureFlags = [ "--with-imagick=${pkgs.imagemagick.dev}" ];
+      nativeBuildInputs = [ pkgs.pkgconfig ];
+      buildInputs = [ pcre' ];
     };
-  };
 
-  php-parallel-lint = mkDerivation rec {
-    version = "1.0.0";
-    pname = "php-parallel-lint";
+    mailparse = buildPecl {
+      version = "3.0.3";
+      pname = "mailparse";
+      sha256 = "00nk14jbdbln93mx3ag691avc11ff94hkadrcv5pn51c6ihsxbmz";
 
-    src = pkgs.fetchFromGitHub {
-      owner = "JakubOnderka";
-      repo = "PHP-Parallel-Lint";
-      rev = "v${version}";
-      sha256 = "16nv8yyk2z3l213dg067l6di4pigg5rd8yswr5xgd18jwbys2vnw";
+      internalDeps = [ php.extensions.mbstring ];
+      postConfigure = ''
+        echo "#define HAVE_MBSTRING 1" >> config.h
+      '';
     };
 
-    buildInputs = [
-      pkgs.makeWrapper
-      php.packages.composer
-      php.packages.box
-    ];
-
-    buildPhase = ''
-      composer dump-autoload
-      box build
-    '';
-
-    installPhase = ''
-      mkdir -p $out/bin
-      install -D parallel-lint.phar $out/libexec/php-parallel-lint/php-parallel-lint.phar
-      makeWrapper ${php}/bin/php $out/bin/php-parallel-lint \
-        --add-flags "$out/libexec/php-parallel-lint/php-parallel-lint.phar"
-    '';
-
-    meta = with pkgs.lib; {
-      description = "This tool check syntax of PHP files faster than serial check with fancier output";
-      license = licenses.bsd2;
-      homepage = https://github.com/JakubOnderka/PHP-Parallel-Lint;
-      maintainers = with maintainers; [ jtojnar ];
+    maxminddb = buildPecl rec {
+      pname = "maxminddb";
+      version = "1.6.0";
+
+      src = pkgs.fetchFromGitHub {
+        owner = "maxmind";
+        repo = "MaxMind-DB-Reader-php";
+        rev = "v${version}";
+        sha256 = "0sa943ij9pgz55aik93lllb8lh063bvr66ibn77p3y3p41vdiabz";
+      };
+
+      buildInputs = [ pkgs.libmaxminddb ];
+      sourceRoot = "source/ext";
+
+      meta = with pkgs.lib; {
+        description = "C extension that is a drop-in replacement for MaxMind\\Db\\Reader";
+        license = with licenses; [ asl20 ];
+        maintainers = with maintainers; [ ajs124 das_j ];
+      };
     };
-  };
-
-  php_excel = buildPecl rec {
-    version = "1.0.2";
-    pname = "php_excel";
-    phpVersion = "php7";
-
-    buildInputs = [ pkgs.libxl ];
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/iliaal/php_excel/releases/download/Excel-1.0.2-PHP7/excel-${version}-${phpVersion}.tgz";
-      sha256 = "0dpvih9gpiyh1ml22zi7hi6kslkilzby00z1p8x248idylldzs2n";
+    memcached = buildPecl rec {
+      version = "3.1.5";
+      pname = "memcached";
+
+      src = fetchgit {
+        url = "https://github.com/php-memcached-dev/php-memcached";
+        rev = "v${version}";
+        sha256 = "01mbh2m3kfbdvih3c8g3g9h4vdd80r0i9g2z8b3lx3mi8mmcj380";
+      };
+
+      internalDeps = [
+        php.extensions.session
+      ] ++ lib.optionals (lib.versionOlder php.version "7.4") [
+        php.extensions.hash
+      ];
+
+      configureFlags = [
+        "--with-zlib-dir=${pkgs.zlib.dev}"
+        "--with-libmemcached-dir=${pkgs.libmemcached}"
+      ];
+
+      nativeBuildInputs = [ pkgs.pkgconfig ];
+      buildInputs = with pkgs; [ cyrus_sasl zlib ];
     };
 
-    configureFlags = [ "--with-excel" "--with-libxl-incdir=${pkgs.libxl}/include_c" "--with-libxl-libdir=${pkgs.libxl}/lib" ];
-  };
-
-  phpcbf = mkDerivation rec {
-    version = "3.5.3";
-    pname = "phpcbf";
-
-    src = pkgs.fetchurl {
-      url = "https://github.com/squizlabs/PHP_CodeSniffer/releases/download/${version}/phpcbf.phar";
-      sha256 = "1mrsf9p6p64pyqyylnlxb2b7cirdfccch83g7yhfnka3znffq86v";
+    mongodb = buildPecl {
+      pname = "mongodb";
+      version = "1.6.1";
+
+      sha256 = "1j1w4n33347j9kwvxwsrix3gvjbiqcn1s5v59pp64s536cci8q0m";
+
+      nativeBuildInputs = [ pkgs.pkgconfig ];
+      buildInputs = with pkgs; [
+        cyrus_sasl
+        icu
+        openssl
+        snappy
+        zlib
+        pcre'
+      ] ++ lib.optional (pkgs.stdenv.isDarwin) pkgs.darwin.apple_sdk.frameworks.Security;
     };
 
-    phases = [ "installPhase" ];
-    nativeBuildInputs = [ pkgs.makeWrapper ];
+    oci8 = buildPecl {
+      version = "2.2.0";
+      pname = "oci8";
 
-    installPhase = ''
-      mkdir -p $out/bin
-      install -D $src $out/libexec/phpcbf/phpcbf.phar
-      makeWrapper ${php}/bin/php $out/bin/phpcbf \
-        --add-flags "$out/libexec/phpcbf/phpcbf.phar"
-    '';
+      sha256 = "0jhivxj1nkkza4h23z33y7xhffii60d7dr51h1czjk10qywl7pyd";
+      buildInputs = [ pkgs.oracle-instantclient ];
+      configureFlags = [ "--with-oci8=shared,instantclient,${pkgs.oracle-instantclient.lib}/lib" ];
 
-    meta = with pkgs.lib; {
-      description = "PHP coding standard beautifier and fixer";
-      license = licenses.bsd3;
-      homepage = https://squizlabs.github.io/PHP_CodeSniffer/;
-      maintainers = with maintainers; [ cmcdragonkai etu ];
+      postPatch = ''
+        sed -i -e 's|OCISDKMANINC=`.*$|OCISDKMANINC="${pkgs.oracle-instantclient.dev}/include"|' config.m4
+      '';
     };
-  };
 
-  phpcs = mkDerivation rec {
-    version = "3.5.3";
-    pname = "phpcs";
+    pcov = buildPecl {
+      version = "1.0.6";
+      pname = "pcov";
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/squizlabs/PHP_CodeSniffer/releases/download/${version}/phpcs.phar";
-      sha256 = "0y4nhsifj4pdmf5g1nnm4951yjgiqswyz7wmjxx6kqiqc7chlkml";
+      sha256 = "1psfwscrc025z8mziq69pcx60k4fbkqa5g2ia8lplb94mmarj0v1";
+
+      buildInputs = [ pcre' ];
     };
 
-    phases = [ "installPhase" ];
-    buildInputs = [ pkgs.makeWrapper ];
+    pcs = buildPecl {
+      version = "1.3.3";
+      pname = "pcs";
 
-    installPhase = ''
-      mkdir -p $out/bin
-      install -D $src $out/libexec/phpcs/phpcs.phar
-      makeWrapper ${php}/bin/php $out/bin/phpcs \
-        --add-flags "$out/libexec/phpcs/phpcs.phar"
-    '';
+      sha256 = "0d4p1gpl8gkzdiv860qzxfz250ryf0wmjgyc8qcaaqgkdyh5jy5p";
 
-    meta = with pkgs.lib; {
-      description = "PHP coding standard tool";
-      license = licenses.bsd3;
-      homepage = https://squizlabs.github.io/PHP_CodeSniffer/;
-      maintainers = with maintainers; [ javaguirre etu ];
+      meta.broken = isPhp74; # Build error
     };
-  };
 
-  phpstan = mkDerivation rec {
-    version = "0.12.14";
-    pname = "phpstan";
+    pdo_oci = buildPecl rec {
+      inherit (php) src version;
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/phpstan/phpstan/releases/download/${version}/phpstan.phar";
-      sha256 = "JAq1/+bVhTgKRR7oFusqZ/yBOYewaOM38ZoiCjirsTg=";
-    };
+      pname = "pdo_oci";
+      sourceRoot = "php-${version}/ext/pdo_oci";
 
-    phases = [ "installPhase" ];
-    nativeBuildInputs = [ pkgs.makeWrapper ];
+      buildInputs = [ pkgs.oracle-instantclient ];
+      configureFlags = [ "--with-pdo-oci=instantclient,${pkgs.oracle-instantclient.lib}/lib" ];
 
-    installPhase = ''
-      mkdir -p $out/bin
-      install -D $src $out/libexec/phpstan/phpstan.phar
-      makeWrapper ${php}/bin/php $out/bin/phpstan \
-        --add-flags "$out/libexec/phpstan/phpstan.phar"
-    '';
+      internalDeps = [ php.extensions.pdo ];
 
-    meta = with pkgs.lib; {
-      description = "PHP Static Analysis Tool";
-      longDescription = ''
-        PHPStan focuses on finding errors in your code without actually running
-        it. It catches whole classes of bugs even before you write tests for the
-        code. It moves PHP closer to compiled languages in the sense that the
-        correctness of each line of the code can be checked before you run the
-        actual line.
-      '';
-      license = licenses.mit;
-      homepage = "https://github.com/phpstan/phpstan";
-      maintainers = with maintainers; [ etu ];
+      postPatch = ''
+      sed -i -e 's|OCISDKMANINC=`.*$|OCISDKMANINC="${pkgs.oracle-instantclient.dev}/include"|' config.m4
+    '';
     };
-  };
 
-  protobuf = buildPecl {
-    version = "3.11.2";
-    pname = "protobuf";
+    pdo_sqlsrv = buildPecl {
+      version = "5.8.0";
+      pname = "pdo_sqlsrv";
 
-    sha256 = "0bhdykdyk58ywqj940zb7jyvrlgdr6hdb4s8kn79fz3p0i79l9hz";
+      sha256 = "0z4vbyd851b4jr6p69l2ylk91iihndsm2qjb429pxcv8g6dqzqll";
 
-    buildInputs = with pkgs; [ (if isPhp73 then pcre2 else pcre) ];
+      internalDeps = [ php.extensions.pdo ];
 
-    meta = with pkgs.lib; {
-      description = ''
-        Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data.
-      '';
-      license = licenses.bsd3;
-      homepage = "https://developers.google.com/protocol-buffers/";
+      buildInputs = [ pkgs.unixODBC ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.libiconv ];
     };
-  };
 
-  psalm = mkDerivation rec {
-    version = "3.9.3";
-    pname = "psalm";
+    php_excel = buildPecl rec {
+      version = "1.0.2";
+      pname = "php_excel";
+      phpVersion = "php7";
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/vimeo/psalm/releases/download/${version}/psalm.phar";
-      sha256 = "KHm2n06y/yxN5B2rCVxT5ja7HxkyxAMsjZ5HLb3xr4M=";
-    };
+      buildInputs = [ pkgs.libxl ];
 
-    phases = [ "installPhase" ];
-    nativeBuildInputs = [ pkgs.makeWrapper ];
+      src = pkgs.fetchurl {
+        url = "https://github.com/iliaal/php_excel/releases/download/Excel-1.0.2-PHP7/excel-${version}-${phpVersion}.tgz";
+        sha256 = "0dpvih9gpiyh1ml22zi7hi6kslkilzby00z1p8x248idylldzs2n";
+      };
 
-    installPhase = ''
-      mkdir -p $out/bin
-      install -D $src $out/libexec/psalm/psalm.phar
-      makeWrapper ${php}/bin/php $out/bin/psalm \
-        --add-flags "$out/libexec/psalm/psalm.phar"
-    '';
-
-    meta = with pkgs.lib; {
-      description = "A static analysis tool for finding errors in PHP applications";
-      license = licenses.mit;
-      homepage = https://github.com/vimeo/psalm;
+      configureFlags = [ "--with-excel" "--with-libxl-incdir=${pkgs.libxl}/include_c" "--with-libxl-libdir=${pkgs.libxl}/lib" ];
     };
-  };
-
-  psysh = mkDerivation rec {
-    version = "0.9.12";
-    pname = "psysh";
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/bobthecow/psysh/releases/download/v${version}/psysh-v${version}.tar.gz";
-      sha256 = "0bzmc94li481xk81gv460ipq9zl03skbnq8m3rnw34i2c04hxczc";
-    };
+    protobuf = buildPecl {
+      version = "3.11.2";
+      pname = "protobuf";
 
-    phases = [ "installPhase" ];
-    nativeBuildInputs = [ pkgs.makeWrapper ];
+      sha256 = "0bhdykdyk58ywqj940zb7jyvrlgdr6hdb4s8kn79fz3p0i79l9hz";
 
-    installPhase = ''
-      mkdir -p $out/bin
-      tar -xzf $src -C $out/bin
-      chmod +x $out/bin/psysh
-      wrapProgram $out/bin/psysh
-    '';
+      buildInputs = with pkgs; [ pcre' ];
 
-    meta = with pkgs.lib; {
-      description = "PsySH is a runtime developer console, interactive debugger and REPL for PHP.";
-      license = licenses.mit;
-      homepage = https://psysh.org/;
-      maintainers = with maintainers; [ caugner ];
+      meta = with pkgs.lib; {
+        description = ''
+          Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data.
+        '';
+        license = licenses.bsd3;
+        homepage = "https://developers.google.com/protocol-buffers/";
+      };
     };
-  };
 
-  redis = buildPecl {
-    version = "5.1.1";
-    pname = "redis";
+    redis = buildPecl {
+      version = "5.1.1";
+      pname = "redis";
 
-    sha256 = "1041zv91fkda73w4c3pj6zdvwjgb3q7mxg6mwnq9gisl80mrs732";
+      sha256 = "1041zv91fkda73w4c3pj6zdvwjgb3q7mxg6mwnq9gisl80mrs732";
 
-    internalDeps = with php.packages.exts; [
-      json
-      session
-    ] ++ lib.optionals (lib.versionOlder php.version "7.4") [
-      hash ];
-  };
+      internalDeps = with php.extensions; [
+        json
+        session
+      ] ++ lib.optionals (lib.versionOlder php.version "7.4") [
+        hash ];
+    };
 
-  sqlsrv = buildPecl {
-    version = "5.8.0";
-    pname = "sqlsrv";
+    sqlsrv = buildPecl {
+      version = "5.8.0";
+      pname = "sqlsrv";
 
-    sha256 = "1kv4krk1w4hri99b0sdgwgy9c4y0yh217wx2y3irhkfi46kdrjnw";
+      sha256 = "1kv4krk1w4hri99b0sdgwgy9c4y0yh217wx2y3irhkfi46kdrjnw";
 
-    buildInputs = [ pkgs.unixODBC ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.libiconv ];
-  };
+      buildInputs = [ pkgs.unixODBC ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.libiconv ];
+    };
 
-  v8 = buildPecl {
-    version = "0.2.2";
-    pname = "v8";
+    v8 = buildPecl {
+      version = "0.2.2";
+      pname = "v8";
 
-    sha256 = "103nys7zkpi1hifqp9miyl0m1mn07xqshw3sapyz365nb35g5q71";
+      sha256 = "103nys7zkpi1hifqp9miyl0m1mn07xqshw3sapyz365nb35g5q71";
 
-    buildInputs = [ pkgs.v8_6_x ];
-    configureFlags = [ "--with-v8=${pkgs.v8_6_x}" ];
-    meta.broken = true;
-  };
+      buildInputs = [ pkgs.v8_6_x ];
+      configureFlags = [ "--with-v8=${pkgs.v8_6_x}" ];
+      meta.broken = true;
+    };
 
-  v8js = buildPecl {
-    version = "2.1.0";
-    pname = "v8js";
+    v8js = buildPecl {
+      version = "2.1.0";
+      pname = "v8js";
 
-    sha256 = "0g63dyhhicngbgqg34wl91nm3556vzdgkq19gy52gvmqj47rj6rg";
+      sha256 = "0g63dyhhicngbgqg34wl91nm3556vzdgkq19gy52gvmqj47rj6rg";
 
-    buildInputs = [ pkgs.v8_6_x ];
-    configureFlags = [ "--with-v8js=${pkgs.v8_6_x}" ];
-    meta.broken = true;
-  };
+      buildInputs = [ pkgs.v8_6_x ];
+      configureFlags = [ "--with-v8js=${pkgs.v8_6_x}" ];
+      meta.broken = true;
+    };
 
-  xdebug = buildPecl {
-    version = "2.8.1";
-    pname = "xdebug";
+    xdebug = buildPecl {
+      version = "2.8.1";
+      pname = "xdebug";
 
-    sha256 = "080mwr7m72rf0jsig5074dgq2n86hhs7rdbfg6yvnm959sby72w3";
+      sha256 = "080mwr7m72rf0jsig5074dgq2n86hhs7rdbfg6yvnm959sby72w3";
 
-    doCheck = true;
-    checkTarget = "test";
+      doCheck = true;
+      checkTarget = "test";
 
-    zendExtension = true;
-  };
-
-  yaml = buildPecl {
-    version = "2.0.4";
-    pname = "yaml";
+      zendExtension = true;
+    };
 
-    sha256 = "1036zhc5yskdfymyk8jhwc34kvkvsn5kaf50336153v4dqwb11lp";
+    yaml = buildPecl {
+      version = "2.0.4";
+      pname = "yaml";
 
-    configureFlags = [
-      "--with-yaml=${pkgs.libyaml}"
-    ];
+      sha256 = "1036zhc5yskdfymyk8jhwc34kvkvsn5kaf50336153v4dqwb11lp";
 
-    nativeBuildInputs = [ pkgs.pkgconfig ];
-  };
+      configureFlags = [
+        "--with-yaml=${pkgs.libyaml}"
+      ];
 
-  zmq = buildPecl {
-    version = "1.1.3";
-    pname = "zmq";
+      nativeBuildInputs = [ pkgs.pkgconfig ];
+    };
 
-    sha256 = "1kj487vllqj9720vlhfsmv32hs2dy2agp6176mav6ldx31c3g4n4";
+    zmq = buildPecl {
+      version = "1.1.3";
+      pname = "zmq";
 
-    configureFlags = [
-      "--with-zmq=${pkgs.zeromq}"
-    ];
+      sha256 = "1kj487vllqj9720vlhfsmv32hs2dy2agp6176mav6ldx31c3g4n4";
 
-    nativeBuildInputs = [ pkgs.pkgconfig ];
+      configureFlags = [
+        "--with-zmq=${pkgs.zeromq}"
+      ];
 
-    meta.broken = isPhp73;
-  };
+      nativeBuildInputs = [ pkgs.pkgconfig ];
 
-  exts = let
+      meta.broken = isPhp73;
+    };
+  } // (let
     # Function to build a single php extension based on the php version.
     #
     # Name passed is the name of the extension and is automatically used
@@ -730,9 +741,7 @@ in
     # want to build.
     #
     # These will be passed as arguments to mkExtension above.
-    extensionData = let
-      pcre' = if (lib.versionAtLeast php.version "7.3") then pcre2 else pcre;
-    in [
+    extensionData = [
       { name = "bcmath"; }
       { name = "bz2"; buildInputs = [ bzip2 ]; configureFlags = [ "--with-bz2=${bzip2.dev}" ]; }
       { name = "calendar"; }
@@ -814,7 +823,7 @@ in
         doCheck = false; }
       { name = "mbstring"; buildInputs = [ oniguruma ]; doCheck = false; }
       { name = "mysqli";
-        internalDeps = [ php.packages.exts.mysqlnd ];
+        internalDeps = [ php.extensions.mysqlnd ];
         configureFlags = [ "--with-mysqli=mysqlnd" "--with-mysql-sock=/run/mysqld/mysqld.sock" ];
         doCheck = false; }
       { name = "mysqlnd";
@@ -875,27 +884,27 @@ in
       { name = "pcntl"; }
       { name = "pdo"; doCheck = false; }
       { name = "pdo_dblib";
-        internalDeps = [ php.packages.exts.pdo ];
+        internalDeps = [ php.extensions.pdo ];
         configureFlags = [ "--with-pdo-dblib=${freetds}" ];
         # Doesn't seem to work on darwin.
         enable = (!stdenv.isDarwin);
         doCheck = false; }
       # pdo_firebird (7.4, 7.3, 7.2)
       { name = "pdo_mysql";
-        internalDeps = with php.packages.exts; [ pdo mysqlnd ];
+        internalDeps = with php.extensions; [ pdo mysqlnd ];
         configureFlags = [ "--with-pdo-mysql=mysqlnd" ];
         doCheck = false; }
       # pdo_oci (7.4, 7.3, 7.2)
       { name = "pdo_odbc";
-        internalDeps = [ php.packages.exts.pdo ];
+        internalDeps = [ php.extensions.pdo ];
         configureFlags = [ "--with-pdo-odbc=unixODBC,${unixODBC}" ];
         doCheck = false; }
       { name = "pdo_pgsql";
-        internalDeps = [ php.packages.exts.pdo ];
+        internalDeps = [ php.extensions.pdo ];
         configureFlags = [ "--with-pdo-pgsql=${postgresql}" ];
         doCheck = false; }
       { name = "pdo_sqlite";
-        internalDeps = [ php.packages.exts.pdo ];
+        internalDeps = [ php.extensions.pdo ];
         buildInputs = [ sqlite ];
         configureFlags = [ "--with-pdo-sqlite=${sqlite.dev}" ];
         doCheck = false; }
@@ -999,5 +1008,5 @@ in
     }) (builtins.filter (i: i.enable or true) extensionData);
 
     # Produce the final attribute set of all extensions defined.
-  in builtins.listToAttrs namedExtensions;
+  in builtins.listToAttrs namedExtensions);
 }