CLI tool
phpenv/phpenv avatar
phpenv/phpenv

phpenv: Per-Directory PHP Versions Without Docker

Simple PHP version management. Ever wondered why you can't run a PHP app on your own development machine?

1,870 stars143 forksShellMIT

At a glance

What is it?
phpenv is a shell-based version manager that switches PHP per project directory via a .php-version file. It is a direct port of rbenv's approach, and it works best for developers who compile PHP locally rather than use package managers.
Who is it for?
Adopt phpenv if you are a PHP developer who needs multiple PHP versions on one machine, especially if you already compile PHP with php-build or want per-directory version switching without containers. Avoid it if you prefer precompiled binaries or need Windows support, since phpenv is shell-based and expects a Unix-like environment.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 47 days ago.
What is it written in?
Mainly Shell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 14, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The Problem: PHP Apps That Need Different Interpreters

PHP developers often face a mismatch between the interpreter version on their machine and the one used in production. A project might require PHP 7.4 while another uses PHP 8.3. The typical workaround is to run multiple virtual machines or containers, which adds overhead. phpenv solves this by letting you switch PHP versions per directory, using a file named .php-version. It is designed for developers who build PHP from source, not for those who prefer precompiled packages. The README frames it as a tool for humans, inspired by rbenv and ruby-build. That lineage shows in its design: it is a thin layer of shell scripts that manage shims and version selection, while the actual compilation is delegated to a plugin called php-build.

How phpenv Selects a PHP Version

The mechanism is straightforward. When you install phpenv, it injects itself into your PATH. Any invocation of php, php-fpm, or other PHP executables first goes through phpenv's shims. phpenv then scans the current project directory for a .php-version file. If that file exists, it determines the version to use. phpenv looks up that version under ~/.phpenv/versions/, where each version is a directory containing its own binaries, libraries, and config files. For example, each version has its own php, php-fpm, pecl, and php.ini. When you run phpenv local 8.3.13, it writes that version into the .php-version file. When you cd into a different project with a different .php-version, phpenv switches to that version. This is exactly how rbenv works for Ruby, and it is a proven pattern. The README claims that phpenv transitions seamlessly between versions when you change directories, which is the core value proposition.

Installation and First Steps

The README offers two installation paths. The first uses Homebrew: brew install phpenv/tap/phpenv, then add eval "$(phpenv init -)" to your shell profile. The second is a manual GitHub checkout: clone the repository into ~/.phpenv, add ~/.phpenv/bin to your PATH, and add the same init line to your profile. After restarting your shell, you can install PHP versions by cloning php-build into the plugins directory: git clone https://github.com/php-build/php-build $(phpenv root)/plugins/php-build, then run phpenv install <php-version>. After installing a new PHP binary, you should run phpenv rehash to rebuild the shim binaries. The README explicitly says to do this any time you install a new PHP binary. This is a manual step that some users might forget, leading to confusing errors where the old version is still invoked.

Building PHP with php-build: Configuration Options

php-build is the plugin that actually compiles PHP. It uses a default set of configure options, plus per-version definitions. For example, the definition for PHP 7.4.13 specifies options specific to that release. You can customize the build by setting environment variables. The README mentions PHP_BUILD_CONFIGURE_OPTS for adding configure options and PHP_BUILD_INSTALL_EXTENSION for adding extensions. This is a key point: phpenv itself does not manage extensions or dependencies. You have to build them into each PHP version at compile time. That gives you full control, but it also means you are responsible for system libraries and build tools. The README also mentions that you can build PECL extensions into PHP or install them manually afterward. This is a trade-off: you get a tailored PHP, but the compilation time and maintenance burden are yours.

Webserver Integration: PHP-FPM and Apache

For web development, phpenv works with PHP-FPM. The README describes several ways to start php-fpm for a specific version: using an init script at ~/.phpenv/versions/$VERSION/etc/init.d/php-fpm, installing a systemd unit from the same directory, or running php-fpm manually. The default configuration file is ~/.phpenv/versions/$VERSION/etc/php-fpm.conf, which listens on localhost:9000. You can edit that file or supply a different one with the -y flag. For Apache, you can build the libphp.so module via php-build and place it under ~/.phpenv/versions/$VERSION/libexec. The README points to external wiki articles for Apache and NGINX configuration. This is a practical section, but it assumes you are comfortable managing system services. If you are not, you might prefer a containerized setup.

Limitations and Failure Modes

phpenv has several limitations that are clear from the README. First, it requires a Unix-like environment; there is no Windows support mentioned. Second, it depends on php-build for compilation, which means you need a full build toolchain and system libraries. If those are missing, builds will fail. Third, the .php-version file is per directory, but it does not handle global defaults or fallback versions as explicitly as some other tools. You must manually create the file or use phpenv local. Fourth, the shim mechanism can break if you forget to run phpenv rehash after installing a new version. The README warns about this, but it is an extra step that is easy to skip. Finally, phpenv does not manage PHP extensions at runtime; you have to compile them in or use PECL manually. This makes it a poor fit for users who want a quick, package-manager-like experience.

Alternatives: Docker and System PHP

The most common alternative is Docker. With Docker, you run a PHP container per project, each with its own image and version. The difference in approach is fundamental: Docker isolates the entire environment, including extensions and system libraries, without modifying your host PATH. phpenv, in contrast, uses shims to intercept PHP calls and switch versions on the fly. Docker is heavier and requires container orchestration, but it avoids the need to compile PHP from source. Another alternative is to use the system PHP package, but that gives you only one version, which is not enough for testing multiple releases. The README does not mention these alternatives, but the design choices make the comparison clear. If you need to test an app against several PHP versions quickly, phpenv is lighter than spinning up multiple containers, but it requires more setup per version.

Maintenance and Upgrade Cost

Upgrading phpenv is simple: because it is a git checkout, you run git pull in ~/.phpenv. The README states this explicitly. That is a low maintenance cost for the core tool. However, the real cost is in maintaining your PHP builds. Each PHP version you install via php-build is a separate compilation, and you need to keep those builds updated with security patches. The README does not provide a command for updating an existing PHP version; you would have to rebuild it. Also, the plugin architecture is bash-based, so extending phpenv requires writing bash scripts. The license is MIT, which means you can modify and redistribute it freely, but the README does not discuss contribution guidelines. Overall, the maintenance burden is on the PHP builds, not on phpenv itself.

Editorial conclusion

Adopt phpenv if you are a PHP developer who needs multiple PHP versions on one machine, especially if you already compile PHP with php-build or want per-directory version switching without containers. Avoid it if you prefer precompiled binaries or need Windows support, since phpenv is shell-based and expects a Unix-like environment. Before adopting, verify that your shell startup files are correctly edited, test the shims with phpenv rehash after each PHP install, and confirm that your build dependencies satisfy php-build's requirements. phpenv is a pragmatic, rbenv-inspired tool, but it does not manage PHP dependencies or extensions beyond what you build into each version.

Official sources

  1. Official README
  2. Project repository
  3. Release notes
Community notes

Community notes