phpdiscover

package module
v0.0.0-...-da3bc85 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2026 License: MIT Imports: 11 Imported by: 0

README

phpdiscover

CI

phpdiscover is a zero-dependency Go package that finds all PHP binaries installed on the current machine. Every candidate is collected, verified and deduplicated.

Usage

package main

import (
	"context"
	"fmt"

	"github.com/shyim/go-php-discover"
)

func main() {
	phps := phpdiscover.Discover(context.Background())

	for _, p := range phps {
		fmt.Printf("PHP %s at %s (%s)\n", p.Version, p.Path, p.Source)
	}
}

Result helpers:

system := phpdiscover.Default(phps)      // first $PATH binary, else newest
latest := phpdiscover.Latest(phps)       // newest version
php82  := phpdiscover.FindVersion(phps, "8.2") // newest matching "8", "8.2" or "8.2.3"
phpdiscover.Sort(phps)                   // ascending by version

Options:

phpdiscover.Discover(ctx,
	phpdiscover.WithTimeout(2*time.Second), // per-binary probe timeout (default 5s)
	phpdiscover.WithConcurrency(8),         // parallel probes (default 4)
	phpdiscover.WithLogger(log.Printf),     // progress messages
	phpdiscover.WithExtraDirs("/opt/my-php"),          // scan extra directories
	phpdiscover.WithSources(phpdiscover.SourcePath),   // only use $PATH
	phpdiscover.WithoutSource(phpdiscover.SourceNix),  // skip one source
)

How discovery works

Candidates come from four places:

  1. $PATH — every directory in $PATH is scanned for php, php8, php8.2, php8.2.3, php-cli, ... The first PHP found in $PATH is marked IsSystem.
  2. Known hoster locations — well-known locations used by hosting providers (/opt/plesk/php/*/bin/php, /opt/alt/php*/usr/bin/php, /usr/local/phpfarm/..., MAMP, ...). The {major}, {minor}, {release} placeholders are turned into glob patterns so that every installed version is matched.
  3. Well-known installation directories — /usr/bin, /usr/local/bin, XAMPP, phpbrew, phpenv, Herd-lite, Homebrew (brew --cellar), Nix (builtins.storeDir), asdf-vm, Remi's RPM repo, and on macOS MAMP, MacPorts and Liip PHP; on Windows XAMPP, Cygwin, Chocolatey, WAMP, MAMP and Herd.
  4. Extra directories — supplied via WithExtraDirs.

Every candidate is verified by running php --version (with a timeout, in parallel) and parsing the PHP X.Y.Z version from its output. Results are deduplicated by the resolved (real) path, so symlinks like /usr/local/bin/php -> ../Cellar/php/8.5.9/bin/php collapse into a single entry. Sibling binaries of the same installation are attached when present:

p.FPMPath       // php-fpm
p.CGIPath       // php-cgi
p.PHPConfigPath // php-config
p.PHPizePath    // phpize
p.PHPdbgPath    // phpdbg

Example output

$ go run ./cmd/phpdiscover
PHP 8.3.33
  path:    /opt/homebrew/Cellar/php@8.3/8.3.33/bin/php
  source:  homebrew
  fpm:     /opt/homebrew/Cellar/php@8.3/8.3.33/sbin/php-fpm
  cgi:     /opt/homebrew/Cellar/php@8.3/8.3.33/bin/php-cgi
  config:  /opt/homebrew/Cellar/php@8.3/8.3.33/bin/php-config
  phpize:  /opt/homebrew/Cellar/php@8.3/8.3.33/bin/phpize
  phpdbg:  /opt/homebrew/Cellar/php@8.3/8.3.33/bin/phpdbg
PHP 8.4.24
  ...
PHP 8.5.9 (system)
  path:    /opt/homebrew/Cellar/php/8.5.9/bin/php
  via:     /opt/homebrew/bin/php
  source:  PATH
  ...

Design

  • Returns all binaries instead of a single "best" one and works without a running PHP (no PHP_BINARY-relative lookups).
  • Zero external dependencies.
  • Symlinks are resolved and deduplicated; sibling server binaries are attached to each version.
  • No disk cache: every call does a fresh, fast discovery.

Development

Linting

The project uses golangci-lint (v2) with all linters enabled except five, each with a documented reason in .golangci.yml:

  • wsl / gomodguard — deprecated, superseded by the enabled wsl_v5 / gomodguard_v2
  • forbidigo — its default rules forbid fmt.Print*, which the CLI legitimately uses
  • testpackage — the unit tests exercise unexported helpers
  • varnamelen — idiomatic short names (p, v, i, ok) in small scopes
golangci-lint run ./...        # lint everything

golangci-lint fmt              # apply gofumpt + goimports

Note: wsl_v5 and nlreturn enforce an airy whitespace style (blank lines between unrelated statements, before return/break/continue). Keep new code consistent with it, or drop those linters from disable: if you dislike the style.

Publishing

The module lives at github.com/shyim/go-php-discover (private). If you later publish it publicly or move it to another account, run:

go mod edit -module github.com/<owner>/go-php-discover

update the import path in cmd/phpdiscover/main.go and the depguard allowlist in .golangci.yml, and adjust the CI badge URL at the top of this README to match the new repository.

License

MIT, see LICENSE.

Documentation

Overview

Package phpdiscover finds all PHP binaries installed on the current machine.

Every candidate is collected, verified and deduplicated. Candidates come from four places:

  • every directory in $PATH (php, php8, php8.2, php8.2.3, php-cli, ...)
  • the "known locations" used by hosting providers, turned into glob patterns so that every installed version matches
  • well-known installation directories (Homebrew, Nix, phpbrew, phpenv, asdf-vm, MAMP, XAMPP, MacPorts, Ondrej PPA, Remi, Herd, ...)
  • extra directories supplied by the caller

Every candidate is verified by running `php --version` (with a timeout), and results are deduplicated by the resolved (real) path. Sibling binaries of the same installation (php-fpm, php-cgi, php-config, phpize, phpdbg) are attached when they exist.

The package has no external dependencies.

Index

Constants

View Source
const (
	SourcePath          = "PATH"
	SourceUsr           = "/usr"
	SourceKnownLocation = "known-location"
	SourceHomebrew      = "homebrew"
	SourceNix           = "nix"
	SourceAsdf          = "asdf-vm"
	SourcePhpbrew       = "phpbrew"
	SourcePhpenv        = "phpenv"
	SourceMAMP          = "MAMP"
	SourceXAMPP         = "XAMPP"
	SourceMacPorts      = "MacPorts"
	SourceOndrej        = "ondrej-ppa"
	SourceRemi          = "remi"
	SourceLiip          = "Liip"
	SourceHerd          = "Herd"
	SourceHerdLite      = "herd-lite"
	SourceWAMP          = "WAMP"
	SourceCygwin        = "Cygwin"
	SourceChocolatey    = "chocolatey"
	SourceExtra         = "extra"
)

Source names, describing where a PHP binary was found.

Variables

This section is empty.

Functions

func Sort

func Sort(list []*PHP)

Sort sorts a list of PHP binaries by version (ascending). Ties are broken by path.

Types

type Logger

type Logger func(format string, args ...any)

Logger receives human-readable progress messages during discovery.

type Option

type Option func(*config)

Option customizes a discovery run.

func WithConcurrency

func WithConcurrency(n int) Option

WithConcurrency sets how many candidate binaries are probed in parallel. Defaults to 4.

func WithExtraDirs

func WithExtraDirs(dirs ...string) Option

WithExtraDirs adds directories that are scanned for php-like executables.

func WithLogger

func WithLogger(l Logger) Option

WithLogger installs a logger that receives progress messages.

func WithSources

func WithSources(sources ...string) Option

WithSources restricts discovery to exactly the given sources (see Source* constants). When set, all other sources are ignored. It can be combined with WithoutSource to exclude individual sources from the allowlist.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the maximum time a single `php --version` probe (or the brew/nix/asdf lookups) may take. Defaults to 5 seconds. Non-positive values keep the default timeout.

func WithoutSource

func WithoutSource(name string) Option

WithoutSource disables a discovery source (see Source* constants). It can be called multiple times.

type PHP

type PHP struct {
	// Path is the absolute path to the PHP binary with all symlinks resolved.
	Path string
	// OriginalPath is the path as it was discovered (may be a symlink).
	OriginalPath string
	// Version is the parsed version reported by `php --version`.
	Version Version
	// Source describes where this binary was found (see Source* constants).
	Source string
	// IsSystem is true for the first PHP binary found in $PATH.
	IsSystem bool

	// FPMPath, CGIPath, PHPConfigPath, PHPizePath and PHPdbgPath are sibling
	// binaries of the same PHP installation, when present.
	FPMPath       string
	CGIPath       string
	PHPConfigPath string
	PHPizePath    string
	PHPdbgPath    string
}

PHP describes a single locally available PHP binary.

func Default

func Default(list []*PHP) *PHP

Default returns the system PHP (the first one found in $PATH) if any, otherwise the newest available binary, or nil if none was found.

func Discover

func Discover(ctx context.Context, opts ...Option) []*PHP

Discover returns all locally available PHP binaries, sorted by version.

Discovery is best-effort: directories that cannot be read, binaries that fail to run or that do not respond with a PHP version are silently skipped. The context is used to bound the runtime of the probes; a canceled context stops new probes from being started but keeps the results found so far.

func FindVersion

func FindVersion(list []*PHP, prefix string) *PHP

FindVersion returns the newest PHP binary matching a version prefix such as "8", "8.2" or "8.2.3", or nil if none matches.

func Latest

func Latest(list []*PHP) *PHP

Latest returns the newest PHP binary of the list, or nil if it is empty.

type Version

type Version struct {
	Major int
	Minor int
	Patch int

	// Extra contains an optional suffix reported by PHP,
	// e.g. "-1ubuntu2.14" for Debian packaged PHP or "RC4" for release candidates.
	Extra string
}

Version is a parsed PHP version like 8.2.3.

func (Version) Compare

func (v Version) Compare(o Version) int

Compare returns -1, 0 or 1 depending on whether v is less than, equal to or greater than o. Extra suffixes are ignored for comparison.

func (Version) String

func (v Version) String() string

String returns the version as a string, e.g. "8.2.3" or "8.1.2-1ubuntu2.14".

Directories

Path Synopsis
cmd
phpdiscover command
Command phpdiscover lists all PHP binaries found on the current machine.
Command phpdiscover lists all PHP binaries found on the current machine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL