* feat: add Ubuntu support via provider-based architecture Implement multi-system support using a provider pattern that enables phpenv to work with both Homebrew (macOS/Linux) and APT (Ubuntu/Debian with Ondřej Surý PPA). - Add provider infrastructure with auto-detection and PHPENV_PROVIDER override - Refactor existing Homebrew code into __phpenv_provider_homebrew_* functions - Implement APT provider with PPA setup, shim-based version switching - Update doctor, versions, and help commands to be provider-aware - Use XDG-compliant shim directory (~/.local/share/phpenv/shims) * fix: address PR #112 code review feedback - Fix semver parsing for complex constraints like ">=8.1 <9.0" - Add input validation for APT commands to prevent injection - Use atomic symlink creation to prevent race conditions - Fix extension uninstall to mirror install package mappings - Replace unsafe glob with explicit binary list in cleanup - Remove redundant PATH filtering logic - Validate PHPENV_PROVIDER against supported providers - Use exact matching for Homebrew tap names - Use Fish's string escape for regex escaping * fix: validate dpkg output before passing to sudo apt-get Validates package names follow Debian naming rules before using them in the sudo apt-get remove command. This prevents potential command injection if dpkg output contains unexpected characters. Addresses remaining Copilot feedback from PR #112.
phpenv.fish
A fast, feature-rich PHP version manager for Fish Shell that acts like goenv or nvm.
Features
- Fast version detection (100-1000x faster than
brew list) - Dynamic version resolution from shivammathur/setup-php
- Multiple version sources:
.php-version,.tool-version,composer.json - Auto-installation of missing PHP versions
- Extension management with availability checking
- Composer.json integration with full semver support
- Auto-switching between versions (configurable)
- Fisher package manager support
- Rich completions with descriptions
Installation
Using Fisher (recommended)
fisher install ivuorinen/phpenv.fish
Manual Installation
-
Copy files to your fish configuration:
# Functions curl -L https://raw.githubusercontent.com/ivuorinen/phpenv.fish/main/functions/phpenv.fish > ~/.config/fish/functions/phpenv.fish # Completions curl -L https://raw.githubusercontent.com/ivuorinen/phpenv.fish/main/completions/phpenv.fish > ~/.config/fish/completions/phpenv.fish # Configuration curl -L https://raw.githubusercontent.com/ivuorinen/phpenv.fish/main/conf.d/phpenv.fish > ~/.config/fish/conf.d/phpenv.fish -
Install dependencies:
brew install jq -
Add Homebrew taps:
brew tap shivammathur/php brew tap shivammathur/extensions
Quick Start
# Show available versions
phpenv versions
# Install PHP versions
phpenv install 8.3
phpenv install 8.1
# Set global default
phpenv global 8.3
# Set project-specific version
phpenv local 8.1
# Install extensions
phpenv extensions install xdebug
phpenv extensions install redis
# Configure behavior
phpenv config set auto-switch false # Disable auto-switching
phpenv config set auto-install true # Enable auto-installation
# Check installation
phpenv doctor
Commands
Version Management
phpenv install <version>- Install PHP versionphpenv uninstall <version>- Uninstall PHP versionphpenv use <version>- Use version for current shellphpenv local <version>- Set version for current projectphpenv global <version>- Set global default versionphpenv list- List installed versionsphpenv current- Show current versionphpenv versions- Show all available versions
Extension Management
phpenv extensions install <ext>- Install extension for current PHPphpenv extensions uninstall <ext>- Uninstall extensionphpenv extensions list- List installed extensionsphpenv extensions available- Show available extensions
Configuration
phpenv config get <key>- Get configuration valuephpenv config set <key> <value>- Set configuration valuephpenv config list- List all configuration
Utilities
phpenv which [binary]- Show path to PHP binaryphpenv doctor- Check installation healthphpenv help- Show help
Version Detection
phpenv automatically detects PHP versions from multiple sources (in priority order):
.php-version- Project-specific version file.tool-version- Tool version file (parsesv8.4as8.4)composer.json- Bothconfig.platform.phpandrequire.phpwith semver support- Global version - Fish universal variable
- System PHP - Fallback to system installation
Composer.json Support
Supports all semver constraints:
^8.1→ Uses PHP 8.3 (latest 8.x)~8.2.0→ Uses PHP 8.2>=8.0→ Uses PHP 8.38.1.*→ Uses PHP 8.1
Checks both locations:
{
"require": {
"php": "^8.1"
},
"config": {
"platform": {
"php": "8.2.0"
}
}
}
Configuration
Configuration Keys
auto-install- Auto-install missing versions (default: false)auto-install-extensions- Install extensions with new PHP versions (default: false)auto-switch- Auto-switch versions when changing directories (default: true)default-extensions- Space-separated list of default extensions (default: "opcache")global-version- Global PHP version
Configuration Files
phpenv checks these locations (in order):
~/.config/fish/conf.d/phpenv.fish(preferred)~/.config/phpenv/config~/.phpenv.fish
Examples
# Enable auto-installation
phpenv config set auto-install true
# Disable auto-switching
phpenv config set auto-switch false
# Set default extensions
phpenv config set default-extensions "opcache xdebug redis"
# Enable auto-extension installation
phpenv config set auto-install-extensions true
Supported PHP Versions
Uses shivammathur/homebrew-php with dynamic version detection:
Version Aliases:
latest- Latest stable PHP versionnightly- Development version8.x- Latest PHP 8.x version7.x- Latest PHP 7.x version5.x- Latest PHP 5.x version
Available Versions: 5.6, 7.0-7.4, 8.0-8.5
Supported Extensions
Uses shivammathur/homebrew-extensions:
- xdebug, redis, imagick, mongodb, memcached
- pcov, ast, grpc, protobuf, yaml
- And many more...
Performance
- Directory checks: ~1-5ms (vs ~1000ms for
brew list) - Bulk version detection: ~10ms for all versions
- No Ruby overhead or git operations
- Efficient caching and lazy loading
Auto-switching
phpenv automatically switches PHP versions when you change directories if a version file is detected in the project.
Fisher Integration
Works seamlessly with Fisher package manager:
# Install
fisher install ivuorinen/phpenv.fish
# Update
fisher update ivuorinen/phpenv.fish
# Uninstall
fisher remove ivuorinen/phpenv.fish
Troubleshooting
Check Installation
phpenv doctor
Common Issues
jq not found
brew install jq
PHP version not found
# Add taps manually
brew tap shivammathur/php
brew tap shivammathur/extensions
# Install specific version
phpenv install 8.3
Slow performance
- phpenv is designed to be fast by avoiding
brew list - If performance issues persist, check your filesystem or try
phpenv doctor
Debug Information
# Check current detection
phpenv current
# Check which binary is used
phpenv which php
# List all configuration
phpenv config list
Contributing
Contributions welcome! Please see CONTRIBUTING.md for detailed guidelines.
Quick Guidelines:
- Follow fish shell best practices
- Add tests for new functionality
- Update documentation
- Maintain performance optimizations
- Run pre-commit hooks before submitting
Development Setup:
# Link development version to Fish config
ln -sf $PWD/functions/phpenv.fish ~/.config/fish/functions/phpenv.fish
ln -sf $PWD/completions/phpenv.fish ~/.config/fish/completions/phpenv.fish
ln -sf $PWD/conf.d/phpenv.fish ~/.config/fish/conf.d/phpenv.fish
# Install pre-commit hooks
pip install pre-commit
pre-commit install
Performance Optimizations
phpenv.fish is designed for speed and efficiency:
Caching System
- API Data Caching: Version information cached for 5 minutes
- Homebrew Path Caching: Cellar path permanently cached
- Smart Debouncing: Auto-switching limited to prevent excessive PATH changes
Unified Helper Functions
- Consolidated jq Parsing: Single function eliminates repeated API calls
- Unified Tap Management: Shared logic for Homebrew tap operations
- Optimized Formula Listing: Cached and shared across operations
Performance Metrics
- 100-1000x faster than
brew listfor version detection - Direct directory checks instead of subprocess calls
- Minimal network requests with intelligent caching
License
MIT License - see LICENSE file for details.