Emergency server help: get in touch

PHP Cheat Sheet: PHP 8.3 and 8.4 Syntax and Functions

A compact PHP 8.3 and 8.4 reference with tables for strings, arrays, functions, classes, the newest language features and the PHP command line.

Published 8 min read

Short answer: PHP 8.3 and 8.4 are the versions to target in 2026. Use declare(strict_types=1);, typed parameters and return types, match instead of long switch blocks, fn() => arrow functions for short callbacks, enums and readonly properties for data, and JSON_THROW_ON_ERROR for JSON. PHP 8.4 adds property hooks, private(set) visibility, array_find() and new Foo()->method() without extra brackets. The tables below cover the syntax you reach for every day.

The examples in this PHP cheat sheet were run with PHP 8.4.21 (CLI) on 9 October 2026. Features marked 8.4 do not work on PHP 8.3; everything else runs on both.

Variables, types and strings

SyntaxWhat it doesExample
$name = "web01";Variables start with $; no declaration needed$port = 8080;
"…$var…" / '…'Double quotes interpolate; single quotes are literal"Host {$name}:{$port}"
<<<TXT … TXT;Heredoc; the closing marker’s indentation is stripped from every lineMulti-line config templates
. and .=String concatenation$log .= "done\n";
str_contains(), str_starts_with(), str_ends_with()Substring tests that return boolstr_ends_with($f, ".log")
explode() / implode()Split a string / join an arrayexplode(",", "a,b,c")
sprintf() / printf()Formatted outputprintf("%-8s %5d\n", $h, $p);
strlen() vs mb_strlen()Bytes vs charactersstrlen("héllo") is 6, mb_strlen gives 5
?? and ??=Null coalescing; no warning for a missing key$ttl = $cfg['ttl'] ?? 300;
<=>Spaceship: returns -1, 0 or 1usort($a, fn($x, $y) => $x <=> $y);
===Strict comparison: value and type"1" === 1 is false
get_debug_type()Readable type name for messagesget_debug_type(1.0) gives float

Since PHP 8.0, 0 == "a" is false: a number is compared with a non-numeric string as a string. Numeric strings still compare as numbers ("10" == "1e1" is true), so prefer === unless you want type juggling.

Arrays and array functions

FunctionWhat it doesExample
[1, 2, 3], ['k' => 'v']List and associative array (both are ordered maps)$cfg = ['host' => 'db01'];
$a[] = 4;Append$hosts[] = 'web02';
[$a, $b] = $pair;Destructuring, also with keys['host' => $h] = $cfg;
[...$a, ...$b]Spread arrays into a new one (string keys allowed since 8.1)$all = [...$web, ...$db];
array_map()Transform each valuearray_map(fn($n) => $n * 2, $a)
array_filter()Keep matching values; keys are preservedarray_values(array_filter($a)) to reindex
array_reduce()Fold to one valuearray_reduce($a, fn($c, $i) => $c + $i, 0)
array_column()One field from a list of rows, optional keyarray_column($users, 'age', 'name')
in_array($x, $a, true)Search values; pass true for strictin_array(3, $ids, true)
array_key_exists() vs isset()isset is false when the value is nullarray_key_exists('ttl', $cfg)
array_merge() vs +Merge overwrites string keys; + keeps the left value$cfg + $defaults
sort, rsort, asort, ksort, usortSort in place (asort/ksort keep keys)ksort($cfg);
array_slice(), array_chunk(), array_unique()Slice, batch, de-duplicatearray_chunk($ids, 100)
array_is_list()True for keys 0, 1, 2… in orderarray_is_list([1, 2])

Control flow and match

SyntaxWhat it doesExample
if / elseif / elseConditionalsif ($code >= 500) { … }
matchExpression with strict comparison, no fall-through, returns a valuesee below
switchLoose comparison, needs breakLegacy code
foreach ($a as $k => $v)Iterate an array or iterableforeach ($cfg as $key => $val)
for, while, do … whileClassic loopsfor ($i = 0; $i < 3; $i++)
break / continueLeave or skip; break 2 leaves two loopsif ($i === 1) continue;
?: and ? :Short ternary and ternary$user = $input ?: 'guest';
$label = match (true) {
    $code >= 500 => 'server error',
    $code >= 400 => 'client error',
    default      => 'ok',
};
echo match ($code) { 200, 204 => 'fine', 404 => 'not found', default => 'other' };

A match with no matching arm and no default throws UnhandledMatchError instead of silently returning null.

Functions, closures and arrow functions

SyntaxWhat it doesExample
function f(int $n): stringTyped parameters and returnfunction greet(string $name): string
$x = "Hello" in the signatureDefault valuefunction greet(string $n, string $g = "Hello")
Named argumentsPass by name, in any ordergreet(greeting: "Hi", name: "Ann")
int ...$numsVariadic parametertotal(...[4, 5]) unpacks an array
?int, int|stringNullable and union typesfunction f(?int $n): int|string
void, never, staticNo return value / never returns / late static bindingfunction fail(): never { throw … }
function () use ($x) {}Closure; captures by value (use (&$x) by reference)$mul = function ($n) use ($f) { … };
fn($n) => $n * $fArrow function: one expression, captures automaticallyarray_map(fn($n) => $n * $f, $a)
strlen(...)First-class callable from any function or method$len = strlen(...);
array &$arrPass by referencefunction addOne(array &$arr): void

Add declare(strict_types=1); as the first statement of a file to stop PHP coercing "5" into int for calls made from that file; a mismatch then throws TypeError.

Classes, enums and readonly properties

enum Status: string {
    case Active = 'active';
    case Suspended = 'suspended';
    public function label(): string { return ucfirst($this->value); }
}

final class Server {
    public function __construct(
        public readonly string $host,
        private int $port = 22,
    ) {}
    public function dsn(): string { return "{$this->host}:{$this->port}"; }
}

$s = new Server('db01', 3306);
echo $s->dsn();                          // db01:3306
echo Status::from('active')->label();    // Active
var_dump(Status::tryFrom('x'));          // NULL
FeatureSyntaxNote
Constructor promotionpublic function __construct(private int $port) {}Declares and assigns in one place
Readonly propertypublic readonly string $hostSet once, inside the class; writing again throws Error
Readonly classreadonly class Point { … }Every property is readonly (8.2+)
Enumenum Suit { case Hearts; }Suit::Hearts->name, Suit::cases()
Backed enumenum Status: stringfrom() throws on bad input, tryFrom() returns null
Interface, abstract, traitinterface, abstract class, use Logs;Traits copy methods into a class
Nullsafe operator$user?->profile?->emailReturns null instead of an error on null
Static factorypublic static function local(): staticnew static(…) respects subclasses

What is new in PHP 8.3 and 8.4

VersionFeatureExample
8.3Typed class constantsconst string VERSION = '1.0';
8.3Dynamic class constant fetchCfg::{$name}
8.3#[\Override] attributeError if the parent has no such method
8.3json_validate()Check JSON without decoding it
8.3str_increment(), mb_str_pad()str_increment('a9') gives b0
8.3DateMalformedStringExceptionThrown by new DateTimeImmutable('nonsense')
8.4Property hooksget and set logic on the property itself (below)
8.4Asymmetric visibilitypublic private(set) int $logins = 0;
8.4new without wrapping bracketsnew Server('h1', 1)->dsn()
8.4array_find(), array_find_key(), array_any(), array_all()array_find($a, fn($n) => $n > 4)
8.4mb_trim(), mb_ucfirst()Multibyte-safe trim and capitalise
8.4#[\Deprecated]Mark your own functions as deprecated
class User {
    public string $email {
        set(string $value) {
            if (!str_contains($value, '@')) throw new ValueError('bad email');
            $this->email = strtolower($value);
        }
    }
    public string $domain { get => substr($this->email, strpos($this->email, '@') + 1); }
}
$u = new User;
$u->email = 'Ann@Example.COM';
echo $u->email, ' ', $u->domain;   // ann@example.com example.com

PHP 8.4 also deprecates implicitly nullable parameters such as function f(string $s = null). Write ?string $s = null instead.

Errors and exceptions

SyntaxWhat it doesExample
try / catch / finallyHandle exceptions; finally always runssee below
catch (A | B $e)Catch several typescatch (InvalidArgumentException | TypeError $e)
ThrowableParent of Exception and Errorcatch (\Throwable $e) in a top-level handler
TypeError, ValueError, DivisionByZeroErrorEngine errors (extend Error, not Exception)intdiv(1, 0)
class ConfigError extends RuntimeException {}Your own exception typethrow new ConfigError("missing DB_HOST");
$e->getMessage(), getCode(), getTraceAsString()Details for loggingerror_log($e->getMessage());
try {
    throw new InvalidArgumentException('bad port', 22);
} catch (InvalidArgumentException | TypeError $e) {
    echo $e->getMessage(), ' ', $e->getCode();
} finally {
    echo "cleanup\n";
}

Files, JSON and the command line

TaskCode
Read a whole file$txt = file_get_contents('/etc/hostname');
Lines as an arrayfile($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
Stream a large filewhile (($line = fgets($fh)) !== false) { … }
Append with a lockfile_put_contents($log, $msg, FILE_APPEND | LOCK_EX);
Decode JSON safelyjson_decode($s, true, flags: JSON_THROW_ON_ERROR)
Encode readable JSONjson_encode($a, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR)
Dates(new DateTimeImmutable('now', new DateTimeZone('UTC')))->format(DATE_ATOM)
Environmentgetenv('DB_HOST')

For server admins: most PHP problems on a hosting server are configuration, not code. These CLI commands answer the usual questions:

CommandWhat it shows
php -vVersion of the CLI binary (on cPanel, /opt/cpanel/ea-php84/root/usr/bin/php -v for a specific EA4 version)
php -l file.phpSyntax check without running the file
php --iniWhich php.ini and extra .ini files are loaded
php -mCompiled and loaded extensions
php -i | grep memory_limitOne setting as the CLI sees it
php -r 'echo PHP_VERSION, "\n";'Run one line of code
php -S 127.0.0.1:8000 -t public/Built-in development server (never for production)

The CLI and the web server can use different PHP versions and different php.ini files. To see what a site really runs, put <?php phpinfo(); in a temporary file, load it once, then delete it.

Official documentation (checked 9 October 2026): PHP manual: types · PHP manual: match · Migrating from PHP 8.3 to 8.4 · PHP 8.4 release announcement · PHP supported versions

PHP Cheat Sheet at a glance

PHP Cheat Sheet – short answer
In short: A compact PHP 8.3 and 8.4 reference with tables for strings, arrays, functions, classes, the newest language features and the PHP command line.
PHP Cheat Sheet – what this guide covers
PHP Cheat Sheet: what this guide covers.

Related: PHP-FPM Calculator: pm.max_children and Spare Servers · JavaScript Cheat Sheet: Modern Syntax for Browser and Node · SQL Cheat Sheet: MySQL, MariaDB and PostgreSQL Syntax.

Reading a lot of our guides? Go ad-free with srvScripts Pro for $6 a month. It also pays for new guides. Cancel any time.

Share this guide

Free website test

Is your website set up right?

Check SSL, security headers, redirects, robots.txt, sitemap, llms.txt and security.txt in one test. It takes about 30 seconds.