# PHP Cheat Sheet: PHP 8.3 and 8.4 Syntax and Functions

Source: https://srvscripts.com/guides/php-cheat-sheet/
Updated: 2026-10-09
Publisher: srvScripts (https://srvscripts.com/)

**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

| Syntax | What it does | Example |
| --- | --- | --- |
| $name = "web01"; | Variables start with $; no declaration needed | $port = 8080; |
| "…$var…" / '…' | Double quotes interpolate; single quotes are literal | "Host {$name}:{$port}" |
|  '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 value | array_map(fn($n) => $n * 2, $a) |
| array_filter() | Keep matching values; keys are preserved | array_values(array_filter($a)) to reindex |
| array_reduce() | Fold to one value | array_reduce($a, fn($c, $i) => $c + $i, 0) |
| array_column() | One field from a list of rows, optional key | array_column($users, 'age', 'name') |
| in_array($x, $a, true) | Search values; pass true for strict | in_array(3, $ids, true) |
| array_key_exists() vs isset() | isset is false when the value is null | array_key_exists('ttl', $cfg) |
| array_merge() vs + | Merge overwrites string keys; + keeps the left value | $cfg + $defaults |
| sort, rsort, asort, ksort, usort | Sort in place (asort/ksort keep keys) | ksort($cfg); |
| array_slice(), array_chunk(), array_unique() | Slice, batch, de-duplicate | array_chunk($ids, 100) |
| array_is_list() | True for keys 0, 1, 2… in order | array_is_list([1, 2]) |

## Control flow and match

| Syntax | What it does | Example |
| --- | --- | --- |
| if / elseif / else | Conditionals | if ($code >= 500) { … } |
| match | Expression with strict comparison, no fall-through, returns a value | see below |
| switch | Loose comparison, needs break | Legacy code |
| foreach ($a as $k => $v) | Iterate an array or iterable | foreach ($cfg as $key => $val) |
| for, while, do … while | Classic loops | for ($i = 0; $i < 3; $i++) |
| break / continue | Leave or skip; break 2 leaves two loops | if ($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

| Syntax | What it does | Example |
| --- | --- | --- |
| function f(int $n): string | Typed parameters and return | function greet(string $name): string |
| $x = "Hello" in the signature | Default value | function greet(string $n, string $g = "Hello") |
| Named arguments | Pass by name, in any order | greet(greeting: "Hi", name: "Ann") |
| int ...$nums | Variadic parameter | total(...[4, 5]) unpacks an array |
| ?int, int|string | Nullable and union types | function f(?int $n): int|string |
| void, never, static | No return value / never returns / late static binding | function fail(): never { throw … } |
| function () use ($x) {} | Closure; captures by value (use (&$x) by reference) | $mul = function ($n) use ($f) { … }; |
| fn($n) => $n * $f | Arrow function: one expression, captures automatically | array_map(fn($n) => $n * $f, $a) |
| strlen(...) | First-class callable from any function or method | $len = strlen(...); |
| array &$arr | Pass by reference | function 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
```

| Feature | Syntax | Note |
| --- | --- | --- |
| Constructor promotion | public function __construct(private int $port) {} | Declares and assigns in one place |
| Readonly property | public readonly string $host | Set once, inside the class; writing again throws Error |
| Readonly class | readonly class Point { … } | Every property is readonly (8.2+) |
| Enum | enum Suit { case Hearts; } | Suit::Hearts->name, Suit::cases() |
| Backed enum | enum Status: string | from() throws on bad input, tryFrom() returns null |
| Interface, abstract, trait | interface, abstract class, use Logs; | Traits copy methods into a class |
| Nullsafe operator | $user?->profile?->email | Returns null instead of an error on null |
| Static factory | public static function local(): static | new static(…) respects subclasses |

## What is new in PHP 8.3 and 8.4

| Version | Feature | Example |
| --- | --- | --- |
| 8.3 | Typed class constants | const string VERSION = '1.0'; |
| 8.3 | Dynamic class constant fetch | Cfg::{$name} |
| 8.3 | #[\Override] attribute | Error if the parent has no such method |
| 8.3 | json_validate() | Check JSON without decoding it |
| 8.3 | str_increment(), mb_str_pad() | str_increment('a9') gives b0 |
| 8.3 | DateMalformedStringException | Thrown by new DateTimeImmutable('nonsense') |
| 8.4 | Property hooks | get and set logic on the property itself (below) |
| 8.4 | Asymmetric visibility | public private(set) int $logins = 0; |
| 8.4 | new without wrapping brackets | new Server('h1', 1)->dsn() |
| 8.4 | array_find(), array_find_key(), array_any(), array_all() | array_find($a, fn($n) => $n > 4) |
| 8.4 | mb_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

| Syntax | What it does | Example |
| --- | --- | --- |
| try / catch / finally | Handle exceptions; finally always runs | see below |
| catch (A | B $e) | Catch several types | catch (InvalidArgumentException | TypeError $e) |
| Throwable | Parent of Exception and Error | catch (\Throwable $e) in a top-level handler |
| TypeError, ValueError, DivisionByZeroError | Engine errors (extend Error, not Exception) | intdiv(1, 0) |
| class ConfigError extends RuntimeException {} | Your own exception type | throw new ConfigError("missing DB_HOST"); |
| $e->getMessage(), getCode(), getTraceAsString() | Details for logging | error_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

| Task | Code |
| --- | --- |
| Read a whole file | $txt = file_get_contents('/etc/hostname'); |
| Lines as an array | file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) |
| Stream a large file | while (($line = fgets($fh)) !== false) { … } |
| Append with a lock | file_put_contents($log, $msg, FILE_APPEND | LOCK_EX); |
| Decode JSON safely | json_decode($s, true, flags: JSON_THROW_ON_ERROR) |
| Encode readable JSON | json_encode($a, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR) |
| Dates | (new DateTimeImmutable('now', new DateTimeZone('UTC')))->format(DATE_ATOM) |
| Environment | getenv('DB_HOST') |

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

| Command | What it shows |
| --- | --- |
| php -v | Version of the CLI binary (on cPanel, /opt/cpanel/ea-php84/root/usr/bin/php -v for a specific EA4 version) |
| php -l file.php | Syntax check without running the file |
| php --ini | Which php.ini and extra .ini files are loaded |
| php -m | Compiled and loaded extensions |
| php -i | grep memory_limit | One 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](https://www.php.net/manual/en/language.types.php) · [PHP manual: match](https://www.php.net/manual/en/control-structures.match.php) · [Migrating from PHP 8.3 to 8.4](https://www.php.net/manual/en/migration84.php) · [PHP 8.4 release announcement](https://www.php.net/releases/8.4/en.php) · [PHP supported versions](https://www.php.net/supported-versions.php)

## PHP Cheat Sheet at a glance

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.

**Related:** [PHP-FPM Calculator: pm.max_children and Spare Servers](https://srvscripts.com/tools/php-fpm-calculator/) · [JavaScript Cheat Sheet: Modern Syntax for Browser and Node](https://srvscripts.com/guides/javascript-cheat-sheet/) · [SQL Cheat Sheet: MySQL, MariaDB and PostgreSQL Syntax](https://srvscripts.com/guides/sql-cheat-sheet/).
