about summary refs log tree commit diff
path: root/pkgs
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/build-support/build-pecl.nix12
-rw-r--r--pkgs/development/interpreters/php/default.nix363
-rw-r--r--pkgs/servers/http/unit/default.nix22
-rw-r--r--pkgs/servers/uwsgi/default.nix9
-rw-r--r--pkgs/top-level/aliases.nix49
-rw-r--r--pkgs/top-level/all-packages.nix89
-rw-r--r--pkgs/top-level/php-packages.nix1352
7 files changed, 1006 insertions, 890 deletions
diff --git a/pkgs/build-support/build-pecl.nix b/pkgs/build-support/build-pecl.nix
index a1030e3b34fa..f43205f24c5c 100644
--- a/pkgs/build-support/build-pecl.nix
+++ b/pkgs/build-support/build-pecl.nix
@@ -1,9 +1,11 @@
-{ stdenv, php, autoreconfHook, fetchurl, re2c }:
+{ stdenv, lib, php, autoreconfHook, fetchurl, re2c }:
 
 { pname
 , version
+, internalDeps ? []
 , buildInputs ? []
 , nativeBuildInputs ? []
+, postPhpize ? ""
 , makeFlags ? []
 , src ? fetchurl {
     url = "http://pecl.php.net/get/${pname}-${version}.tgz";
@@ -22,5 +24,11 @@ stdenv.mkDerivation (args // {
 
   makeFlags = [ "EXTENSION_DIR=$(out)/lib/php/extensions" ] ++ makeFlags;
 
-  autoreconfPhase = "phpize";
+  autoreconfPhase = ''
+    phpize
+    ${postPhpize}
+    ${lib.concatMapStringsSep "\n"
+      (dep: "mkdir -p ext; ln -s ${dep.dev}/include ext/${dep.extensionName}")
+      internalDeps}
+  '';
 })
diff --git a/pkgs/development/interpreters/php/default.nix b/pkgs/development/interpreters/php/default.nix
index 497a1d87f557..d260a90e8ea6 100644
--- a/pkgs/development/interpreters/php/default.nix
+++ b/pkgs/development/interpreters/php/default.nix
@@ -1,13 +1,9 @@
-# pcre functionality is tested in nixos/tests/php-pcre.nix
-{ config, lib, stdenv, fetchurl
-, autoconf, automake, bison, file, flex, libtool, pkgconfig, re2c
-, libxml2, readline, zlib, curl, postgresql, gettext
-, openssl, pcre, pcre2, sqlite
-, libxslt, bzip2, icu, openldap, cyrus_sasl, unixODBC
-, uwimap, pam, gmp, apacheHttpd, libiconv, systemd, libsodium, html-tidy, libargon2
-, gd, freetype, libXpm, libjpeg, libpng, libwebp
-, libzip, valgrind, oniguruma, symlinkJoin, writeText
-, makeWrapper, callPackage
+# We have tests for PCRE and PHP-FPM in nixos/tests/php/ or
+# both in the same attribute named nixosTests.php
+
+{ callPackage, config, fetchurl, lib, makeWrapper, stdenv, symlinkJoin
+, writeText , autoconf, automake, bison, flex, libtool, pkgconfig, re2c
+, apacheHttpd, libargon2, libxml2, pcre, pcre2 , systemd, valgrind
 }:
 
 let
@@ -15,182 +11,83 @@ let
   { version
   , sha256
   , extraPatches ? []
-  , withSystemd ? config.php.systemd or stdenv.isLinux
-  , imapSupport ? config.php.imap or (!stdenv.isDarwin)
-  , ldapSupport ? config.php.ldap or true
-  , mysqlndSupport ? config.php.mysqlnd or true
-  , mysqliSupport ? (config.php.mysqli or true) && (mysqlndSupport)
-  , pdo_mysqlSupport ? (config.php.pdo_mysql or true) && (mysqlndSupport)
-  , libxml2Support ? config.php.libxml2 or true
-  , apxs2Support ? config.php.apxs2 or (!stdenv.isDarwin)
-  , embedSupport ? config.php.embed or false
-  , bcmathSupport ? config.php.bcmath or true
-  , socketsSupport ? config.php.sockets or true
-  , curlSupport ? config.php.curl or true
-  , gettextSupport ? config.php.gettext or true
-  , pcntlSupport ? config.php.pcntl or true
-  , pdo_odbcSupport ? config.php.pdo_odbc or true
-  , postgresqlSupport ? config.php.postgresql or true
-  , pdo_pgsqlSupport ? config.php.pdo_pgsql or true
-  , readlineSupport ? config.php.readline or true
-  , sqliteSupport ? config.php.sqlite or true
-  , soapSupport ? (config.php.soap or true) && (libxml2Support)
-  , zlibSupport ? config.php.zlib or true
-  , opensslSupport ? config.php.openssl or true
-  , mbstringSupport ? config.php.mbstring or true
-  , gdSupport ? config.php.gd or true
-  , intlSupport ? config.php.intl or true
-  , exifSupport ? config.php.exif or true
-  , xslSupport ? config.php.xsl or false
-  , bz2Support ? config.php.bz2 or false
-  , zipSupport ? config.php.zip or true
-  , ftpSupport ? config.php.ftp or true
-  , fpmSupport ? config.php.fpm or true
-  , gmpSupport ? config.php.gmp or true
-  , ztsSupport ? (config.php.zts or false) || (apxs2Support)
-  , calendarSupport ? config.php.calendar or true
-  , sodiumSupport ? (config.php.sodium or true) && (lib.versionAtLeast version "7.2")
-  , tidySupport ? (config.php.tidy or false)
-  , argon2Support ? (config.php.argon2 or true) && (lib.versionAtLeast version "7.2")
-  , libzipSupport ? (config.php.libzip or true) && (lib.versionAtLeast version "7.2")
-  , phpdbgSupport ? config.php.phpdbg or true
+
+  # Sapi flags
   , cgiSupport ? config.php.cgi or true
   , cliSupport ? config.php.cli or true
+  , fpmSupport ? config.php.fpm or true
+  , pearSupport ? config.php.pear or true
   , pharSupport ? config.php.phar or true
-  , xmlrpcSupport ? (config.php.xmlrpc or false) && (libxml2Support)
+  , phpdbgSupport ? config.php.phpdbg or true
+
+
+  # Misc flags
+  , apxs2Support ? config.php.apxs2 or (!stdenv.isDarwin)
+  , argon2Support ? config.php.argon2 or true
   , cgotoSupport ? config.php.cgoto or false
-  , valgrindSupport ? (config.php.valgrind or true) && (lib.versionAtLeast version "7.2")
+  , embedSupport ? config.php.embed or false
   , ipv6Support ? config.php.ipv6 or true
-  , pearSupport ? (config.php.pear or true) && (libxml2Support)
-  }: stdenv.mkDerivation {
+  , systemdSupport ? config.php.systemd or stdenv.isLinux
+  , valgrindSupport ? config.php.valgrind or true
+  , ztsSupport ? (config.php.zts or false) || (apxs2Support)
+  }: let
+    pcre' = if (lib.versionAtLeast version "7.3") then pcre2 else pcre;
+  in stdenv.mkDerivation {
     pname = "php";
 
     inherit version;
 
     enableParallelBuilding = true;
 
-    nativeBuildInputs = [ autoconf automake bison file flex libtool pkgconfig re2c ];
-
-    buildInputs = [ ]
-      ++ lib.optional (lib.versionOlder version "7.3") pcre
-      ++ lib.optional (lib.versionAtLeast version "7.3") pcre2
-      ++ lib.optional (lib.versionAtLeast version "7.4") oniguruma
-      ++ lib.optional withSystemd systemd
-      ++ lib.optionals imapSupport [ uwimap openssl pam ]
-      ++ lib.optionals curlSupport [ curl openssl ]
-      ++ lib.optionals ldapSupport [ openldap openssl ]
-      ++ lib.optionals gdSupport [ gd freetype libXpm libjpeg libpng libwebp ]
-      ++ lib.optionals opensslSupport [ openssl openssl.dev ]
+    nativeBuildInputs = [ autoconf automake bison flex libtool pkgconfig re2c ];
+
+    buildInputs =
+      # PCRE extension
+      [ pcre' ]
+
+      # Enable sapis
+      ++ lib.optional pearSupport [ libxml2.dev ]
+
+      # Misc deps
       ++ lib.optional apxs2Support apacheHttpd
-      ++ lib.optional (ldapSupport && stdenv.isLinux) cyrus_sasl
-      ++ lib.optional zlibSupport zlib
-      ++ lib.optional libxml2Support libxml2
-      ++ lib.optional readlineSupport readline
-      ++ lib.optional sqliteSupport sqlite
-      ++ lib.optional postgresqlSupport postgresql
-      ++ lib.optional pdo_odbcSupport unixODBC
-      ++ lib.optional pdo_pgsqlSupport postgresql
-      ++ lib.optional gmpSupport gmp
-      ++ lib.optional gettextSupport gettext
-      ++ lib.optional intlSupport icu
-      ++ lib.optional xslSupport libxslt
-      ++ lib.optional bz2Support bzip2
-      ++ lib.optional sodiumSupport libsodium
-      ++ lib.optional tidySupport html-tidy
       ++ lib.optional argon2Support libargon2
-      ++ lib.optional libzipSupport libzip
-      ++ lib.optional valgrindSupport valgrind;
+      ++ lib.optional systemdSupport systemd
+      ++ lib.optional valgrindSupport valgrind
+    ;
 
     CXXFLAGS = lib.optionalString stdenv.cc.isClang "-std=c++11";
 
-    configureFlags = [ "--with-config-file-scan-dir=/etc/php.d" ]
-      ++ lib.optionals (lib.versionOlder version "7.3") [ "--with-pcre-regex=${pcre.dev}" "PCRE_LIBDIR=${pcre}" ]
-      ++ lib.optionals (lib.versions.majorMinor version == "7.3") [ "--with-pcre-regex=${pcre2.dev}" "PCRE_LIBDIR=${pcre2}" ]
-      ++ lib.optionals (lib.versionAtLeast version "7.4") [ "--with-external-pcre=${pcre2.dev}" "PCRE_LIBDIR=${pcre2}" ]
-      ++ lib.optional stdenv.isDarwin "--with-iconv=${libiconv}"
-      ++ lib.optional withSystemd "--with-fpm-systemd"
-      ++ lib.optionals imapSupport [
-        "--with-imap=${uwimap}"
-        "--with-imap-ssl"
-      ]
-      ++ lib.optionals ldapSupport [
-        "--with-ldap=/invalid/path"
-        "LDAP_DIR=${openldap.dev}"
-        "LDAP_INCDIR=${openldap.dev}/include"
-        "LDAP_LIBDIR=${openldap.out}/lib"
-      ]
-      ++ lib.optional (ldapSupport && stdenv.isLinux) "--with-ldap-sasl=${cyrus_sasl.dev}"
-      ++ lib.optional apxs2Support "--with-apxs2=${apacheHttpd.dev}/bin/apxs"
-      ++ lib.optional embedSupport "--enable-embed"
-      ++ lib.optional curlSupport "--with-curl=${curl.dev}"
-      ++ lib.optional zlibSupport "--with-zlib=${zlib.dev}"
-      ++ lib.optional (libxml2Support && (lib.versionOlder version "7.4")) "--with-libxml-dir=${libxml2.dev}"
-      ++ lib.optional (!libxml2Support) [
-        "--disable-dom"
-        (if (lib.versionOlder version "7.4") then "--disable-libxml" else "--without-libxml")
-        "--disable-simplexml"
-        "--disable-xml"
-        "--disable-xmlreader"
-        "--disable-xmlwriter"
-        "--without-pear"
-      ]
-      ++ lib.optional pcntlSupport "--enable-pcntl"
-      ++ lib.optional readlineSupport "--with-readline=${readline.dev}"
-      ++ lib.optional sqliteSupport "--with-pdo-sqlite=${sqlite.dev}"
-      ++ lib.optional postgresqlSupport "--with-pgsql=${postgresql}"
-      ++ lib.optional pdo_odbcSupport "--with-pdo-odbc=unixODBC,${unixODBC}"
-      ++ lib.optional pdo_pgsqlSupport "--with-pdo-pgsql=${postgresql}"
-      ++ lib.optional (pdo_mysqlSupport && mysqlndSupport) "--with-pdo-mysql=mysqlnd"
-      ++ lib.optional (mysqliSupport && mysqlndSupport) "--with-mysqli=mysqlnd"
-      ++ lib.optional (pdo_mysqlSupport || mysqliSupport) "--with-mysql-sock=/run/mysqld/mysqld.sock"
-      ++ lib.optional bcmathSupport "--enable-bcmath"
-      ++ lib.optionals (gdSupport && lib.versionAtLeast version "7.4") [
-        "--enable-gd"
-        "--with-external-gd=${gd.dev}"
-        "--with-webp=${libwebp}"
-        "--with-jpeg=${libjpeg.dev}"
-        "--with-xpm=${libXpm.dev}"
-        "--with-freetype=${freetype.dev}"
-        "--enable-gd-jis-conv"
-      ] ++ lib.optionals (gdSupport && lib.versionOlder version "7.4") [
-        "--with-gd=${gd.dev}"
-        "--with-webp-dir=${libwebp}"
-        "--with-jpeg-dir=${libjpeg.dev}"
-        "--with-png-dir=${libpng.dev}"
-        "--with-freetype-dir=${freetype.dev}"
-        "--with-xpm-dir=${libXpm.dev}"
-        "--enable-gd-jis-conv"
-      ]
-      ++ lib.optional gmpSupport "--with-gmp=${gmp.dev}"
-      ++ lib.optional soapSupport "--enable-soap"
-      ++ lib.optional socketsSupport "--enable-sockets"
-      ++ lib.optional opensslSupport "--with-openssl"
-      ++ lib.optional mbstringSupport "--enable-mbstring"
-      ++ lib.optional gettextSupport "--with-gettext=${gettext}"
-      ++ lib.optional intlSupport "--enable-intl"
-      ++ lib.optional exifSupport "--enable-exif"
-      ++ lib.optional xslSupport "--with-xsl=${libxslt.dev}"
-      ++ lib.optional bz2Support "--with-bz2=${bzip2.dev}"
-      ++ lib.optional (zipSupport && (lib.versionOlder version "7.4")) "--enable-zip"
-      ++ lib.optional (zipSupport && (lib.versionAtLeast version "7.4")) "--with-zip"
-      ++ lib.optional ftpSupport "--enable-ftp"
-      ++ lib.optional fpmSupport "--enable-fpm"
-      ++ lib.optional ztsSupport "--enable-maintainer-zts"
-      ++ lib.optional calendarSupport "--enable-calendar"
-      ++ lib.optional sodiumSupport "--with-sodium=${libsodium.dev}"
-      ++ lib.optional tidySupport "--with-tidy=${html-tidy}"
-      ++ lib.optional argon2Support "--with-password-argon2=${libargon2}"
-      ++ lib.optional (libzipSupport && (lib.versionOlder version "7.4")) "--with-libzip=${libzip.dev}"
-      ++ lib.optional phpdbgSupport "--enable-phpdbg"
-      ++ lib.optional (!phpdbgSupport) "--disable-phpdbg"
+    configureFlags =
+      # Disable all extensions
+      [ "--disable-all" ]
+
+      # PCRE
+      ++ lib.optionals (lib.versionAtLeast version "7.4") [ "--with-external-pcre=${pcre'.dev}" ]
+      ++ lib.optionals (lib.versions.majorMinor version == "7.3") [ "--with-pcre-regex=${pcre'.dev}" ]
+      ++ lib.optionals (lib.versionOlder version "7.3") [ "--with-pcre-regex=${pcre'.dev}" ]
+      ++ [ "PCRE_LIBDIR=${pcre'}" ]
+
+
+      # Enable sapis
       ++ lib.optional (!cgiSupport) "--disable-cgi"
       ++ lib.optional (!cliSupport) "--disable-cli"
-      ++ lib.optional (!pharSupport) "--disable-phar"
-      ++ lib.optional xmlrpcSupport "--with-xmlrpc"
+      ++ lib.optional fpmSupport    "--enable-fpm"
+      ++ lib.optional pearSupport [ "--with-pear=$(out)/lib/php/pear" "--enable-xml" "--with-libxml" ]
+      ++ lib.optional (pearSupport && (lib.versionOlder version "7.4")) "--enable-libxml"
+      ++ lib.optional pharSupport   "--enable-phar"
+      ++ lib.optional phpdbgSupport "--enable-phpdbg"
+
+
+      # Misc flags
+      ++ lib.optional apxs2Support "--with-apxs2=${apacheHttpd.dev}/bin/apxs"
+      ++ lib.optional argon2Support "--with-password-argon2=${libargon2}"
       ++ lib.optional cgotoSupport "--enable-re2c-cgoto"
-      ++ lib.optional valgrindSupport "--with-valgrind=${valgrind.dev}"
+      ++ lib.optional embedSupport "--enable-embed"
       ++ lib.optional (!ipv6Support) "--disable-ipv6"
-      ++ lib.optional (pearSupport && libxml2Support) "--with-pear=$(out)/lib/php/pear";
+      ++ lib.optional systemdSupport "--with-fpm-systemd"
+      ++ lib.optional valgrindSupport "--with-valgrind=${valgrind.dev}"
+      ++ lib.optional ztsSupport "--enable-maintainer-zts"
+    ;
 
     hardeningDisable = [ "bindnow" ];
 
@@ -204,8 +101,6 @@ let
           --replace '@PHP_LDFLAGS@' ""
       done
 
-      substituteInPlace ./build/libtool.m4 --replace /usr/bin/file ${file}/bin/file
-
       export EXTENSION_DIR=$out/lib/php/extensions
 
       ./buildconf --copy --force
@@ -235,6 +130,12 @@ let
       inherit sha256;
     };
 
+    patches = [ ./fix-paths-php7.patch ] ++ extraPatches;
+
+    separateDebugInfo = true;
+
+    outputs = [ "out" "dev" ];
+
     meta = with stdenv.lib; {
       description = "An HTML-embedded scripting language";
       homepage = "https://www.php.net/";
@@ -243,57 +144,121 @@ let
       platforms = platforms.all;
       outputsToInstall = [ "out" "dev" ];
     };
+  };
 
-    patches = [ ./fix-paths-php7.patch ] ++ extraPatches;
+  generic' = { version, sha256, self, selfWithExtensions, ... }@args:
+    let
+      php = generic (builtins.removeAttrs args [ "self" "selfWithExtensions" ]);
 
-    stripDebugList = "bin sbin lib modules";
+      php-packages = (callPackage ../../../top-level/php-packages.nix {
+        php = self;
+        phpWithExtensions = selfWithExtensions;
+      });
 
-    outputs = [ "out" "dev" ];
-  };
+      buildEnv = { extensions ? (_: []), extraConfig ? "" }:
+        let
+          getExtName = ext: lib.removePrefix "php-" (builtins.parseDrvName ext.name).name;
+          enabledExtensions = extensions php-packages.extensions;
 
-  generic' = { version, sha256, ... }@args: let php = generic args; in php.overrideAttrs (_: {
-    passthru.buildEnv = { exts ? (_: []), extraConfig ? "" }: let
-      extraInit = writeText "custom-php.ini" ''
-        ${extraConfig}
-        ${lib.concatMapStringsSep "\n" (ext: let
-          extName = lib.removePrefix "php-" (builtins.parseDrvName ext.name).name;
-          type = "${lib.optionalString (ext.zendExtension or false) "zend_"}extension";
-        in ''
-          ${type}=${ext}/lib/php/extensions/${extName}.so
-        '') (exts (callPackage ../../../top-level/php-packages.nix { inherit php; }))}
-      '';
-    in symlinkJoin {
-      name = "php-custom-${version}";
-      nativeBuildInputs = [ makeWrapper ];
-      paths = [ php ];
-      postBuild = ''
-        wrapProgram $out/bin/php \
-          --add-flags "-c ${extraInit}"
-        wrapProgram $out/bin/php-fpm \
-          --add-flags "-c ${extraInit}"
-      '';
-    };
-  });
+          # Generate extension load configuration snippets from the
+          # extension parameter. This is an attrset suitable for use
+          # with textClosureList, which is used to put the strings in
+          # the right order - if a plugin which is dependent on
+          # another plugin is placed before its dependency, it will
+          # fail to load.
+          extensionTexts =
+            lib.listToAttrs
+              (map (ext:
+                let
+                  extName = getExtName ext;
+                  type = "${lib.optionalString (ext.zendExtension or false) "zend_"}extension";
+                in
+                  lib.nameValuePair extName {
+                    text = "${type}=${ext}/lib/php/extensions/${extName}.so";
+                    deps = lib.optionals (ext ? internalDeps)
+                      (map getExtName ext.internalDeps);
+                  })
+                enabledExtensions);
 
-in {
-  php72 = generic' {
+          extNames = map getExtName enabledExtensions;
+          extraInit = writeText "custom-php.ini" ''
+            ${lib.concatStringsSep "\n"
+              (lib.textClosureList extensionTexts extNames)}
+            ${extraConfig}
+          '';
+        in
+          symlinkJoin {
+            name = "php-with-extensions-${version}";
+            inherit (php) version dev;
+            nativeBuildInputs = [ makeWrapper ];
+            passthru = {
+              inherit buildEnv withExtensions enabledExtensions;
+              inherit (php-packages) packages extensions;
+            };
+            paths = [ php ];
+            postBuild = ''
+              cp ${extraInit} $out/lib/custom-php.ini
+
+              wrapProgram $out/bin/php --set PHP_INI_SCAN_DIR $out/lib
+
+              if test -e $out/bin/php-fpm; then
+                 wrapProgram $out/bin/php-fpm --set PHP_INI_SCAN_DIR $out/lib
+              fi
+            '';
+          };
+
+      withExtensions = extensions: buildEnv { inherit extensions; };
+    in
+      php.overrideAttrs (_: {
+        passthru = {
+          enabledExtensions = [];
+          inherit buildEnv withExtensions;
+          inherit (php-packages) packages extensions;
+        };
+      });
+
+  php72base = generic' {
     version = "7.2.28";
     sha256 = "18sjvl67z5a2x5s2a36g6ls1r3m4hbrsw52hqr2qsgfvg5dkm5bw";
+    self = php72base;
+    selfWithExtensions = php72;
 
     # https://bugs.php.net/bug.php?id=76826
     extraPatches = lib.optional stdenv.isDarwin ./php72-darwin-isfinite.patch;
   };
 
-  php73 = generic' {
+  php73base = generic' {
     version = "7.3.15";
     sha256 = "0g84hws15s8gh8iq4h6q747dyfazx47vh3da3whz8d80x83ibgld";
+    self = php73base;
+    selfWithExtensions = php73;
 
     # https://bugs.php.net/bug.php?id=76826
     extraPatches = lib.optional stdenv.isDarwin ./php73-darwin-isfinite.patch;
   };
 
-  php74 = generic' {
+  php74base = generic' {
     version = "7.4.3";
     sha256 = "wVF7pJV4+y3MZMc6Ptx21PxQfEp6xjmYFYTMfTtMbRQ=";
+    self = php74base;
+    selfWithExtensions = php74;
   };
+
+  defaultPhpExtensions = extensions: with extensions; ([
+    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
+    posix readline session simplexml sockets soap sodium sqlite3
+    tokenizer xmlreader xmlwriter zip zlib
+  ] ++ lib.optionals (!stdenv.isDarwin) [ imap ]);
+
+  defaultPhpExtensionsWithHash = extensions:
+    (defaultPhpExtensions extensions) ++ [ extensions.hash ];
+
+  php74 = php74base.withExtensions defaultPhpExtensions;
+  php73 = php73base.withExtensions defaultPhpExtensionsWithHash;
+  php72 = php72base.withExtensions defaultPhpExtensionsWithHash;
+
+in {
+  inherit php72base php73base php74base php72 php73 php74;
 }
diff --git a/pkgs/servers/http/unit/default.nix b/pkgs/servers/http/unit/default.nix
index c56e994ed54e..752a0fa493c1 100644
--- a/pkgs/servers/http/unit/default.nix
+++ b/pkgs/servers/http/unit/default.nix
@@ -16,7 +16,19 @@
 
 with stdenv.lib;
 
-stdenv.mkDerivation rec {
+let
+  phpConfig = {
+    config.php.embed = true;
+    config.php.apxs2 = false;
+    config.php.systemd = false;
+    config.php.phpdbg = false;
+    config.php.cgi = false;
+    config.php.fpm = false;
+  };
+
+  php72-unit = php72.override phpConfig;
+  php73-unit = php73.override phpConfig;
+in stdenv.mkDerivation rec {
   version = "1.16.0";
   pname = "unit";
 
@@ -37,8 +49,8 @@ stdenv.mkDerivation rec {
   buildInputs = [ ]
     ++ optional withPython2 python2
     ++ optionals withPython3 [ python3 ncurses ]
-    ++ optional withPHP72 php72
-    ++ optional withPHP73 php73
+    ++ optional withPHP72 php72-unit
+    ++ optional withPHP73 php73-unit
     ++ optional withPerl528 perl528
     ++ optional withPerl530 perl530
     ++ optional withPerldevel perldevel
@@ -59,8 +71,8 @@ stdenv.mkDerivation rec {
   postConfigure = ''
     ${optionalString withPython2    "./configure python --module=python2  --config=${python2}/bin/python2-config  --lib-path=${python2}/lib"}
     ${optionalString withPython3    "./configure python --module=python3  --config=${python3}/bin/python3-config  --lib-path=${python3}/lib"}
-    ${optionalString withPHP72      "./configure php    --module=php72    --config=${php72.dev}/bin/php-config    --lib-path=${php72}/lib"}
-    ${optionalString withPHP73      "./configure php    --module=php73    --config=${php73.dev}/bin/php-config    --lib-path=${php73}/lib"}
+    ${optionalString withPHP72      "./configure php    --module=php72    --config=${php72-unit.dev}/bin/php-config    --lib-path=${php72-unit}/lib"}
+    ${optionalString withPHP73      "./configure php    --module=php73    --config=${php73-unit.dev}/bin/php-config    --lib-path=${php73-unit}/lib"}
     ${optionalString withPerl528    "./configure perl   --module=perl528  --perl=${perl528}/bin/perl"}
     ${optionalString withPerl530    "./configure perl   --module=perl530  --perl=${perl530}/bin/perl"}
     ${optionalString withPerldevel  "./configure perl   --module=perldev  --perl=${perldevel}/bin/perl"}
diff --git a/pkgs/servers/uwsgi/default.nix b/pkgs/servers/uwsgi/default.nix
index 7669053d2294..0a1ad23c2cef 100644
--- a/pkgs/servers/uwsgi/default.nix
+++ b/pkgs/servers/uwsgi/default.nix
@@ -4,10 +4,15 @@
 , pam, withPAM ? stdenv.isLinux
 , systemd, withSystemd ? stdenv.isLinux
 , python2, python3, ncurses
-, ruby, php-embed, libmysqlclient
+, ruby, php, libmysqlclient
 }:
 
-let pythonPlugin = pkg : lib.nameValuePair "python${if pkg.isPy2 then "2" else "3"}" {
+let php-embed = php.override {
+      config.php.embed = true;
+      config.php.apxs2 = false;
+    };
+
+    pythonPlugin = pkg : lib.nameValuePair "python${if pkg.isPy2 then "2" else "3"}" {
                            interpreter = pkg.interpreter;
                            path = "plugins/python";
                            inputs = [ pkg ncurses ];
diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix
index 2aaefa78ccdc..b56f921d0c2a 100644
--- a/pkgs/top-level/aliases.nix
+++ b/pkgs/top-level/aliases.nix
@@ -322,6 +322,55 @@ mapAliases ({
   perlArchiveCpio = perlPackages.ArchiveCpio; # added 2018-10-12
   pgp-tools = signing-party; # added 2017-03-26
   pg_tmp = ephemeralpg; # added 2018-01-16
+
+  php-embed = throw ''
+    php*-embed has been dropped, you can build the same package by using
+     something similar with this following snippet:
+    (php74.override { config.php.embed = true; config.php.apxs2 = false; })
+  ''; # added 2020-04-01
+  php72-embed = php-embed; # added 2020-04-01
+  php73-embed = php-embed; # added 2020-04-01
+  php74-embed = php-embed; # added 2020-04-01
+
+  phpPackages-embed = throw ''
+    php*Packages-embed has been dropped, you can build the same package by using
+     something similar with this following snippet:
+    (php74.override { config.php.embed = true; config.php.apxs2 = false; }).packages
+  ''; # added 2020-04-01
+  php74Packages-embed = phpPackages-embed;
+  php73Packages-embed = phpPackages-embed;
+  php72Packages-embed = phpPackages-embed;
+
+  php-unit = throw ''
+    php*-unit has been dropped, you can build the same package by using
+     something similar with this following snippet:
+    (php74.override {
+      config.php.embed = true;
+      config.php.apxs2 = false;
+      config.php.systemd = false;
+      config.php.phpdbg = false;
+      config.php.cgi = false;
+      config.php.fpm = false; })
+  ''; # added 2020-04-01
+  php72-unit = php-unit; # added 2020-04-01
+  php73-unit = php-unit; # added 2020-04-01
+  php74-unit = php-unit; # added 2020-04-01
+
+  phpPackages-unit = throw ''
+    php*Packages-unit has been dropped, you can build the same package by using
+     something similar with this following snippet:
+    (php74.override {
+      config.php.embed = true;
+      config.php.apxs2 = false;
+      config.php.systemd = false;
+      config.php.phpdbg = false;
+      config.php.cgi = false;
+      config.php.fpm = false; }).packages
+  ''; # added 2020-04-01
+  php74Packages-unit = phpPackages-unit;
+  php73Packages-unit = phpPackages-unit;
+  php72Packages-unit = phpPackages-unit;
+
   pidgin-with-plugins = pidgin; # added 2016-06
   pidginlatex = pidgin-latex; # added 2018-01-08
   pidginlatexSF = pidgin-latex; # added 2014-11-02
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 4d864e1c0934..13f65d7c1c7f 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -9391,86 +9391,20 @@ in
   pachyderm = callPackage ../applications/networking/cluster/pachyderm { };
 
   php = php74;
-  phpPackages = php74Packages;
-
-  php72Packages = recurseIntoAttrs (callPackage ./php-packages.nix {
-    php = php72;
-  });
-
-  php73Packages = recurseIntoAttrs (callPackage ./php-packages.nix {
-    php = php73;
-  });
-
-  php74Packages = recurseIntoAttrs (callPackage ./php-packages.nix {
-    php = php74;
-  });
-
-  phpPackages-unit = php74Packages-unit;
 
-  php72Packages-unit = recurseIntoAttrs (callPackage ./php-packages.nix {
-    php = php72-unit;
-  });
+  phpPackages = php74Packages;
+  php72Packages = recurseIntoAttrs php72.packages;
+  php73Packages = recurseIntoAttrs php73.packages;
+  php74Packages = recurseIntoAttrs php74.packages;
 
-  php73Packages-unit = recurseIntoAttrs (callPackage ./php-packages.nix {
-    php = php73-unit;
-  });
-
-  php74Packages-unit = recurseIntoAttrs (callPackage ./php-packages.nix {
-    php = php74-unit;
-  });
+  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;
-
-  php-embed = php74-embed;
-
-  php72-embed = php72.override {
-    config.php.embed = true;
-    config.php.apxs2 = false;
-  };
-
-  php73-embed = php73.override {
-    config.php.embed = true;
-    config.php.apxs2 = false;
-  };
-
-  php74-embed = php74.override {
-    config.php.embed = true;
-    config.php.apxs2 = false;
-  };
-
-  php-unit = php74-unit;
-
-  php72-unit = php72.override {
-    config.php.embed = true;
-    config.php.apxs2 = false;
-    config.php.systemd = false;
-    config.php.phpdbg = false;
-    config.php.cgi = false;
-    config.php.fpm = false;
-  };
-
-  php73-unit = php73.override {
-    config.php.embed = true;
-    config.php.apxs2 = false;
-    config.php.systemd = false;
-    config.php.phpdbg = false;
-    config.php.cgi = false;
-    config.php.fpm = false;
-  };
-
-  php74-unit = php74.override {
-    config.php.embed = true;
-    config.php.apxs2 = false;
-    config.php.systemd = false;
-    config.php.phpdbg = false;
-    config.php.cgi = false;
-    config.php.fpm = false;
-  };
+  }) php74 php73 php72 php74base php73base php72base;
 
   picoc = callPackage ../development/interpreters/picoc {};
 
@@ -15641,10 +15575,7 @@ in
 
   neard = callPackage ../servers/neard { };
 
-  unit = callPackage ../servers/http/unit {
-    php72 = php72-unit;
-    php73 = php73-unit;
-  };
+  unit = callPackage ../servers/http/unit { };
 
   nginx = nginxStable;
 
diff --git a/pkgs/top-level/php-packages.nix b/pkgs/top-level/php-packages.nix
index cc830fa34986..6bae48b54c38 100644
--- a/pkgs/top-level/php-packages.nix
+++ b/pkgs/top-level/php-packages.nix
@@ -1,704 +1,731 @@
-{ stdenv, lib, pkgs, fetchgit, php, autoconf, pkgconfig, re2c
-, bzip2, curl, libxml2, openssl, gmp5, icu, oniguruma, libsodium, html-tidy
-, libzip, zlib, pcre, pcre2, libxslt, aspell, openldap, cyrus_sasl, uwimap
-, pam, libiconv, enchant1, libXpm, gd, libwebp, libjpeg, libpng, freetype
-, libffi, freetds, postgresql, sqlite, recode, net-snmp, unixODBC }:
+{ stdenv, lib, pkgs, fetchgit, php, phpWithExtensions, autoconf, pkgconfig, re2c
+, gettext, bzip2, curl, libxml2, openssl, gmp, icu, oniguruma, libsodium
+, html-tidy, libzip, zlib, pcre, pcre2, libxslt, aspell, openldap, cyrus_sasl
+, uwimap, pam, libiconv, enchant1, libXpm, gd, libwebp, libjpeg, libpng
+, freetype, libffi, freetds, postgresql, sqlite, net-snmp, unixODBC, libedit
+, readline, rsync
+}:
 
 let
-  self = with self; {
-    buildPecl = import ../build-support/build-pecl.nix {
-      inherit php;
-      inherit (pkgs) stdenv autoreconfHook fetchurl re2c;
-    };
+  buildPecl = import ../build-support/build-pecl.nix {
+    inherit php lib;
+    inherit (pkgs) stdenv autoreconfHook fetchurl re2c;
+  };
 
-    # Wrap mkDerivation to prepend pname with "php-" to make names consistent
-    # with how buildPecl does it and make the file easier to overview.
-    mkDerivation = { pname, ... }@args: pkgs.stdenv.mkDerivation (args // {
-      pname = "php-${pname}";
-    });
+  # Wrap mkDerivation to prepend pname with "php-" to make names consistent
+  # with how buildPecl does it and make the file easier to overview.
+  mkDerivation = { pname, ... }@args: pkgs.stdenv.mkDerivation (args // {
+    pname = "php-${pname}";
+  });
 
   isPhp73 = pkgs.lib.versionAtLeast php.version "7.3";
   isPhp74 = pkgs.lib.versionAtLeast php.version "7.4";
 
-  apcu = buildPecl {
-    version = "5.1.18";
-    pname = "apcu";
-
-    sha256 = "0ayykd4hfvdzk7qnr5k6yq5scwf6rb2i05xscfv76q5dmkkynvfl";
-
-    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" ];
-  };
-
-  apcu_bc = buildPecl {
-    version = "1.0.5";
-    pname = "apcu_bc";
+  pcre' = if (lib.versionAtLeast php.version "7.3") then pcre2 else pcre;
+in
+{
+  inherit buildPecl;
 
-    sha256 = "0ma00syhk2ps9k9p02jz7rii6x3i2p986il23703zz5npd6y9n20";
+  # This is a set of interactive tools based on PHP.
+  packages = {
+    box = mkDerivation rec {
+      version = "2.7.5";
+      pname = "box";
 
-    buildInputs = [ apcu (if isPhp73 then pkgs.pcre2 else pkgs.pcre) ];
-  };
+      src = pkgs.fetchurl {
+        url = "https://github.com/box-project/box2/releases/download/${version}/box-${version}.phar";
+        sha256 = "1zmxdadrv0i2l8cz7xb38gnfmfyljpsaz2nnkjzqzksdmncbgd18";
+      };
 
-  ast = buildPecl {
-    version = "1.0.5";
-    pname = "ast";
-
-    sha256 = "16c5isldm4csjbcvz1qk2mmrhgvh24sxsp6w6f5a37xpa3vciawp";
-  };
+      phases = [ "installPhase" ];
+      buildInputs = [ pkgs.makeWrapper ];
 
-  box = mkDerivation rec {
-    version = "2.7.5";
-    pname = "box";
-
-    src = pkgs.fetchurl {
-      url = "https://github.com/box-project/box2/releases/download/${version}/box-${version}.phar";
-      sha256 = "1zmxdadrv0i2l8cz7xb38gnfmfyljpsaz2nnkjzqzksdmncbgd18";
-    };
-
-    phases = [ "installPhase" ];
-    buildInputs = [ pkgs.makeWrapper ];
-
-    installPhase = ''
-      mkdir -p $out/bin
-      install -D $src $out/libexec/box/box.phar
-      makeWrapper ${php}/bin/php $out/bin/box \
-        --add-flags "-d phar.readonly=0 $out/libexec/box/box.phar"
-    '';
+      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"
+      '';
 
-    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 ];
+      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 ];
+      };
     };
-  };
 
-  composer = mkDerivation rec {
-    version = "1.9.3";
-    pname = "composer";
+    composer = mkDerivation rec {
+      version = "1.9.3";
+      pname = "composer";
 
-    src = pkgs.fetchurl {
-      url = "https://getcomposer.org/download/${version}/composer.phar";
-      sha256 = "VRZVwvyB9BBlCPQrvEsk6r00sCKxO8Hn2WQr9IPQp9Q=";
-    };
+      src = pkgs.fetchurl {
+        url = "https://getcomposer.org/download/${version}/composer.phar";
+        sha256 = "VRZVwvyB9BBlCPQrvEsk6r00sCKxO8Hn2WQr9IPQp9Q=";
+      };
 
-    dontUnpack = true;
+      dontUnpack = true;
 
-    nativeBuildInputs = [ pkgs.makeWrapper ];
+      nativeBuildInputs = [ pkgs.makeWrapper ];
 
-    installPhase = ''
-      mkdir -p $out/bin
-      install -D $src $out/libexec/composer/composer.phar
-      makeWrapper ${php}/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 $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 ]}
+      '';
 
-    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 = "Dependency Manager for PHP";
+        license = licenses.mit;
+        homepage = https://getcomposer.org/;
+        maintainers = with maintainers; [ globin offline ];
+      };
     };
-  };
-
-  couchbase = buildPecl rec {
-    version = "2.6.1";
-    pname = "couchbase";
-
-    buildInputs = [ pkgs.libcouchbase pkgs.zlib igbinary pcs ];
-
-    src = pkgs.fetchFromGitHub {
-      owner = "couchbase";
-      repo = "php-couchbase";
-      rev = "v${version}";
-      sha256 = "0jdzgcvab1vpxai23brmmvizjjq2d2dik9aklz6bzspfb512qjd6";
-    };
-
-    configureFlags = [ "--with-couchbase" ];
-
-    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 "${igbinary.dev}/include/ext/igbinary/igbinary.h"; then
-        +    igbinary_inc_path="${igbinary.dev}/include"
-           fi
-           if test "$igbinary_inc_path" = ""; then
-             AC_MSG_WARN([Cannot find igbinary.h])
-      '')
-    ];
 
-    meta.broken = isPhp74; # Build error
-  };
+    php-cs-fixer = mkDerivation rec {
+      version = "2.16.1";
+      pname = "php-cs-fixer";
 
-  event = buildPecl {
-    version = "2.5.3";
-    pname = "event";
+      src = pkgs.fetchurl {
+        url = "https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v${version}/php-cs-fixer.phar";
+        sha256 = "1dq1nhy666zg6d4fkfsjwhj1vwh1ncap2c9ljplxv98a9mm6fk68";
+      };
 
-    sha256 = "12liry5ldvgwp1v1a6zgfq8w6iyyxmsdj4c71bp157nnf58cb8hb";
+      phases = [ "installPhase" ];
+      buildInputs = [ pkgs.makeWrapper ];
 
-    configureFlags = [
-      "--with-event-libevent-dir=${pkgs.libevent.dev}"
-      "--with-event-core"
-      "--with-event-extra"
-      "--with-event-pthreads"
-    ];
-    nativeBuildInputs = [ pkgs.pkgconfig ];
-    buildInputs = with pkgs; [ openssl libevent ];
-
-    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/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"
       '';
-      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 = "A tool to automatically fix PHP coding standards issues";
+        license = licenses.mit;
+        homepage = http://cs.sensiolabs.org/;
+        maintainers = with maintainers; [ jtojnar ];
+      };
+    };
 
-    configureFlags = [ "--enable-igbinary" ];
-    makeFlags = [ "phpincludedir=$(dev)/include" ];
-    outputs = [ "out" "dev" ];
-  };
+    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
+      '';
 
-  imagick = buildPecl {
-    version = "3.4.4";
-    pname = "imagick";
+      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"
+      '';
 
-    sha256 = "0xvhaqny1v796ywx83w7jyjyd0nrxkxf34w9zi8qc8aw8qbammcd";
+      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 ];
+      };
+    };
 
-    configureFlags = [ "--with-imagick=${pkgs.imagemagick.dev}" ];
-    nativeBuildInputs = [ pkgs.pkgconfig ];
-    buildInputs = [ (if isPhp73 then pkgs.pcre2 else pkgs.pcre) ];
-  };
+    phpcbf = mkDerivation rec {
+      version = "3.5.3";
+      pname = "phpcbf";
 
-  mailparse = buildPecl {
-    version = "3.0.3";
-    pname = "mailparse";
+      src = pkgs.fetchurl {
+        url = "https://github.com/squizlabs/PHP_CodeSniffer/releases/download/${version}/phpcbf.phar";
+        sha256 = "1mrsf9p6p64pyqyylnlxb2b7cirdfccch83g7yhfnka3znffq86v";
+      };
 
-    sha256 = "00nk14jbdbln93mx3ag691avc11ff94hkadrcv5pn51c6ihsxbmz";
-  };
+      phases = [ "installPhase" ];
+      nativeBuildInputs = [ pkgs.makeWrapper ];
 
-  maxminddb = buildPecl rec {
-    pname = "maxminddb";
-    version = "1.6.0";
+      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"
+      '';
 
-    src = pkgs.fetchFromGitHub {
-      owner = "maxmind";
-      repo = "MaxMind-DB-Reader-php";
-      rev = "v${version}";
-      sha256 = "0sa943ij9pgz55aik93lllb8lh063bvr66ibn77p3y3p41vdiabz";
+      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 ];
+      };
     };
 
-    buildInputs = [ pkgs.libmaxminddb ];
-    sourceRoot = "source/ext";
+    phpcs = mkDerivation rec {
+      version = "3.5.3";
+      pname = "phpcs";
 
-    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 ];
-    };
-  };
+      src = pkgs.fetchurl {
+        url = "https://github.com/squizlabs/PHP_CodeSniffer/releases/download/${version}/phpcs.phar";
+        sha256 = "0y4nhsifj4pdmf5g1nnm4951yjgiqswyz7wmjxx6kqiqc7chlkml";
+      };
 
-  memcached = buildPecl rec {
-    version = "3.1.5";
-    pname = "memcached";
+      phases = [ "installPhase" ];
+      buildInputs = [ pkgs.makeWrapper ];
 
-    src = fetchgit {
-      url = "https://github.com/php-memcached-dev/php-memcached";
-      rev = "v${version}";
-      sha256 = "01mbh2m3kfbdvih3c8g3g9h4vdd80r0i9g2z8b3lx3mi8mmcj380";
-    };
+      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"
+      '';
 
-    configureFlags = [
-      "--with-zlib-dir=${pkgs.zlib.dev}"
-      "--with-libmemcached-dir=${pkgs.libmemcached}"
-    ];
+      meta = with pkgs.lib; {
+        description = "PHP coding standard tool";
+        license = licenses.bsd3;
+        homepage = https://squizlabs.github.io/PHP_CodeSniffer/;
+        maintainers = with maintainers; [ javaguirre etu ];
+      };
+    };
 
-    nativeBuildInputs = [ pkgs.pkgconfig ];
-    buildInputs = with pkgs; [ cyrus_sasl zlib ];
-  };
+    phpstan = mkDerivation rec {
+      version = "0.12.14";
+      pname = "phpstan";
 
-  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;
-  };
+      src = pkgs.fetchurl {
+        url = "https://github.com/phpstan/phpstan/releases/download/${version}/phpstan.phar";
+        sha256 = "JAq1/+bVhTgKRR7oFusqZ/yBOYewaOM38ZoiCjirsTg=";
+      };
 
-  oci8 = buildPecl {
-    version = "2.2.0";
-    pname = "oci8";
+      phases = [ "installPhase" ];
+      nativeBuildInputs = [ pkgs.makeWrapper ];
 
-    sha256 = "0jhivxj1nkkza4h23z33y7xhffii60d7dr51h1czjk10qywl7pyd";
-    buildInputs = [ pkgs.oracle-instantclient ];
-    configureFlags = [ "--with-oci8=shared,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"
+      '';
 
-    postPatch = ''
-      sed -i -e 's|OCISDKMANINC=`.*$|OCISDKMANINC="${pkgs.oracle-instantclient.dev}/include"|' config.m4
-    '';
-  };
+      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 ];
+      };
+    };
 
-  pcov = buildPecl {
-    version = "1.0.6";
-    pname = "pcov";
+    psalm = mkDerivation rec {
+      version = "3.9.3";
+      pname = "psalm";
 
-    sha256 = "1psfwscrc025z8mziq69pcx60k4fbkqa5g2ia8lplb94mmarj0v1";
+      src = pkgs.fetchurl {
+        url = "https://github.com/vimeo/psalm/releases/download/${version}/psalm.phar";
+        sha256 = "KHm2n06y/yxN5B2rCVxT5ja7HxkyxAMsjZ5HLb3xr4M=";
+      };
 
-    buildInputs = [ (if isPhp73 then pkgs.pcre2 else pkgs.pcre) ];
-  };
+      phases = [ "installPhase" ];
+      nativeBuildInputs = [ pkgs.makeWrapper ];
 
-  pcs = buildPecl {
-    version = "1.3.3";
-    pname = "pcs";
+      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"
+      '';
 
-    sha256 = "0d4p1gpl8gkzdiv860qzxfz250ryf0wmjgyc8qcaaqgkdyh5jy5p";
+      meta = with pkgs.lib; {
+        description = "A static analysis tool for finding errors in PHP applications";
+        license = licenses.mit;
+        homepage = https://github.com/vimeo/psalm;
+      };
+    };
 
-    meta.broken = isPhp74; # Build error
-  };
+    psysh = mkDerivation rec {
+      version = "0.9.12";
+      pname = "psysh";
 
-  pdo_oci = buildPecl rec {
-    inherit (php) src version;
+      src = pkgs.fetchurl {
+        url = "https://github.com/bobthecow/psysh/releases/download/v${version}/psysh-v${version}.tar.gz";
+        sha256 = "0bzmc94li481xk81gv460ipq9zl03skbnq8m3rnw34i2c04hxczc";
+      };
 
-    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
+        tar -xzf $src -C $out/bin
+        chmod +x $out/bin/psysh
+        wrapProgram $out/bin/psysh
+      '';
 
-    postPatch = ''
-      sed -i -e 's|OCISDKMANINC=`.*$|OCISDKMANINC="${pkgs.oracle-instantclient.dev}/include"|' config.m4
-    '';
+      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 ];
+      };
+    };
   };
 
-  pdo_sqlsrv = buildPecl {
-    version = "5.8.0";
-    pname = "pdo_sqlsrv";
 
-    sha256 = "0z4vbyd851b4jr6p69l2ylk91iihndsm2qjb429pxcv8g6dqzqll";
 
-    buildInputs = [ pkgs.unixODBC ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.libiconv ];
-  };
+  # This is a set of PHP extensions meant to be used in php.buildEnv
+  # or php.withExtensions to extend the functionality of the PHP
+  # interpreter.
+  extensions = {
+    apcu = buildPecl {
+      version = "5.1.18";
+      pname = "apcu";
 
-  php-cs-fixer = mkDerivation rec {
-    version = "2.16.1";
-    pname = "php-cs-fixer";
+      sha256 = "0ayykd4hfvdzk7qnr5k6yq5scwf6rb2i05xscfv76q5dmkkynvfl";
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v${version}/php-cs-fixer.phar";
-      sha256 = "1dq1nhy666zg6d4fkfsjwhj1vwh1ncap2c9ljplxv98a9mm6fk68";
+      buildInputs = [ 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/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 = "0ma00syhk2ps9k9p02jz7rii6x3i2p986il23703zz5npd6y9n20";
 
-    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 ];
+      buildInputs = [
+        php.extensions.apcu
+        pcre'
+      ];
     };
-  };
 
-  php-parallel-lint = mkDerivation rec {
-    version = "1.0.0";
-    pname = "php-parallel-lint";
+    ast = buildPecl {
+      version = "1.0.5";
+      pname = "ast";
 
-    src = pkgs.fetchFromGitHub {
-      owner = "JakubOnderka";
-      repo = "PHP-Parallel-Lint";
-      rev = "v${version}";
-      sha256 = "16nv8yyk2z3l213dg067l6di4pigg5rd8yswr5xgd18jwbys2vnw";
+      sha256 = "16c5isldm4csjbcvz1qk2mmrhgvh24sxsp6w6f5a37xpa3vciawp";
     };
 
-    buildInputs = [ pkgs.makeWrapper composer box ];
+    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
+    };
 
-    buildPhase = ''
-      composer dump-autoload
-      box build
-    '';
+    event = buildPecl {
+      version = "2.5.3";
+      pname = "event";
 
-    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 ];
-    };
-  };
+      sha256 = "12liry5ldvgwp1v1a6zgfq8w6iyyxmsdj4c71bp157nnf58cb8hb";
 
-  php_excel = buildPecl rec {
-    version = "1.0.2";
-    pname = "php_excel";
-    phpVersion = "php7";
+      configureFlags = [
+        "--with-event-libevent-dir=${pkgs.libevent.dev}"
+        "--with-event-core"
+        "--with-event-extra"
+        "--with-event-pthreads"
+      ];
 
-    buildInputs = [ pkgs.libxl ];
+      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/iliaal/php_excel/releases/download/Excel-1.0.2-PHP7/excel-${version}-${phpVersion}.tgz";
-      sha256 = "0dpvih9gpiyh1ml22zi7hi6kslkilzby00z1p8x248idylldzs2n";
+      nativeBuildInputs = [ pkgs.pkgconfig ];
+      buildInputs = with pkgs; [ openssl libevent ];
+      internalDeps = [ php.extensions.sockets ];
+
+      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/";
+      };
     };
 
-    configureFlags = [ "--with-excel" "--with-libxl-incdir=${pkgs.libxl}/include_c" "--with-libxl-libdir=${pkgs.libxl}/lib" ];
-    meta.broken = true;
-  };
+    igbinary = buildPecl {
+      version = "3.0.1";
+      pname = "igbinary";
 
-  phpcbf = mkDerivation rec {
-    version = "3.5.3";
-    pname = "phpcbf";
+      sha256 = "1w8jmf1qpggdvq0ndfi86n7i7cqgh1s8q6hys2lijvi37rzn0nar";
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/squizlabs/PHP_CodeSniffer/releases/download/${version}/phpcbf.phar";
-      sha256 = "1mrsf9p6p64pyqyylnlxb2b7cirdfccch83g7yhfnka3znffq86v";
+      configureFlags = [ "--enable-igbinary" ];
+      makeFlags = [ "phpincludedir=$(dev)/include" ];
+      outputs = [ "out" "dev" ];
     };
 
-    phases = [ "installPhase" ];
-    nativeBuildInputs = [ pkgs.makeWrapper ];
+    imagick = buildPecl {
+      version = "3.4.4";
+      pname = "imagick";
 
-    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 = "0xvhaqny1v796ywx83w7jyjyd0nrxkxf34w9zi8qc8aw8qbammcd";
 
-    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-imagick=${pkgs.imagemagick.dev}" ];
+      nativeBuildInputs = [ pkgs.pkgconfig ];
+      buildInputs = [ pcre' ];
     };
-  };
 
-  phpcs = mkDerivation rec {
-    version = "3.5.3";
-    pname = "phpcs";
+    mailparse = buildPecl {
+      version = "3.0.3";
+      pname = "mailparse";
+      sha256 = "00nk14jbdbln93mx3ag691avc11ff94hkadrcv5pn51c6ihsxbmz";
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/squizlabs/PHP_CodeSniffer/releases/download/${version}/phpcs.phar";
-      sha256 = "0y4nhsifj4pdmf5g1nnm4951yjgiqswyz7wmjxx6kqiqc7chlkml";
+      internalDeps = [ php.extensions.mbstring ];
+      postConfigure = ''
+        echo "#define HAVE_MBSTRING 1" >> config.h
+      '';
     };
 
-    phases = [ "installPhase" ];
-    buildInputs = [ pkgs.makeWrapper ];
-
-    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"
-    '';
-
-    meta = with pkgs.lib; {
-      description = "PHP coding standard tool";
-      license = licenses.bsd3;
-      homepage = https://squizlabs.github.io/PHP_CodeSniffer/;
-      maintainers = with maintainers; [ javaguirre etu ];
+    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 ];
+      };
     };
-  };
 
-  phpstan = mkDerivation rec {
-    version = "0.12.14";
-    pname = "phpstan";
+    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 ];
+    };
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/phpstan/phpstan/releases/download/${version}/phpstan.phar";
-      sha256 = "JAq1/+bVhTgKRR7oFusqZ/yBOYewaOM38ZoiCjirsTg=";
+    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/phpstan/phpstan.phar
-      makeWrapper ${php}/bin/php $out/bin/phpstan \
-        --add-flags "$out/libexec/phpstan/phpstan.phar"
-    '';
+      sha256 = "0jhivxj1nkkza4h23z33y7xhffii60d7dr51h1czjk10qywl7pyd";
+      buildInputs = [ pkgs.oracle-instantclient ];
+      configureFlags = [ "--with-oci8=shared,instantclient,${pkgs.oracle-instantclient.lib}/lib" ];
 
-    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.
+      postPatch = ''
+        sed -i -e 's|OCISDKMANINC=`.*$|OCISDKMANINC="${pkgs.oracle-instantclient.dev}/include"|' config.m4
       '';
-      license = licenses.mit;
-      homepage = "https://github.com/phpstan/phpstan";
-      maintainers = with maintainers; [ etu ];
     };
-  };
 
-  pinba = if isPhp73 then pinba73 else pinba7;
+    pcov = buildPecl {
+      version = "1.0.6";
+      pname = "pcov";
 
-  pinba7 = assert !isPhp73; buildPecl {
-    version = "1.1.1";
-    pname = "pinba";
+      sha256 = "1psfwscrc025z8mziq69pcx60k4fbkqa5g2ia8lplb94mmarj0v1";
 
-    src = pkgs.fetchFromGitHub {
-      owner = "tony2001";
-      repo = "pinba_extension";
-      rev = "RELEASE_1_1_1";
-      sha256 = "1kdp7vav0y315695vhm3xifgsh6h6y6pny70xw3iai461n58khj5";
+      buildInputs = [ pcre' ];
     };
 
-    meta = with pkgs.lib; {
-      description = "PHP extension for Pinba";
-      longDescription = ''
-        Pinba is a MySQL storage engine that acts as a realtime monitoring and
-        statistics server for PHP using MySQL as a read-only interface.
-      '';
-      homepage = "http://pinba.org/";
-    };
-  };
+    pcs = buildPecl {
+      version = "1.3.3";
+      pname = "pcs";
 
-  pinba73 = assert isPhp73; buildPecl {
-    version = "1.1.2-dev";
-    pname = "pinba";
+      sha256 = "0d4p1gpl8gkzdiv860qzxfz250ryf0wmjgyc8qcaaqgkdyh5jy5p";
 
-    src = pkgs.fetchFromGitHub {
-      owner = "tony2001";
-      repo = "pinba_extension";
-      rev = "edbc313f1b4fb8407bf7d5acf63fbb0359c7fb2e";
-      sha256 = "02sljqm6griw8ccqavl23f7w1hp2zflcv24lpf00k6pyrn9cwx80";
+      meta.broken = isPhp74; # Build error
     };
 
-    meta = with pkgs.lib; {
-      description = "PHP extension for Pinba";
-      longDescription = ''
-        Pinba is a MySQL storage engine that acts as a realtime monitoring and
-        statistics server for PHP using MySQL as a read-only interface.
-      '';
-      homepage = "http://pinba.org/";
-    };
-  };
+    pdo_oci = buildPecl rec {
+      inherit (php) src version;
 
-  protobuf = buildPecl {
-    version = "3.11.2";
-    pname = "protobuf";
+      pname = "pdo_oci";
+      sourceRoot = "php-${version}/ext/pdo_oci";
 
-    sha256 = "0bhdykdyk58ywqj940zb7jyvrlgdr6hdb4s8kn79fz3p0i79l9hz";
+      buildInputs = [ pkgs.oracle-instantclient ];
+      configureFlags = [ "--with-pdo-oci=instantclient,${pkgs.oracle-instantclient.lib}/lib" ];
 
-    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/";
+      postPatch = ''
+      sed -i -e 's|OCISDKMANINC=`.*$|OCISDKMANINC="${pkgs.oracle-instantclient.dev}/include"|' config.m4
+    '';
     };
-  };
 
-  psalm = mkDerivation rec {
-    version = "3.9.3";
-    pname = "psalm";
+    pdo_sqlsrv = buildPecl {
+      version = "5.8.0";
+      pname = "pdo_sqlsrv";
 
-    src = pkgs.fetchurl {
-      url = "https://github.com/vimeo/psalm/releases/download/${version}/psalm.phar";
-      sha256 = "KHm2n06y/yxN5B2rCVxT5ja7HxkyxAMsjZ5HLb3xr4M=";
-    };
+      sha256 = "0z4vbyd851b4jr6p69l2ylk91iihndsm2qjb429pxcv8g6dqzqll";
 
-    phases = [ "installPhase" ];
-    nativeBuildInputs = [ pkgs.makeWrapper ];
+      internalDeps = [ php.extensions.pdo ];
 
-    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;
+      buildInputs = [ pkgs.unixODBC ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.libiconv ];
     };
-  };
-
-  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";
-    };
+    php_excel = buildPecl rec {
+      version = "1.0.2";
+      pname = "php_excel";
+      phpVersion = "php7";
 
-    phases = [ "installPhase" ];
-    nativeBuildInputs = [ pkgs.makeWrapper ];
+      buildInputs = [ pkgs.libxl ];
 
-    installPhase = ''
-      mkdir -p $out/bin
-      tar -xzf $src -C $out/bin
-      chmod +x $out/bin/psysh
-      wrapProgram $out/bin/psysh
-    '';
+      src = pkgs.fetchurl {
+        url = "https://github.com/iliaal/php_excel/releases/download/Excel-1.0.2-PHP7/excel-${version}-${phpVersion}.tgz";
+        sha256 = "0dpvih9gpiyh1ml22zi7hi6kslkilzby00z1p8x248idylldzs2n";
+      };
 
-    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 ];
+      configureFlags = [ "--with-excel" "--with-libxl-incdir=${pkgs.libxl}/include_c" "--with-libxl-libdir=${pkgs.libxl}/lib" ];
     };
-  };
 
-  pthreads = if isPhp73 then pthreads32-dev else pthreads32;
+    pinba = let
+      version = if isPhp73 then "1.1.2-dev" else "1.1.1";
+      src = pkgs.fetchFromGitHub ({
+        owner = "tony2001";
+        repo = "pinba_extension";
+      } // (if (isPhp73) then {
+        rev = "edbc313f1b4fb8407bf7d5acf63fbb0359c7fb2e";
+        sha256 = "02sljqm6griw8ccqavl23f7w1hp2zflcv24lpf00k6pyrn9cwx80";
+      } else {
+        rev = "RELEASE_1_1_1";
+        sha256 = "1kdp7vav0y315695vhm3xifgsh6h6y6pny70xw3iai461n58khj5";
+      }));
+    in buildPecl {
+      pname = "pinba";
+      inherit version src;
+
+      meta = with pkgs.lib; {
+        description = "PHP extension for Pinba";
+        longDescription = ''
+          Pinba is a MySQL storage engine that acts as a realtime monitoring and
+          statistics server for PHP using MySQL as a read-only interface.
+        '';
+        homepage = "http://pinba.org/";
+      };
+    };
 
-  pthreads32 = assert (pkgs.config.php.zts or false); assert !isPhp73; buildPecl rec {
-    version = "3.2.0";
-    pname = "pthreads";
+    protobuf = buildPecl {
+      version = "3.11.2";
+      pname = "protobuf";
 
-    src = pkgs.fetchFromGitHub {
-      owner = "krakjoe";
-      repo = "pthreads";
-      rev = "v${version}";
-      sha256 = "17hypm75d4w7lvz96jb7s0s87018yzmmap0l125d5fd7abnhzfvv";
-    };
+      sha256 = "0bhdykdyk58ywqj940zb7jyvrlgdr6hdb4s8kn79fz3p0i79l9hz";
 
-    buildInputs = with pkgs; [ pcre.dev ];
-  };
+      buildInputs = with pkgs; [ pcre' ];
 
-  pthreads32-dev = assert (pkgs.config.php.zts or false); assert isPhp73; buildPecl {
-    version = "3.2.0-dev";
-    pname = "pthreads";
+      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/";
+      };
+    };
 
-    src = pkgs.fetchFromGitHub {
-      owner = "krakjoe";
-      repo = "pthreads";
-      rev = "4d1c2483ceb459ea4284db4eb06646d5715e7154";
-      sha256 = "07kdxypy0bgggrfav2h1ccbv67lllbvpa3s3zsaqci0gq4fyi830";
+    pthreads = let
+      version = "3.2.0";
+      src = pkgs.fetchFromGitHub ({
+        owner = "krakjoe";
+        repo = "pthreads";
+      } // (if (isPhp73) then {
+        rev = "4d1c2483ceb459ea4284db4eb06646d5715e7154";
+        sha256 = "07kdxypy0bgggrfav2h1ccbv67lllbvpa3s3zsaqci0gq4fyi830";
+      } else {
+        rev = "v3.2.0";
+        sha256 = "17hypm75d4w7lvz96jb7s0s87018yzmmap0l125d5fd7abnhzfvv";
+      }));
+    in buildPecl {
+      pname = "pthreads";
+      inherit version src;
+
+      buildInputs = [ pcre'.dev ];
+
+      meta.broken = isPhp74;
     };
 
-    buildInputs = with pkgs; [ pcre2.dev ];
-  };
+    redis = buildPecl {
+      version = "5.1.1";
+      pname = "redis";
 
-  redis = buildPecl {
-    version = "5.1.1";
-    pname = "redis";
+      sha256 = "1041zv91fkda73w4c3pj6zdvwjgb3q7mxg6mwnq9gisl80mrs732";
 
-    sha256 = "1041zv91fkda73w4c3pj6zdvwjgb3q7mxg6mwnq9gisl80mrs732";
-  };
+      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 = assert !isPhp73; 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;
-  };
+      zendExtension = true;
+    };
 
-  yaml = buildPecl {
-    version = "2.0.4";
-    pname = "yaml";
+    yaml = buildPecl {
+      version = "2.0.4";
+      pname = "yaml";
 
-    sha256 = "1036zhc5yskdfymyk8jhwc34kvkvsn5kaf50336153v4dqwb11lp";
+      sha256 = "1036zhc5yskdfymyk8jhwc34kvkvsn5kaf50336153v4dqwb11lp";
 
-    configureFlags = [
-      "--with-yaml=${pkgs.libyaml}"
-    ];
+      configureFlags = [
+        "--with-yaml=${pkgs.libyaml}"
+      ];
 
-    nativeBuildInputs = [ pkgs.pkgconfig ];
-  };
+      nativeBuildInputs = [ pkgs.pkgconfig ];
+    };
 
-  zmq = assert !isPhp73; buildPecl {
-    version = "1.1.3";
-    pname = "zmq";
+    zmq = buildPecl {
+      version = "1.1.3";
+      pname = "zmq";
 
-    sha256 = "1kj487vllqj9720vlhfsmv32hs2dy2agp6176mav6ldx31c3g4n4";
+      sha256 = "1kj487vllqj9720vlhfsmv32hs2dy2agp6176mav6ldx31c3g4n4";
 
-    configureFlags = [
-      "--with-zmq=${pkgs.zeromq}"
-    ];
+      configureFlags = [
+        "--with-zmq=${pkgs.zeromq}"
+      ];
 
-    nativeBuildInputs = [ pkgs.pkgconfig ];
-  };
+      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
@@ -709,39 +736,67 @@ let
     mkExtension = {
       name
       , configureFlags ? [ "--enable-${name}" ]
+      , internalDeps ? []
+      , postPhpize ? ""
       , buildInputs ? []
       , zendExtension ? false
+      , doCheck ? true
       , ...
-    }: stdenv.mkDerivation {
-      pname = "php-ext-${name}";
+    }@args: stdenv.mkDerivation ((builtins.removeAttrs args [ "name" ]) // {
+      pname = "php-${name}";
+      extensionName = name;
 
       inherit (php) version src;
       sourceRoot = "php-${php.version}/ext/${name}";
 
       enableParallelBuilding = true;
       nativeBuildInputs = [ php autoconf pkgconfig re2c ];
-      inherit configureFlags buildInputs zendExtension;
-
-      preConfigure = "phpize";
-
+      inherit configureFlags internalDeps buildInputs
+        zendExtension doCheck;
+
+      preConfigure = ''
+        nullglobRestore=$(shopt -p nullglob)
+        shopt -u nullglob   # To make ?-globbing work
+
+        # Some extensions have a config0.m4 or config9.m4
+        if [ -f config?.m4 ]; then
+          mv config?.m4 config.m4
+        fi
+
+        $nullglobRestore
+        phpize
+        ${postPhpize}
+        ${lib.concatMapStringsSep "\n"
+          (dep: "mkdir -p ext; ln -s ${dep.dev}/include ext/${dep.extensionName}")
+          internalDeps}
+      '';
+      checkPhase = "echo n | make test";
+      outputs = [ "out" "dev" ];
       installPhase = ''
         mkdir -p $out/lib/php/extensions
-        cp modules/${name}.so $out/lib/php/extensions/ext-${name}.so
+        cp modules/${name}.so $out/lib/php/extensions/${name}.so
+        mkdir -p $dev/include
+        ${rsync}/bin/rsync -r --filter="+ */" \
+                              --filter="+ *.h" \
+                              --filter="- *" \
+                              --prune-empty-dirs \
+                              . $dev/include/
       '';
-    };
+    });
 
     # This list contains build instructions for different modules that one may
     # 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"; }
       { name = "ctype"; }
-      { name = "curl"; buildInputs = [ curl ]; configureFlags = [ "--with-curl=${curl.dev}" ]; }
+      { name = "curl";
+        buildInputs = [ curl ];
+        configureFlags = [ "--with-curl=${curl.dev}" ];
+        doCheck = false; }
       { name = "dba"; }
       { name = "dom";
         buildInputs = [ libxml2 ];
@@ -752,8 +807,9 @@ let
         buildInputs = [ enchant1 ];
         configureFlags = [ "--with-enchant=${enchant1}" ];
         # enchant1 doesn't build on darwin.
-        enable = (!stdenv.isDarwin); }
-      { name = "exif"; }
+        enable = (!stdenv.isDarwin);
+        doCheck = false; }
+      { name = "exif"; doCheck = false; }
       { name = "ffi"; buildInputs = [ libffi ]; enable = lib.versionAtLeast php.version "7.4"; }
       { name = "fileinfo"; buildInputs = [ pcre' ]; }
       { name = "filter"; buildInputs = [ pcre' ]; }
@@ -765,6 +821,7 @@ let
           "--with-external-gd=${gd.dev}"
           "--enable-gd-jis-conv"
         ];
+        doCheck = false;
         enable = lib.versionAtLeast php.version "7.4"; }
       { name = "gd";
         buildInputs = [ zlib gd libXpm ];
@@ -778,21 +835,22 @@ let
           "--with-zlib-dir=${zlib.dev}"
           "--enable-gd-jis-conv"
         ];
+        doCheck = false;
         enable = lib.versionOlder php.version "7.4"; }
-      ## gettext (7.2, 7.3, 7.4) -- configure: error: Cannot locate header file libintl.h
-      #{ name = "gettext";
-      #  buildInputs = [ gettext ];
-      #  configureFlags = "--with-gettext=${gettext}"; }
+      { name = "gettext";
+        buildInputs = [ gettext ];
+        postPhpize = ''substituteInPlace configure --replace 'as_fn_error $? "Cannot locate header file libintl.h" "$LINENO" 5' ':' '';
+        configureFlags = "--with-gettext=${gettext}"; }
       { name = "gmp";
-        buildInputs = [ gmp5 ];
-        configureFlags = [ "--with-gmp=${gmp5.dev}" ];
-        # gmp5 doesn't build on darwin.
-        enable = (!stdenv.isDarwin); }
+        buildInputs = [ gmp ];
+        configureFlags = [ "--with-gmp=${gmp.dev}" ]; }
       { name = "hash"; enable = lib.versionOlder php.version "7.4"; }
-      { name = "iconv"; configureFlags = if stdenv.isDarwin then
+      { name = "iconv";
+        configureFlags = if stdenv.isDarwin then
                            [ "--with-iconv=${libiconv}" ]
                          else
-                           [ "--with-iconv" ]; }
+                           [ "--with-iconv" ];
+        doCheck = false; }
       { name = "imap";
         buildInputs = [ uwimap openssl pam pcre' ];
         configureFlags = [ "--with-imap=${uwimap}" "--with-imap-ssl" ];
@@ -808,36 +866,110 @@ let
           "LDAP_DIR=${openldap.dev}"
           "LDAP_INCDIR=${openldap.dev}/include"
           "LDAP_LIBDIR=${openldap.out}/lib"
-        ] ++ lib.optional stdenv.isLinux "--with-ldap-sasl=${cyrus_sasl.dev}"; }
-      { name = "mbstring"; buildInputs = [ oniguruma ]; }
-      { name = "mysqli"; configureFlags = [ "--with-mysqli=mysqlnd" "--with-mysql-sock=/run/mysqld/mysqld.sock" ]; }
+        ] ++ lib.optional stdenv.isLinux "--with-ldap-sasl=${cyrus_sasl.dev}";
+        doCheck = false; }
+      { name = "mbstring"; buildInputs = [ oniguruma ]; doCheck = false; }
+      { name = "mysqli";
+        internalDeps = [ php.extensions.mysqlnd ];
+        configureFlags = [ "--with-mysqli=mysqlnd" "--with-mysql-sock=/run/mysqld/mysqld.sock" ];
+        doCheck = false; }
+      { name = "mysqlnd";
+        buildInputs = [ zlib openssl ];
+        # The configure script doesn't correctly add library link
+        # flags, so we add them to the variable used by the Makefile
+        # when linking.
+        MYSQLND_SHARED_LIBADD = "-lssl -lcrypto -lz";
+        # The configure script builds a config.h which is never
+        # included. Let's include it in the main header file
+        # included by all .c-files.
+        patches = [
+          (pkgs.writeText "mysqlnd_config.patch" ''
+            --- a/mysqlnd.h
+            +++ b/mysqlnd.h
+            @@ -1,3 +1,6 @@
+            +#ifdef HAVE_CONFIG_H
+            +#include "config.h"
+            +#endif
+             /*
+               +----------------------------------------------------------------------+
+               | Copyright (c) The PHP Group                                          |
+          '')
+        ];
+        postPhpize = lib.optionalString (lib.versionOlder php.version "7.4") ''
+          substituteInPlace configure --replace '$OPENSSL_LIBDIR' '${openssl}/lib' \
+                                      --replace '$OPENSSL_INCDIR' '${openssl.dev}/include'
+        ''; }
       # oci8 (7.4, 7.3, 7.2)
       # odbc (7.4, 7.3, 7.2)
-      { name = "opcache"; buildInputs = [ pcre' ]; zendExtension = true; }
+      { name = "opcache";
+        buildInputs = [ pcre' ];
+        # HAVE_OPCACHE_FILE_CACHE is defined in config.h, which is
+        # included from ZendAccelerator.h, but ZendAccelerator.h is
+        # included after the ifdef...
+        patches = lib.optional (lib.versionOlder php.version "7.4") [
+          (pkgs.writeText "zend_file_cache_config.patch" ''
+            --- a/zend_file_cache.c
+            +++ b/zend_file_cache.c
+            @@ -27,9 +27,9 @@
+             #include "ext/standard/md5.h"
+             #endif
+
+            +#include "ZendAccelerator.h"
+             #ifdef HAVE_OPCACHE_FILE_CACHE
+
+            -#include "ZendAccelerator.h"
+             #include "zend_file_cache.h"
+             #include "zend_shared_alloc.h"
+             #include "zend_accelerator_util_funcs.h"
+          '') ];
+        zendExtension = true;
+        doCheck = !(lib.versionOlder php.version "7.4"); }
+      { name = "openssl";
+        buildInputs = [ openssl ];
+        configureFlags = [ "--with-openssl" ];
+        doCheck = false; }
       { name = "pcntl"; }
-      { name = "pdo"; }
+      { name = "pdo"; doCheck = false; }
       { name = "pdo_dblib";
+        internalDeps = [ php.extensions.pdo ];
         configureFlags = [ "--with-pdo-dblib=${freetds}" ];
         # Doesn't seem to work on darwin.
-        enable = (!stdenv.isDarwin); }
+        enable = (!stdenv.isDarwin);
+        doCheck = false; }
       # pdo_firebird (7.4, 7.3, 7.2)
-      { name = "pdo_mysql"; configureFlags = [ "--with-pdo-mysql=mysqlnd" ]; }
+      { name = "pdo_mysql";
+        internalDeps = with php.extensions; [ pdo mysqlnd ];
+        configureFlags = [ "--with-pdo-mysql=mysqlnd" ];
+        doCheck = false; }
       # pdo_oci (7.4, 7.3, 7.2)
-      { name = "pdo_odbc"; configureFlags = [ "--with-pdo-odbc=unixODBC,${unixODBC}" ]; }
-      { name = "pdo_pgsql"; configureFlags = [ "--with-pdo-pgsql=${postgresql}" ]; }
-      { name = "pdo_sqlite"; buildInputs = [ sqlite ]; configureFlags = [ "--with-pdo-sqlite=${sqlite.dev}" ]; }
-      { name = "pgsql"; buildInputs = [ pcre' ]; configureFlags = [ "--with-pgsql=${postgresql}" ]; }
-      { name = "phar"; buildInputs = [ pcre' openssl ]; }
-      { name = "posix"; }
+      { name = "pdo_odbc";
+        internalDeps = [ php.extensions.pdo ];
+        configureFlags = [ "--with-pdo-odbc=unixODBC,${unixODBC}" ];
+        doCheck = false; }
+      { name = "pdo_pgsql";
+        internalDeps = [ php.extensions.pdo ];
+        configureFlags = [ "--with-pdo-pgsql=${postgresql}" ];
+        doCheck = false; }
+      { name = "pdo_sqlite";
+        internalDeps = [ php.extensions.pdo ];
+        buildInputs = [ sqlite ];
+        configureFlags = [ "--with-pdo-sqlite=${sqlite.dev}" ];
+        doCheck = false; }
+      { name = "pgsql";
+        buildInputs = [ pcre' ];
+        configureFlags = [ "--with-pgsql=${postgresql}" ];
+        doCheck = false; }
+      { name = "posix"; doCheck = false; }
       { name = "pspell"; configureFlags = [ "--with-pspell=${aspell}" ]; }
-      ## readline (7.4, 7.3, 7.2) -- configure: error: Please reinstall libedit - I cannot find readline.h
-      #{ name = "readline";
-      #  buildInputs = [ libedit readline ];
-      #  configureFlags = [ "--with-readline=${readline.dev}" ]; }
-      { name = "recode";
-        configureFlags = [ "--with-recode=${recode}" ];
-        # Removed in php 7.4.
-        enable = lib.versionOlder php.version "7.4"; }
+      { name = "readline";
+        buildInputs = [ libedit readline ];
+        configureFlags = [ "--with-readline=${readline.dev}" ];
+        postPhpize = lib.optionalString (lib.versionOlder php.version "7.4") ''
+          substituteInPlace configure --replace 'as_fn_error $? "Please reinstall libedit - I cannot find readline.h" "$LINENO" 5' ':'
+        '';
+        doCheck = false;
+      }
+      # recode (7.3, 7.2)
       { name = "session"; }
       { name = "shmop"; }
       { name = "simplexml";
@@ -849,21 +981,25 @@ let
         buildInputs = [ net-snmp openssl ];
         configureFlags = [ "--with-snmp" ];
         # net-snmp doesn't build on darwin.
-        enable = (!stdenv.isDarwin); }
+        enable = (!stdenv.isDarwin);
+        doCheck = false; }
       { name = "soap";
         buildInputs = [ libxml2 ];
         configureFlags = [ "--enable-soap" ]
           # Required to build on darwin.
-          ++ lib.optional (lib.versionOlder php.version "7.4") [ "--with-libxml-dir=${libxml2.dev}" ]; }
-      { name = "sockets"; }
+          ++ lib.optional (lib.versionOlder php.version "7.4") [ "--with-libxml-dir=${libxml2.dev}" ];
+        doCheck = false; }
+      { name = "sockets"; doCheck = false; }
       { name = "sodium"; buildInputs = [ libsodium ]; }
+      { name = "sqlite3"; buildInputs = [ sqlite ]; }
       { name = "sysvmsg"; }
       { name = "sysvsem"; }
       { name = "sysvshm"; }
-      { name = "tidy"; configureFlags = [ "--with-tidy=${html-tidy}" ]; }
+      { name = "tidy"; configureFlags = [ "--with-tidy=${html-tidy}" ]; doCheck = false; }
       { name = "tokenizer"; }
       { name = "wddx";
         buildInputs = [ libxml2 ];
+        internalDeps = [ php.extensions.session ];
         configureFlags = [ "--enable-wddx" "--with-libxml-dir=${libxml2.dev}" ];
         # Removed in php 7.4.
         enable = lib.versionOlder php.version "7.4"; }
@@ -871,7 +1007,8 @@ let
         buildInputs = [ libxml2 ];
         configureFlags = [ "--enable-xml" ]
           # Required to build on darwin.
-          ++ lib.optional (lib.versionOlder php.version "7.4") [ "--with-libxml-dir=${libxml2.dev}" ]; }
+          ++ lib.optional (lib.versionOlder php.version "7.4") [ "--with-libxml-dir=${libxml2.dev}" ];
+        doCheck = false; }
       { name = "xmlreader";
         buildInputs = [ libxml2 ];
         configureFlags = [ "--enable-xmlreader CFLAGS=-I../.." ]
@@ -887,12 +1024,21 @@ let
         configureFlags = [ "--enable-xmlwriter" ]
           # Required to build on darwin.
           ++ lib.optional (lib.versionOlder php.version "7.4") [ "--with-libxml-dir=${libxml2.dev}" ]; }
-      { name = "xsl"; buildInputs = [ libxslt libxml2 ]; configureFlags = [ "--with-xsl=${libxslt.dev}" ]; }
+      { name = "xsl";
+        buildInputs = [ libxslt libxml2 ];
+        doCheck = !(lib.versionOlder php.version "7.4");
+        configureFlags = [ "--with-xsl=${libxslt.dev}" ]; }
       { name = "zend_test"; }
-      { name = "zip"; buildInputs = [ libzip pcre' ];
+      { name = "zip";
+        buildInputs = [ libzip pcre' ];
         configureFlags = [ "--with-zip" ]
           ++ lib.optional (lib.versionOlder php.version "7.4") [ "--with-zlib-dir=${zlib.dev}" ]
-          ++ lib.optional (lib.versionOlder php.version "7.3") [ "--with-libzip" ]; }
+          ++ lib.optional (lib.versionOlder php.version "7.3") [ "--with-libzip" ];
+        doCheck = false; }
+      { name = "zlib";
+        buildInputs = [ zlib ];
+        configureFlags = [ "--with-zlib" ]
+          ++ lib.optional (lib.versionOlder php.version "7.4") [ "--with-zlib-dir=${zlib.dev}" ]; }
     ];
 
     # Convert the list of attrs:
@@ -909,5 +1055,5 @@ let
     }) (builtins.filter (i: i.enable or true) extensionData);
 
     # Produce the final attribute set of all extensions defined.
-  in builtins.listToAttrs namedExtensions;
-}; in self
+  in builtins.listToAttrs namedExtensions);
+}