PHP — Reference
Source: https://www.php.net/manual/en/
PHP
- Created: 1994 by Rasmus Lerdorf (originally “Personal Home Page tools”; reinterpreted as the recursive “PHP: Hypertext Preprocessor”)
- Latest stable: 8.5 (released 2025-11-20, https://www.php.net/releases/8.5/en.php; 8.5.x patch series in 2026 — verify exact patch on https://www.php.net/downloads.php)
- Paradigms: Multi-paradigm — imperative, object-oriented (full class/interface/trait/enum support since 8.1), functional-leaning (first-class callables, arrow fns, closures), reflective
- Typing: Dynamic by default; gradual typing with optional declarations (parameter, return, property since 7.4, readonly since 8.1, union since 8.0, intersection since 8.1, never since 8.1, true/false/null pseudo-types since 8.2).
declare(strict_types=1)enforces strict scalar checks per file - Memory: Garbage-collected — reference counting + cycle collector for circular refs (synchronous, deterministic destruction is the default)
- Compilation: Source → opcodes (Zend opcodes) → executed by the Zend Engine. OPcache caches opcodes in shared memory; JIT (PHP 8.0+) compiles hot opcodes to x86-64/ARM64 native code via DynASM
- Primary domains: Server-side web (still ~75% of all websites per W3Techs), CMSes (WordPress, Drupal, Joomla), e-commerce (Magento, WooCommerce, Shopware), CLI tooling (Composer itself, Laravel Artisan)
- Official docs: https://www.php.net/manual/en/
At a glance
- Steward: The PHP Group + php-src maintainers; governance by PHP RFCs (https://wiki.php.net/rfc) requiring 2/3 majority of voting members.
- Major release cadence: roughly one minor per November (8.0 → 2020-11, 8.1 → 2021-11, …, 8.5 → 2025-11). Active support 2 years + 1 year security-only after release.
- Reference implementation: Zend Engine (in C); OPcache is bundled and on-by-default in modern PHP-FPM / SAPI configs.
- Alternative runtimes: HHVM (Facebook; diverged into Hack), Swoole / OpenSwoole (event-loop coroutine runtime), FrankenPHP (Caddy-embedded, app-server mode), RoadRunner (Go-based PHP app server), php-wasm (browser/WASI).
- License: PHP License (3.01 — BSD-style, with a clause forbidding products called “PHP”).
Getting started
-
Install: Linux: distro packages (
apt install php8.5,dnf install php); macOS:brew install php; Windows: official ZIP from windows.php.net or via WSL/XAMPP/Laragon. Multi-version managers:phpbrew,phpenv,brew install shivammathur/php/php@8.4for tap-based switching, asdf-php, Docker images (php:8.5-fpm). -
Hello world (
hello.php):<?php echo "Hello, world!\n";Run:
php hello.php. Built-in dev server:php -S localhost:8000(since 5.4). -
Project layout (Composer / PSR-4):
composer.json,vendor/(auto-generated, gitignored),src/for autoloaded code,tests/,bin/,public/for web entrypoint,composer.lock(commit it). -
Package manager: Composer (https://getcomposer.org) is universal and non-negotiable for modern PHP — packagist.org is the public registry. PIE (PHP Installer for Extensions, official) replaces PECL for installing C extensions since 2024.
-
REPL:
php -aopens an interactive shell (limited — no autocomplete, no multi-line state on some builds). PsySH (composer global require psy/psysh) is the de-facto power REPL with tab completion, syntax highlighting, anddump. Symfony’sbin/console tinkerand Laravel’sphp artisan tinkerwrap PsySH with framework boot. (https://www.php.net/manual/en/features.commandline.interactive.php)
Basics
- Types/literals: scalar —
int,float,string,bool; compound —array(ordered hash map),object; special —null,resource,callable,iterable. Numeric:1_000_000(since 7.4),0xFF,0b1010,0o777(since 8.1),1.5e3. Strings: single-quoted (literal except\\and\'), double-quoted (interpolation + escapes), heredoc (<<<EOT), nowdoc (<<<'EOT'). - Variables:
$camelCasemandatory sigil. Variable variables ($$x). No declarations — first assignment creates. Constants viaconst FOO = 1;(compile-time, class-scope) ordefine('FOO', 1)(runtime). - Scoping: Function-scoped; no closures over enclosing locals by default —
function () use ($x) { ... }to capture,use (&$x)for by-reference. Arrow fns (fn($x) => $x * 2, since 7.4) auto-capture by value. - Control flow:
if/elseif/else,switch(loose==),match(since 8.0 — strict===, expression, exhaustive),for,foreach ($arr as $k => $v),while,do-while. Alternative syntax for templates:if (...): ... endif;.try/catch/finally. - Functions:
function name(int $a, int $b = 0): int { return $a + $b; }. Named args (since 8.0), default args, variadic (...$args), spread (f(...$args)), nullable (?int), union (int|string), intersection (A&B),neverreturn. - Strings: Concatenation with
.(not+). Interpolation in double-quoted:"Hello $name","Hello {$obj->prop}".sprintf,printf,number_format.str_contains/str_starts_with/str_ends_withsince 8.0. - Collections:
arrayis the data structure — both an ordered list and an associative map (preserves insertion order).[1, 2, 3]and['a' => 1, 'b' => 2]use the same type.SplObjectStorage,SplStack,SplQueue,SplPriorityQueue,WeakMap(since 8.0),WeakReference.ArrayObjectfor OO interface over arrays.
Intermediate
- Type system depth: strict mode per file (
declare(strict_types=1)); without it, scalar types coerce. Generics are not native — Psalm/PHPStan provide them via docblocks (@template T). Covariant returns + contravariant params since 7.4. Property promotion in constructors (since 8.0):public function __construct(public string $name) {}. - Modules: PHP has namespaces (
namespace App\\Foo;) but no module system per se. PSR-4 autoloading via Composer maps namespaces to filesystem paths.use App\\Foo\\Bar;for imports. - Error handling:
Throwableis the root;Error(engine errors, type errors) andException(user errors) descend from it.try { } catch (Throwable $e) { } finally { }. Multi-catch:catch (A | B $e). The PHP error-reporting system (E_NOTICE, E_WARNING, etc.) is separate from exceptions — convert viaset_error_handlerorErrorExceptionwrapping. PHP 8 promoted many warnings to errors/exceptions. - Concurrency primitives:
- Fibers (since 8.1): native coroutines (
new Fiber($callable)+Fiber::suspend()/->resume()). Powers async libraries like ReactPHP, Amp v3, Revolt event loop. - No threads in the official runtime by default (the
pthreadsandparallelextensions exist but are CLI-only and require ZTS builds). - PCNTL (
pcntl_fork) for true process parallelism (Unix only). - Process model: traditional PHP-FPM is request-per-process — concurrency is the web server’s job. Swoole / RoadRunner / FrankenPHP flip the model to long-running app servers with goroutine/fiber-like primitives.
- Fibers (since 8.1): native coroutines (
- I/O:
file_get_contents,fopen/fread/fwrite/fclose,SplFileObject, stream wrappers (http://,php://stdin,php://memory,compress.zlib://, custom viastream_wrapper_register),curl(PECL bundled by default), Guzzle (guzzlehttp/guzzle) for HTTP. - Stdlib highlights: SPL (Standard PHP Library — datastructures, iterators, file objects),
json_encode/json_decode(withJSON_THROW_ON_ERROR),DateTime/DateTimeImmutable/DateInterval/DatePeriod,IntlDateFormatter/NumberFormatter(intl ext),mbstring(multibyte strings),PDO(DB abstraction),password_hash/password_verify(Argon2/bcrypt),random_int/random_bytes(CSPRNG),Reflection*.
Advanced
- Memory/GC: Reference counting (
refcountper zval) gives deterministic destruction; the cycle collector runs periodically to clean up reference cycles (algorithm based on Bacon-Rajan synchronous mark-and-sweep).gc_collect_cycles(),gc_status(),gc_disable()/gc_enable(). Object destructors fire deterministically when refcount drops to zero — useful for RAII-style resource cleanup. - OPcache + JIT (PHP 8.x): OPcache compiles each
.phpto opcodes once and stores them in shared memory (opcache.memory_consumption,opcache.max_accelerated_files). Preloading (since 7.4) loads classes once at server start, eliminating per-request resolution. JIT (since 8.0) tiers up hot opcodes to native code via DynASM; tuned byopcache.jit=tracing(default) orfunction,opcache.jit_buffer_size. Big wins on CPU-bound workloads; modest on typical I/O-bound web. (https://php.net/manual/en/opcache.configuration.php) - FFI:
ext-ffi(since 7.4) lets PHP call into C libraries withcdefstrings — preload.hfiles,FFI::cdef('int strlen(const char*);', 'libc.so.6'). Same speed as a C extension for simple cases but no need to compile. Disabled in non-CLI by default (ffi.enable=preload). - Reflection:
ReflectionClass,ReflectionMethod,ReflectionProperty,ReflectionAttribute(since 8.0),ReflectionEnum(since 8.1),ReflectionFiber(since 8.1). Used by every DI container, ORM, and serializer in the ecosystem (Symfony, Doctrine, Laravel). - Performance tools: Xdebug (debugger + profiler — slow but ubiquitous),
spx(lightweight built-in-style profiler), Blackfire.io (commercial, callgraph + assertions), Tideways (commercial APM),opcache.preloadfor cold-start wins,pcovfor fast coverage. Built-inmicrotime(true),memory_get_peak_usage(),getrusage(). VLD extension dumps opcodes (php -d vld.active=1 script.php).
God mode
- OPcache + JIT internals: opcodes live in shared memory; the JIT compiler emits native code into a JIT buffer. Tracing JIT records hot loops; function JIT compiles whole functions on first call. Inspect with
opcache_get_status(). Tune withopcache.jit_max_root_traces,opcache.jit_hot_loop. Disable selectively for problem code withfunction_existsguards oropcache.jit_blacklist. - FFI deep: preload
.hdefinitions inopcache.preloadso cdef cost is paid once; pass C structs back and forth viaFFI::new/FFI::addr. Lets you ship near-C performance without writing a Zend extension. - Fiber concurrency:
Fiber::suspend($value)returns control to whoever called->resume();->resume($value)becomes the return value ofFiber::suspend. Build event loops on top (Revolt / Amp v3 / ReactPHP 3 do this). The runtime keeps Fiber stacks separately allocated; cheap in millions per process. - Attributes (PHP 8): native annotations —
#[Route('/users')]parsed by the engine (no docblock string parsing). Read withReflectionMethod::getAttributes(). Powers Symfony routing, Doctrine ORM v3, validators. - Readonly classes (since 8.2):
readonly class Point { ... }makes all properties readonly. Asymmetric visibility (public(set)/private(set)) added in 8.4 — finer-grained mutation control. - Enum internals (since 8.1):
enum Status { case Active; case Inactive; }(pure) orenum Status: string { case Active = 'a'; }(backed). Backed enums are singletons —Status::Active === Status::from('a'). Methods, interfaces, constants allowed; no constructors, no instantiation. - Reflection API depth:
ReflectionParameter::getDefaultValueExpression()(since 8.4),ReflectionFunction::getClosureUsedVariables()for inspectingusecaptures,ReflectionGeneratorfor paused generators. Combined withevalit’s a full metaprogramming kit — Doctrine builds proxies this way. - Opcode dumping (vld):
php -d vld.active=1 -d vld.execute=0 script.phpprints the opcode stream — invaluable when diagnosing JIT or OPcache misbehavior. (https://github.com/derickr/vld) - Preloading: in
php.ini,opcache.preload=/app/preload.phpruns that file once at server startup, permanently loading classes/functions into shared memory. Saves ~5-15% on real apps. Beware: preloaded classes can’t be redeclared without restarting PHP-FPM. - php-internals: the engine is C; the test suite is
.phptfiles; RFCs at https://wiki.php.net/rfc/. The php-src repo (https://github.com/php/php-src) is the canonical source. The Zend Engine spec is de facto (no formal language standard). - Stream wrappers: register custom protocols —
stream_wrapper_register('s3', S3StreamWrapper::class)letsfopen('s3://bucket/key', 'r')work. Used by Flysystem, Symfony filesystem.
Idioms & style
- Naming:
camelCasefor methods/variables,PascalCasefor classes/interfaces/traits/enums,SCREAMING_SNAKE_CASEfor constants. Files: one class per file, file name matches class name (PSR-4). - Formatter / linter: PSR-12 (https://www.php-fig.org/psr/psr-12/) is the de-facto coding standard, succeeded by PER-CS (PHP Evolving Recommendation — Coding Style). Tools: PHP_CodeSniffer (
phpcs/phpcbf), PHP-CS-Fixer (php-cs-fixer fix), Pint (Laravel’s wrapper around PHP-CS-Fixer). PHPStan and Psalm for static analysis (level 0–9 / level 1–8 strictness ramps). - Idiomatic patterns: type-declare everything (params, returns, properties); use DTOs with
readonlyconstructor-promoted properties; throw exceptions, don’t return false-on-error in new code; embrace named arguments for clarity; immutable value objects;Stringableinterface over__toString. - Expert review focus: missing
declare(strict_types=1), mixedarrayof unknown shape (use shape annotations or DTOs), un-disposed Fibers, untyped Composer dependencies, opcache-unsafe code (e.g.,evalof dynamic class definitions), preload contamination, reliance on global state for request-scoped data (broken on Swoole/RoadRunner).
Ecosystem
- Web frameworks: Laravel (the dominant full-stack — Eloquent, Blade, Livewire, Inertia), Symfony (component-based; many other frameworks use Symfony components), CakePHP, CodeIgniter, Yii, Slim (micro), Mezzio (PSR middleware), Phalcon (C-extension perf).
- CMS / e-commerce: WordPress, Drupal, Joomla, Magento 2, Shopware, Statamic, October CMS.
- API: API Platform (Symfony-based, JSON-LD/Hydra/GraphQL), Laravel API Resources, Lumen (deprecated for Laravel slim mode).
- App servers / async: FrankenPHP (Caddy module + worker mode), RoadRunner (Go), Swoole / OpenSwoole (C ext), ReactPHP (Fiber-based now), Amp v3 (Fibers).
- Testing: PHPUnit (de-facto), Pest (developer-friendly Laravel-flavored layer over PHPUnit), Codeception (BDD), Behat (Gherkin), Infection (mutation testing), Mockery, Prophecy.
- DB / ORM: Doctrine (Symfony default — data mapper), Eloquent (Laravel — Active Record), Cycle ORM, raw PDO.
- Docs: phpDocumentor (
phpdoc), Doctum (Symfony’s), Sami (deprecated). Nativephp.netdocs are exemplary — community comments + man-page-style reference. - Notable users: Facebook/Meta (origin; now uses Hack on HHVM, but still PHP-derived), Wikipedia/Wikimedia, Slack, Etsy, MailChimp, Tumblr, Yahoo, Vimeo, WordPress.com (Automattic), most of Drupal-based gov sites.
Gotchas
==does loose comparison with type juggling —0 == "abc"wastrueuntil PHP 8 fixed it;0 == ""wastrueuntil 8.0 too. Always prefer===.arrayis both list and dict —count($arr)works on both, butarray_values()re-indexes. JSON encode of associative array → object; of sequential → array.array_is_list()(since 8.1) checks.nullpropagation: pre-8 most stdlib functions accepted null silently; many nowType cannot be nulldeprecation/warning in 8.1+, error in 9.x.foreachby reference (foreach ($arr as &$v)) — the reference persists after the loop;unset($v)after, or you’ll mutate the last element on next assignment.- Static analysis grade-3+ catches almost everything, but the language won’t — adopt PHPStan/Psalm early.
- Trait conflicts must be resolved with
insteadof/as. Order ofusematters. __constructis not inherited by name — child overrides parent and must callparent::__construct()explicitly.privatein a trait means private-per-using-class (each class gets its own copy).- OPcache cache invalidation: in production with
opcache.validate_timestamps=0, you must restart PHP-FPM (oropcache_reset) after deploys. - JIT and Xdebug are mutually exclusive (Xdebug disables JIT).
- PHP-FPM session locking: default file-based sessions hold an exclusive lock on the session file for the whole request — concurrent AJAX requests serialize. Switch to Redis or call
session_write_close()early. - Default
error_reportingin dev should includeE_ALL; many silent-bug pitfalls only surface with notices on. intis 64-bit on 64-bit builds, 32-bit on 32-bit (rare today).PHP_INT_MAXto check.
Citations
- Manual root: https://www.php.net/manual/en/
- Downloads: https://www.php.net/downloads.php
- Migration guides: https://www.php.net/manual/en/migration85.php (and prior
migrationXXper minor) - RFCs / governance: https://wiki.php.net/rfc
- PSR-12 coding style: https://www.php-fig.org/psr/psr-12/
- PER coding style (successor): https://www.php-fig.org/per/coding-style/
- Composer: https://getcomposer.org/doc/
- Packagist: https://packagist.org/
- Fibers RFC: https://wiki.php.net/rfc/fibers
- JIT RFC: https://wiki.php.net/rfc/jit
- OPcache config: https://www.php.net/manual/en/opcache.configuration.php
- FFI: https://www.php.net/manual/en/book.ffi.php
- Reflection: https://www.php.net/manual/en/book.reflection.php
- VLD opcode dumper: https://github.com/derickr/vld
- php-src (the engine): https://github.com/php/php-src
- PHPStan: https://phpstan.org/
- Psalm: https://psalm.dev/
- Version verified 2026-05-06: 8.5 series current per php.net manual landing