Installing Homebrew PHP extensions with PECL

Recently the homebrew/php tap was deprecated in favour of PHP versions taken directly from homebrew/core. With this deprecation however, all versions with pre-built extensions were removed. In this guide we'll take a look at how we can compile and add these extensions ourselves.


Prerequisites

For this guide, we’ll assume you’re running a PHP version installed from homebrew/core. If you’re unsure, check what’s installed by running:

$ brew list | grep php

New versions would be listed as:

php ← the latest version
php@7.1
php@7.2

Old versions would be listed as:

php71
php72
php72-memcached
php72-opcache
[...]

If you haven’t made the switch, follow these excellent guides for removing and installing the right version(s).

Also make sure you have pkg-config and zlib installed. If these are missing, the extension will not be compiled properly.

$ brew install pkg-config zlib

Installing extensions

The preferred way to install extensions nowadays is through PECL. This can be accomplished with the pecl command.

Install

To install an extension, run the following command.

$ pecl install <extension>

This command will…

  • compile and install the extension in the PECL extension directory
  • add the extension to your currently active PHP configuration (php.ini)

It will not…

  • tell PHP about your PECL extension directory (one-time configuration)

Note: the install command might ask you for a few (path) settings, but usually you can safely accept the defaults and hit enter.


To verify the extension is correctly added in you PHP configuration, run php --ini and open it. The newly installed extension will be on top of the file if you didn’t have an existing extension entry before. Else it will be added below any previously added entry.

The extension is now installed and activated, but at this time PHP still can’t locate the compiled extension itself.

Configure the extension directory

To load extensions installed by PECL, we need to point the extension_dir in our php.ini to the extension directory created by PECL. This directory can be found by running:

$ pecl config-get ext_dir

Now uncomment and update the extension_dir in your php.ini:

extension_dir = /usr/local/lib/php/pecl/<php_api_version>

Verify

After installing an extension you should of course restart your webserver or PHP-FPM instance, depending on how you’re running PHP.

To verify the module is loaded on the CLI, run either:

$ php --info | grep <module>\\.
$ php --modules | grep <module>

If you’re running PHP-FPM, it’s likely the CLI version isn’t the same version as the one running your (web) application. If you want to be sure it’s loading properly, you could create an info.php file, and open it in the browser with these contents:

<?php phpinfo() ?>

Both should show some entries for the newly installed extension.


When running multiple PHP versions

There are two minor caveats to keep in mind when running multiple PHP versions, or switching to a new version.

Different extension directories

Every minor PHP version has its own API version. This means that PECL will have its own extension directory per minor PHP version (7.1, 7.2, 7.3, …). For example:

/usr/local/lib/php/pecl/20160303 ← 7.1
/usr/local/lib/php/pecl/20170718 ← 7.2
/usr/local/lib/php/pecl/20180731 ← 7.3

Make sure you don’t mix them up when adding them as the extension_dir in your php.ini. You can always check the current API version by running:

$ php -i | grep 'PHP API'

Compile for each API version

Furthermore, it’s required to compile extensions for every PHP API version. One might think we can cheat the system, and just compile extensions and point all PHP versions to that directory. Trying to do so will result in errors however.

The solution is to switch to the PHP version you want to use, and install the extension again. This will add it to the current version, and will install the compiled extension in the correct API version directory.


An example

As an example, we’ll install the Memcached PHP extension. We use this for communicating with the Memcached daemon, which is a memory caching system comparable to Redis.

Install

To compile the Memcached extension — not to be confused with the outdated Memcache one — we first need to install libmemcached:

$ brew install libmemcached

Compile and install the extension:

$ pecl install memcached

You can safely hit enter when the installation scripts asks you for paths and configuration options:

libmemcached directory [no] :
zlib directory [no] :
use system fastlz [no] :
...

Now you’ve installed the memcached extension, provided you’ve pointed your extension_dir to the right path, and restarted your web server or PHP-FPM daemon.

Verify

To verify the module is loaded, run:

$ php --info | grep memcached\\.

It should output a bunch of Memcached-related configuration entries.

Finally

Only thing left is getting the Memcached service itself up and running:

$ brew install memcached

To start the daemon, launch it with Homebrew Services:

$ brew services start memcached

This will start Memcached, and will also launch it when logging in. To have it run only once, launch it with run instead of start, or use the memcached command for more direct control.

You’re all set. Start caching 💪


Having trouble?

A few paths that might help when having trouble…

PHP installations

/usr/local/opt/php/<version>

PHP configurations

/usr/local/etc/php/<version>

PECL extension directories

/usr/local/lib/php/pecl/<version>

Updated on October 12, 2019: Fixed a few typos, updated with 7.3 examples, and add pkg-config and zlib prerequisites after a tip on Twitter.