Modern PHP Cheat Sheet

6 days ago 12

# Arrays

# Destructuring 7.1

You can destructure arrays to pull out several elements into separate variables:

$array = [1, 2, 3]; // Using the list syntax: list($a, $b, $c) = $array; // Or the shorthand syntax: [$a, $b, $c] = $array;

You can skip elements:

[, , $c] = $array;

As well as destructure based on keys:

$array = [ 'a' => 1, 'b' => 2, 'c' => 3, ]; ['c' => $c, 'a' => $a] = $array;

# Rest and Spread Operators 5.6

Arrays can be spread into functions:

$array = [1, 2]; function foo(int $a, int $b) { } foo(...$array);

Functions can automatically collect the rest of the variables using the same operator:

function foo($first, ...$other) { } foo('a', 'b', 'c', 'd', …);

Rest parameters can even be type hinted:

function foo($first, string ...$other) { } foo('a', 'b', 'c', 'd', …);

7.4 Arrays with numerical keys can also be spread into a new array:

$a = [1, 2]; $b = [3, 4]; $result = [...$a, ...$b];

8.1 You can also spread arrays with textual keys starting from PHP 8.1

# Attributes 8.0

Make your own by tagging a class with

class ListensTo { public string $event; public function __construct(string $event) { $this->event = $event; } }

You can add them to properties, (anonymous) classes, functions, constants, closures, function arguments:

Route(Http::POST, '/products/create'), Autowire, class ProductsCreateController { public function __invoke() { } }

Use reflection to get them, you can pass in optional arguments to `

getAttributes

` in order to filter the result:

$attributes = $reflectionClass->getAttributes( ContainerAttribute::class, ReflectionAttribute::IS_INSTANCEOF );

# Closures

# Short Closures 7.4

Short closures have automatic access to the outer scope, and only allow a single expression which is automatically returned:

array_map( fn($x) => $x * $this->modifier, $numbers );

# First class callables 8.1

You can now make a closure from a callable by calling that callable and passing it '...' as its argument

function foo(int $a, int $b) { /* … */ } $foo = foo(...); $foo(a: 1, b: 2);

# Cosmetics

# Class Names 8.0

As of PHP 8, you can use ::class on objects as well:

Order::class; $object::class;

# Numeric Values 7.4

Use the _ operator to format numeric values:

$price = 100_10;

# Trailing Commas 8.0

Trailing commas are allowed in several places:

  • Arrays
  • Function calls
  • Function definitions
  • Closure use statements

# Enums

# Declaring Enums 8.1

Enums are built-in in the language:

enum Status { case DRAFT; case PUBLISHED; case ARCHIVED; }

# Enum methods 8.1

Enums can have methods, as well as have a string or integer value per case:

enum Status: int { case DRAFT = 1; case PUBLISHED = 2; case ARCHIVED = 3; public function color(): string { return match($this) { Status::DRAFT => 'grey', Status::PUBLISHED => 'green', Status::ARCHIVED => 'red', }; } }

# Exceptions 8.0

Throwing an exception is an expression now, which means there are more places you can throw from, such as short closures or as a null coalescing fallback:

$error = fn($message) => throw new Error($message); $input = $data['input'] ?? throw new Exception('Input not set');

You also don't have to catch an exception with a variable anymore:

try { } catch (SpecificException) { throw new OtherException(); }

# Match 8.0

Similar to switch, but with strong type checks, no break keyword, combined arms and it returns a value:

$message = match ($statusCode) { 200, 300 => null, 400 => 'not found', 500 => 'server error', default => 'unknown status code', };

# Dealing with null

# Null Coalescing 7.0

Use the null coalescing operator to provide a fallback when a property is null:

$paymentDate = $invoice->paymentDate ?? Date::now();

It also works nested:

$input = $data['few']['levels']['deep'] ?? 'foo';

7.4

You can use the null coalescing assignment operator to write the value into the original variable when it's null:

$temporaryPaymentDate = $invoice->paymentDate ??= Date::now();

# Nullsafe Operator 8.0

Chain methods that possibly return null:

$invoice ->getPaymentDate() ?->format('Y-m-d');

The nullsafe operator can also be chained multiple times:

$object ?->methodA() ?->methodB() ?->methodC();

# Named Arguments 8.0

Pass in arguments by name instead of their position:

setcookie( name: 'test', expires: time() + 60 * 60 * 2, );

Named arguments also support array spreading:

$data = [ 'name' => 'test', 'expires' => time() + 60 * 60 * 2, ]; setcookie(...$data);

# Performance

# The JIT 8.0

Enable the JIT by specifying a buffer size in your ini settings; you can switch the jit mode between function or tracing:

opcache.jit_buffer_size=100M opcache.jit=function

# Preloading 7.4

Add opcache.preload to your ini settings:

opcache.preload=/path​/to​/project​/preload.php

Every file that's loaded in the preload script will be preloaded into memory until server restart.

# Properties

# Using new in initializers 8.1

PHP 8.1 allows you to use the new keyword in function definitions as a default parameter, as well as in attribute arguments and other places.

class MyController { public function __construct( private Logger $logger = new NullLogger(), ) {} }

This also means that nested attributes are a thing now:

#[Assert\All( new Assert\NotNull, new Assert\Length(max: 6),

# Read only properties 8.1

Properties can be marked readonly.

class Offer { public readonly ?string $offerNumber = null; public readonly Money $totalPrice;

Once a readonly property is set, it cannot change ever again.

# Types

# Built-in Types

During the PHP 7.x releases and with PHP 8, several new built-in types were added:

  • void: a return type indicating nothing's returned 7.1
  • static: a return type representing the current class or its children 8.0
  • object: anything that is an object 7.2
  • mixed: anything 8.0

# Intersection Types 8.1

Combine several types into one intersection, which means that whatever input must match all of the given types

public function url(WithId&WithSlug $obj): string;

# Typed properties 7.4

Add types to your class properties:

class Offer { public ?string $offerNumber = null; public Money $totalPrice; }

Beware of the uninitialized state, which is only checked when reading a property, and not when constructing the class:

$offer = new Offer(); $offer->totalPrice;

# Union Types 8.0

Combine several types into one union, which means that whatever input must match one of the given types:

interface Repository { public function find(int|string $id); }
Read Entire Article