3 ## User Guide {#ssec-php-user-guide}
5 ### Overview {#ssec-php-user-guide-overview}
7 Several versions of PHP are available on Nix, each of which having a
8 wide variety of extensions and libraries available.
10 The different versions of PHP that nixpkgs provides are located under
11 attributes named based on major and minor version number; e.g.,
14 Only versions of PHP that are supported by upstream for the entirety
15 of a given NixOS release will be included in that release of
16 NixOS. See [PHP Supported
17 Versions](https://www.php.net/supported-versions.php).
19 The attribute `php` refers to the version of PHP considered most
20 stable and thoroughly tested in nixpkgs for any given release of
21 NixOS - not necessarily the latest major release from upstream.
23 All available PHP attributes are wrappers around their respective
24 binary PHP package and provide commonly used extensions this way. The
25 real PHP 8.1 package, i.e. the unwrapped one, is available as
26 `php81.unwrapped`; see the next section for more details.
28 Interactive tools built on PHP are put in `php.packages`; composer is
29 for example available at `php.packages.composer`.
31 Most extensions that come with PHP, as well as some popular
32 third-party ones, are available in `php.extensions`; for example, the
33 opcache extension shipped with PHP is available at
34 `php.extensions.opcache` and the third-party ImageMagick extension at
35 `php.extensions.imagick`.
37 ### Installing PHP with extensions {#ssec-php-user-guide-installing-with-extensions}
39 A PHP package with specific extensions enabled can be built using
40 `php.withExtensions`. This is a function which accepts an anonymous
41 function as its only argument; the function should accept two named
42 parameters: `enabled` - a list of currently enabled extensions and
43 `all` - the set of all extensions, and return a list of wanted
44 extensions. For example, a PHP package with all default extensions and
48 php.withExtensions ({ enabled, all }:
49 enabled ++ [ all.imagick ])
52 To exclude some, but not all, of the default extensions, you can
53 filter the `enabled` list like this:
56 php.withExtensions ({ enabled, all }:
57 (lib.filter (e: e != php.extensions.opcache) enabled)
61 To build your list of extensions from the ground up, you can
65 php.withExtensions ({ all, ... }: with all; [ imagick opcache ])
68 `php.withExtensions` provides extensions by wrapping a minimal php
69 base package, providing a `php.ini` file listing all extensions to be
70 loaded. You can access this package through the `php.unwrapped`
71 attribute; useful if you, for example, need access to the `dev`
72 output. The generated `php.ini` file can be accessed through the
73 `php.phpIni` attribute.
75 If you want a PHP build with extra configuration in the `php.ini`
76 file, you can use `php.buildEnv`. This function takes two named and
77 optional parameters: `extensions` and `extraConfig`. `extensions`
78 takes an extension specification equivalent to that of
79 `php.withExtensions`, `extraConfig` a string of additional `php.ini`
80 configuration parameters. For example, a PHP package with the opcache
81 and ImageMagick extensions enabled, and `memory_limit` set to `256M`:
85 extensions = { all, ... }: with all; [ imagick opcache ];
86 extraConfig = "memory_limit=256M";
90 #### Example setup for `phpfpm` {#ssec-php-user-guide-installing-with-extensions-phpfpm}
92 You can use the previous examples in a `phpfpm` pool called `foo` as
97 myPhp = php.withExtensions ({ all, ... }: with all; [ imagick opcache ]);
99 services.phpfpm.pools."foo".phpPackage = myPhp;
105 myPhp = php.buildEnv {
106 extensions = { all, ... }: with all; [ imagick opcache ];
107 extraConfig = "memory_limit=256M";
110 services.phpfpm.pools."foo".phpPackage = myPhp;
114 #### Example usage with `nix-shell` {#ssec-php-user-guide-installing-with-extensions-nix-shell}
116 This brings up a temporary environment that contains a PHP interpreter
117 with the extensions `imagick` and `opcache` enabled:
120 nix-shell -p 'php.withExtensions ({ all, ... }: with all; [ imagick opcache ])'
123 ### Installing PHP packages with extensions {#ssec-php-user-guide-installing-packages-with-extensions}
125 All interactive tools use the PHP package you get them from, so all
126 packages at `php.packages.*` use the `php` package with its default
127 extensions. Sometimes this default set of extensions isn't enough and
128 you may want to extend it. A common case of this is the `composer`
129 package: a project may depend on certain extensions and `composer`
130 won't work with that project unless those extensions are loaded.
132 Example of building `composer` with additional extensions:
135 (php.withExtensions ({ all, enabled }:
136 enabled ++ (with all; [ imagick redis ]))
140 ### Overriding PHP packages {#ssec-php-user-guide-overriding-packages}
142 `php-packages.nix` form a scope, allowing us to override the packages defined
143 within. For example, to apply a patch to a `mysqlnd` extension, you can
144 pass an overlay-style function to `php`’s `packageOverrides` argument:
148 packageOverrides = final: prev: {
149 extensions = prev.extensions // {
150 mysqlnd = prev.extensions.mysqlnd.overrideAttrs (attrs: {
151 patches = attrs.patches or [] ++ [
160 ### Building PHP projects {#ssec-building-php-projects}
162 With [Composer](https://getcomposer.org/), you can effectively build PHP
163 projects by streamlining dependency management. As the de-facto standard
164 dependency manager for PHP, Composer enables you to declare and manage the
165 libraries your project relies on, ensuring a more organized and efficient
168 Composer is not a package manager in the same sense as `Yum` or `Apt` are. Yes,
169 it deals with "packages" or libraries, but it manages them on a per-project
170 basis, installing them in a directory (e.g. `vendor`) inside your project. By
171 default, it does not install anything globally. This idea is not new and
172 Composer is strongly inspired by node's `npm` and ruby's `bundler`.
174 Currently, there is no other PHP tool that offers the same functionality as
175 Composer. Consequently, incorporating a helper in Nix to facilitate building
176 such applications is a logical choice.
178 In a Composer project, dependencies are defined in a `composer.json` file,
179 while their specific versions are locked in a `composer.lock` file. Some
180 Composer-based projects opt to include this `composer.lock` file in their source
181 code, while others choose not to.
183 In Nix, there are multiple approaches to building a Composer-based project.
185 One such method is the `php.buildComposerProject` helper function, which serves
186 as a wrapper around `mkDerivation`.
188 Using this function, you can build a PHP project that includes both a
189 `composer.json` and `composer.lock` file. If the project specifies binaries
190 using the `bin` attribute in `composer.json`, these binaries will be
191 automatically linked and made accessible in the derivation. In this context,
192 "binaries" refer to PHP scripts that are intended to be executable.
194 To use the helper effectively, add the `vendorHash` attribute, which
195 enables the wrapper to handle the heavy lifting.
197 Internally, the helper operates in three stages:
199 1. It constructs a `composerRepository` attribute derivation by creating a
200 composer repository on the filesystem containing dependencies specified in
201 `composer.json`. This process uses the function
202 `php.mkComposerRepository` which in turn uses the
203 `php.composerHooks.composerRepositoryHook` hook. Internally this function uses
205 [Composer plugin](https://github.com/nix-community/composer-local-repo-plugin) to
206 generate the repository.
207 2. The resulting `composerRepository` derivation is then used by the
208 `php.composerHooks.composerInstallHook` hook, which is responsible for
209 creating the final `vendor` directory.
210 3. Any "binary" specified in the `composer.json` are linked and made accessible
213 As the autoloader optimization can be activated directly within the
214 `composer.json` file, we do not enable any autoloader optimization flags.
216 To customize the PHP version, you can specify the `php` attribute. Similarly, if
217 you wish to modify the Composer version, use the `composer` attribute. It is
218 important to note that both attributes should be of the `derivation` type.
220 Here's an example of working code example using `php.buildComposerProject`:
223 { php, fetchFromGitHub }:
225 php.buildComposerProject (finalAttrs: {
229 src = fetchFromGitHub {
232 rev = finalAttrs.version;
233 hash = "sha256-VcQRSss2dssfkJ+iUb5qT+FJ10GHiFDzySigcmuVI+8=";
236 # PHP version containing the `ast` extension enabled
238 extensions = ({ enabled, all }: enabled ++ (with all; [
243 # The composer vendor hash
244 vendorHash = "sha256-86s/F+/5cBAwBqZ2yaGRM5rTGLmou5//aLRK5SA0WiQ=";
246 # If the composer.lock file is missing from the repository, add it:
247 # composerLock = ./path/to/composer.lock;
251 In case the file `composer.lock` is missing from the repository, it is possible
252 to specify it using the `composerLock` attribute.
254 The other method is to use all these methods and hooks individually. This has
255 the advantage of building a PHP library within another derivation very easily
258 Here's a working code example to build a PHP library using `mkDerivation` and
259 separate functions and hooks:
262 { stdenvNoCC, fetchFromGitHub, php }:
264 stdenvNoCC.mkDerivation (finalAttrs:
266 src = fetchFromGitHub {
269 rev = finalAttrs.version;
270 hash = "sha256-VcQRSss2dssfkJ+iUb5qT+FJ10GHiFDzySigcmuVI+8=";
277 buildInputs = [ php ];
279 nativeBuildInputs = [
280 php.packages.composer
281 # This hook will use the attribute `composerRepository`
282 php.composerHooks.composerInstallHook
285 composerRepository = php.mkComposerRepository {
286 inherit (finalAttrs) pname version src;
287 composerNoDev = true;
288 composerNoPlugins = true;
289 composerNoScripts = true;
290 # Specifying a custom composer.lock since it is not present in the sources.
291 composerLock = ./composer.lock;
292 # The composer vendor hash
293 vendorHash = "sha256-86s/F+/5cBAwBqZ2yaGRM5rTGLmou5//aLRK5SA0WiQ=";