Skip to content

sen-ltd/phpinfo-json

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

phpinfo-json

Parse phpinfo() output into clean, scriptable JSON. Diff two environments. CI-friendly exit codes. PHP 8.2 stdlib only — no Composer runtime deps, just DOMDocument + DOMXPath + json_encode.

phpinfo() is still the canonical way to ask "what does this environment actually look like?" but its HTML dump is hostile to everything you'd reasonably want to do with it: you can't grep a nested directive with its section, you can't pipe it into jq, you can't diff two containers that claim to run the same PHP stack. phpinfo-json fixes that in ~400 lines of strict PHP.

Why

The typical workflow: a CI job fails because OPcache was disabled on one runner, or a container ships with a different openssl version than the dev image, or memory_limit somehow ended up at 128M in production and nobody knows why. You reach for phpinfo(), get a 200 KB HTML blob, and then stare at it. This tool turns that blob into:

{
  "general": {
    "php_version": "8.2.20",
    "system": "Linux host 6.1.0 #1 SMP x86_64",
    "server_api": "Command Line Interface"
  },
  "sections": {
    "Core": {
      "memory_limit": { "local": "256M", "master": "128M" },
      "display_errors": { "local": "Off", "master": "On" }
    },
    "opcache": {
      "opcache.enable": { "local": "On", "master": "On" }
    }
  },
  "modules": ["Core", "opcache", "PDO", "json", "curl"]
}

Now you can jq '.sections.opcache', grep memory_limit, or feed two dumps into --diff and get a clean added / removed / changed report.

Features

  • Parses phpinfo() HTML via DOMDocument + DOMXPath — no regex, no SimpleXML, no Composer runtime deps.
  • Also parses text output (php -i) so you can feed it raw CLI dumps.
  • Auto-detects format by looking for <table tags.
  • --diff mode: compare two environments, get added/removed/changed keys + a modules.added/removed delta.
  • --section NAME to extract a single section; --only-modules to list loaded extensions.
  • --format flat emits section.key=value lines for grep / awk.
  • No arguments = run phpinfo() inside the current PHP process via output buffering and dump the result as JSON. Great for Dockerfile RUN phpinfo-json > /env.json.
  • Exit codes: 0 success, 1 parse/IO error, 2 bad CLI args.
  • 20+ PHPUnit tests, strict types, PSR-4 autoload, fallback manual autoloader for zero-vendor runtime.

Install (Docker — recommended)

docker build -t phpinfo-json .

# Dump the running container's phpinfo
docker run --rm phpinfo-json | jq '.sections.Core'

# Just the module list
docker run --rm phpinfo-json --only-modules

# Parse a captured file
docker run --rm -v $(pwd):/work phpinfo-json /work/phpinfo.html --format flat

# Diff two containers
docker run --rm -v $(pwd):/work phpinfo-json /work/env-a.html --diff /work/env-b.html

The image is a multi-stage Alpine build (alpine:3.19 runtime). PHPUnit lives in the builder stage only. Final size is under 100 MB.

Install (local)

git clone https://github.com/sen-ltd/phpinfo-json.git
cd phpinfo-json
php bin/phpinfo-json --help

No composer install is required for the tool to run — the bin script registers a manual PSR-4 autoloader. Composer is only needed for tests.

Usage

# Default: capture phpinfo() inside the current PHP process → JSON
phpinfo-json

# Parse a saved HTML dump
phpinfo-json phpinfo.html

# Parse CLI text output (php -i > info.txt)
phpinfo-json info.txt --input text

# Pipe from stdin
php -i | phpinfo-json -

# One section only
phpinfo-json --section opcache
phpinfo-json --section Core

# Just loaded modules
phpinfo-json --only-modules

# Flat format: section.key=value
phpinfo-json --format flat | grep memory_limit

# Diff two environments
phpinfo-json prod.html --diff staging.html | jq '.changed'

How it works

phpinfo() HTML has a predictable structure: each section is an <h2> tag followed by a <table> with rows of <tr><td>key</td><td>value</td></tr>, or the Directive | Local Value | Master Value three-column form for INI-style directives. The parser walks <h2> elements in document order, picks up the next <table> sibling, and extracts rows via XPath.

The tricky bits are handled by design:

  • "no value" cells (<i>no value</i> in HTML, literal no value in text mode) become the empty string in output.
  • Multi-line values (like disable_functions with \n-separated function names) are preserved with newlines intact.
  • UTF-8 keys and values work without manual encoding — the DOMDocument loader is given an <?xml encoding="UTF-8"?> hint.

Read the article for the full write-up: Parsing phpinfo() in pure PHP.

Tests

composer install
vendor/bin/phpunit

# or inside the docker image:
docker run --rm --entrypoint /app/vendor/bin/phpunit phpinfo-json \
  --no-coverage -c /app/phpunit.xml

License

MIT

Links

About

A phpinfo() -> JSON converter written in pure PHP 8.2 stdlib (DOMDocument + DOMXPath + json_encode, zero Composer runtime deps) because phpinfo()'s 72 KB HTML dump is the most-used PHP debugging tool on earth and is hostile to every reasonable thing you'd want to do with it.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors