PHP Modern Features
Use when modern PHP features including typed properties, union types, match expressions, named arguments, attributes, enums, and patterns for writing type-safe, expressive PHP code with latest language improvements.
What this skill does
# PHP Modern Features
## Introduction
Modern PHP (7.4+, 8.0+, 8.1+, 8.2+) has evolved dramatically with features that
improve type safety, expressiveness, and developer experience. These additions
transform PHP from a loosely-typed scripting language into a powerful,
type-safe platform for building robust applications.
Key improvements include strict typing, property and parameter types, union and
intersection types, match expressions, named arguments, attributes (annotations),
enumerations, and readonly properties. These features enable clearer intent,
better IDE support, and fewer runtime errors.
This skill covers typed properties, union/intersection types, match expressions,
enums, attributes, named arguments, and patterns for leveraging modern PHP
effectively.
## Typed Properties and Parameters
Type declarations improve code reliability by enforcing types at runtime and
enabling better static analysis.
```php
<?php
// PHP 7.4+ typed properties
class User {
public string $name;
public int $age;
public ?string $email = null; // Nullable
private array $roles = [];
protected bool $active = true;
}
$user = new User();
$user->name = "Alice"; // OK
$user->age = 30; // OK
// $user->age = "thirty"; // TypeError
// Constructor property promotion (PHP 8.0+)
class Product {
public function __construct(
public string $name,
public float $price,
public int $stock,
private ?string $sku = null
) {}
}
$product = new Product("Laptop", 999.99, 10);
echo $product->name; // "Laptop"
// echo $product->sku; // Error: private property
// Return type declarations
function calculateTotal(float $price, int $quantity): float {
return $price * $quantity;
}
function findUser(int $id): ?User {
// Return User or null
return $id > 0 ? new User() : null;
}
function getUsers(): array {
return [new User(), new User()];
}
// Void return type
function logMessage(string $message): void {
echo $message . "\n";
}
// Never return type (PHP 8.1+)
function fail(string $message): never {
throw new Exception($message);
}
// Mixed type (PHP 8.0+)
function process(mixed $value): mixed {
return $value;
}
// Static return type
class Builder {
public function setName(string $name): static {
return $this;
}
public function build(): static {
return new static();
}
}
// Parameter types
function greet(
string $name,
int $age,
bool $formal = false
): string {
$greeting = $formal ? "Good day" : "Hello";
return "$greeting, $name ($age)";
}
// Variadic typed parameters
function sum(int ...$numbers): int {
return array_sum($numbers);
}
$total = sum(1, 2, 3, 4, 5); // 15
```
Typed properties and parameters catch type errors early and provide clear
contracts for function interfaces.
## Union and Intersection Types
Union types allow multiple type possibilities, while intersection types require
all specified types simultaneously.
```php
<?php
// Union types (PHP 8.0+)
function processId(int|string $id): void {
if (is_int($id)) {
echo "Processing integer ID: $id\n";
} else {
echo "Processing string ID: $id\n";
}
}
processId(123);
processId("ABC-456");
// Union type properties
class Response {
public function __construct(
public int|string $code,
public array|string $data
) {}
}
// Nullable as union type
function findProduct(int $id): Product|null {
return $id > 0 ? new Product("Item", 10.0, 5) : null;
}
// Multiple union types
function format(int|float|string $value): string {
return match (true) {
is_int($value) => "Integer: $value",
is_float($value) => "Float: $value",
is_string($value) => "String: $value",
};
}
// False pseudo-type in unions
function parseValue(string $input): int|false {
$result = filter_var($input, FILTER_VALIDATE_INT);
return $result !== false ? $result : false;
}
// Union types with built-in types
function getData(): array|object|null {
return ['key' => 'value'];
}
// Intersection types (PHP 8.1+)
interface Loggable {
public function log(): void;
}
interface Cacheable {
public function cache(): void;
}
// Function accepting intersection type
function process(Loggable&Cacheable $object): void {
$object->log();
$object->cache();
}
class Service implements Loggable, Cacheable {
public function log(): void {
echo "Logging\n";
}
public function cache(): void {
echo "Caching\n";
}
}
// Intersection with union
function handle((Loggable&Cacheable)|null $object): void {
$object?->log();
}
// DNF types (PHP 8.2+ - Disjunctive Normal Form)
function advanced((Loggable&Cacheable)|(Loggable&Serializable) $object): void {
$object->log();
}
```
Union types enable flexible parameter acceptance while intersection types
enforce multiple capabilities simultaneously.
## Match Expressions
Match expressions provide pattern matching with strict comparisons and
exhaustive checking, improving upon switch statements.
```php
<?php
// Basic match expression (PHP 8.0+)
$status = 200;
$message = match ($status) {
200 => "OK",
404 => "Not Found",
500 => "Server Error",
default => "Unknown",
};
echo $message; // "OK"
// Multiple conditions
$result = match ($status) {
200, 201, 202 => "Success",
400, 401, 403 => "Client Error",
500, 502, 503 => "Server Error",
default => "Unknown",
};
// Match with expressions
$age = 25;
$category = match (true) {
$age < 13 => "Child",
$age < 18 => "Teen",
$age < 65 => "Adult",
default => "Senior",
};
// Match without default (throws on no match)
function getColor(string $type): string {
return match ($type) {
'primary' => '#007bff',
'success' => '#28a745',
'danger' => '#dc3545',
// Missing default throws UnhandledMatchError
};
}
// Match with complex expressions
enum Status {
case Draft;
case Published;
case Archived;
}
function canEdit(Status $status): bool {
return match ($status) {
Status::Draft => true,
Status::Published => false,
Status::Archived => false,
};
}
// Match returning different types
function process(mixed $value): int|string {
return match (gettype($value)) {
'integer' => $value * 2,
'string' => strtoupper($value),
'array' => count($value),
default => 0,
};
}
// Match vs switch strict comparison
$value = "1";
// Switch uses == (loose)
switch ($value) {
case 1:
echo "Matches with switch\n"; // Prints
break;
}
// Match uses === (strict)
$result = match ($value) {
1 => "Matches with match",
"1" => "Strict match", // This matches
default => "No match",
};
echo $result; // "Strict match"
```
Match expressions are safer than switch due to strict comparison and exhaustive
checking requirements.
## Enumerations
Enums provide type-safe sets of possible values, replacing magic strings and
constants with explicit types.
```php
<?php
// Basic enum (PHP 8.1+)
enum Status {
case Pending;
case Approved;
case Rejected;
}
function updateOrder(Status $status): void {
echo "Order status: " . $status->name . "\n";
}
updateOrder(Status::Approved);
// Backed enum with values
enum Priority: int {
case Low = 1;
case Medium = 2;
case High = 3;
case Critical = 4;
}
$priority = Priority::High;
echo $priority->value; // 3
echo $priority->name; // "High"
// String-backed enum
enum Role: string {
case Admin = 'admin';
case User = 'user';
case Guest = 'guest';
}
// Enum methods
enum HttpStatus: int {
case OK = 200;
case Created = 201;
case BadRequest = 400;
case Unauthorized = 401;
case NotFound = 404;
case ServerError = 500;
public function isSuccess(): bool {
return $this->value >= 200 && $this->value < 300;
}
public function isError(): bool {
Related in Writing & Docs
jax-development
IncludedUse this skill when the user is writing, debugging, profiling, refactoring, reviewing, benchmarking, parallelising, exporting, or explaining JAX code, or when they mention JAX, jax.numpy, jit, grad, value_and_grad, vmap, scan, lax, random keys, pytrees, jax.Array, sharding, Mesh, PartitionSpec, NamedSharding, pmap, shard_map, Pallas, XLA, StableHLO, checkify, profiler, or the JAX repo. It helps turn NumPy or PyTorch-style code into pure functional JAX, fix tracer/control-flow/shape/PRNG bugs, remove recompiles and host-device syncs, choose transforms and sharding strategies, inspect jaxpr/lowering/IR, and benchmark compiled code correctly.
nature-article-writer
IncludedDrafts, rewrites, diagnostically critiques, and style-calibrates primary research manuscripts for Nature and Nature Portfolio journals. Use when the user wants a Nature-style title, summary paragraph or abstract, introduction, results, discussion, methods, figure legends, presubmission enquiry, cover letter, reviewer response, or when a scientific draft sounds generic, jargon-heavy, structurally weak, or AI-ish and needs precise, broad-reader-friendly prose without inventing data, analyses, or references. Best for primary research articles and letters rather than reviews or press releases unless explicitly adapting one.
deckrd
IncludedDocument-driven framework that derives requirements, specifications, implementation plans, and executable tasks from goals through structured AI dialogue. Use when user says "write requirements", "create spec", "plan implementation", "derive tasks", "structure this feature", "break down into tasks", or "document this module". Also use for reverse engineering existing code into docs (/deckrd rev). Do NOT use for direct code writing — use /deckrd-coder after tasks are generated. Do NOT use when the user only wants to run or fix existing code without planning.
clinical-decision-support
IncludedGenerate professional clinical decision support (CDS) documents for pharmaceutical and clinical research settings, including patient cohort analyses (biomarker-stratified with outcomes) and treatment recommendation reports (evidence-based guidelines with decision algorithms). Supports GRADE evidence grading, statistical analysis (hazard ratios, survival curves, waterfall plots), biomarker integration, and regulatory compliance. Outputs publication-ready LaTeX/PDF format optimized for drug development, clinical research, and evidence synthesis.
handling-sf-data
IncludedSalesforce data operations with 130-point scoring. Use this skill to create, update, delete, bulk import/export, generate test data, and clean up org records using sf CLI and anonymous Apex. TRIGGER when: user creates test data, performs bulk import/export, uses sf data CLI commands, needs data factory patterns for Apex tests, or needs to seed/clean records in a Salesforce org. DO NOT TRIGGER when: SOQL query writing only (use querying-soql), Apex test execution (use running-apex-tests), or metadata deployment (use deploying-metadata).
accelint-ac-to-playwright
IncludedConvert and validate acceptance criteria for Playwright test automation. Use when user asks to (1) review/evaluate/check if AC are ready for automation, (2) assess if AC can be converted as-is, (3) validate AC quality for Playwright, (4) turn AC into tests, (5) generate tests from acceptance criteria, (6) convert .md bullets or .feature Gherkin files to Playwright specs, (7) create test automation from requirements. Handles both bullet-style markdown and Gherkin syntax with JSON test plan generation and validation.