Toolmingo
Guides12 min read

PHP Cheat Sheet: The Complete Quick Reference

A complete PHP cheat sheet — syntax, arrays, strings, OOP, error handling, database access, Composer, and modern PHP 8 patterns with ready-to-use examples.

The PHP syntax you forget between projects — and the modern PHP 8 patterns you need every day. This reference covers variables, arrays, strings, OOP, PDO, Composer, and more.

Quick reference

The 25 patterns that cover 90% of daily PHP work.

Pattern Example
Variable $name = "Alice";
String interpolation "Hello, $name!"
Null coalescing $val = $arr['key'] ?? 'default';
Ternary $x = $a > 0 ? 'pos' : 'non-pos';
Nullsafe operator $city = $user?->address?->city;
Named arguments array_slice(array: $arr, offset: 2);
Match expression $label = match($code) { 200 => 'OK', ... };
Spread operator $merged = [...$a, ...$b];
Arrow function $double = fn($x) => $x * 2;
Array destructuring [$first, $second] = $arr;
List by key ['name' => $n, 'age' => $a] = $row;
Short closure $fn = fn($x, $y) => $x + $y;
Type declaration function add(int $a, int $b): int
Union types function foo(int|string $val): void
Readonly property public readonly string $name;
Constructor promotion public function __construct(private string $name)
Enum enum Status { case Active; case Inactive; }
Fibers $fiber = new Fiber(fn() => ...);
str_contains str_contains($str, 'needle')
array_is_list array_is_list([1, 2, 3]) // true
PDO query $stmt = $pdo->prepare("SELECT ...");
json_encode echo json_encode($data, JSON_PRETTY_PRINT);
array_map $doubled = array_map(fn($x) => $x * 2, $arr);
array_filter $evens = array_filter($arr, fn($x) => $x % 2 === 0);
array_reduce $sum = array_reduce($arr, fn($c, $x) => $c + $x, 0);

Variables and types

<?php
// Scalar types
$int    = 42;
$float  = 3.14;
$string = "Hello";
$bool   = true;
$null   = null;

// Type juggling — be explicit with strict_types
declare(strict_types=1);

// Type checking
gettype($int);          // "integer"
is_int($int);           // true
is_string($string);     // true
is_null($null);         // true

// Type casting
$str  = (string) 42;    // "42"
$num  = (int) "42abc";  // 42
$bool = (bool) "";       // false

// Constants
const MAX_SIZE = 100;
define('API_URL', 'https://example.com');

PHP 8 adds union types, intersection types, and never return type:

function processId(int|string $id): void { /* ... */ }

function fail(): never {
    throw new \RuntimeException("Always fails");
}

Strings

$s = "Hello, World!";

// Length and case
strlen($s);              // 13
strtoupper($s);          // "HELLO, WORLD!"
strtolower($s);          // "hello, world!"
ucfirst("hello");        // "Hello"
ucwords("hello world");  // "Hello World"

// Search and replace
strpos($s, "World");             // 7 (false if not found)
str_contains($s, "World");       // true  (PHP 8+)
str_starts_with($s, "Hello");    // true  (PHP 8+)
str_ends_with($s, "World!");     // true  (PHP 8+)
str_replace("World", "PHP", $s); // "Hello, PHP!"

// Extract and pad
substr($s, 7, 5);        // "World"
str_pad("5", 3, "0", STR_PAD_LEFT);  // "005"
trim("  hello  ");       // "hello"
ltrim(" hi");            // "hi"
rtrim("hi ");            // "hi"

// Split and join
$parts = explode(",", "a,b,c");  // ["a","b","c"]
implode("-", $parts);             // "a-b-c"

// Regex
preg_match('/\d+/', $s, $m);         // $m[0] = first match
preg_match_all('/\d+/', $s, $m);     // $m[0] = all matches
preg_replace('/\s+/', ' ', $s);      // collapse whitespace
preg_split('/[\s,]+/', "a b,c");     // ["a","b","c"]

// Formatting
number_format(1234567.89, 2, '.', ',');  // "1,234,567.89"
sprintf("%.2f", 3.14159);               // "3.14"
printf("Hello, %s! You are %d.\n", "Alice", 30);

// Heredoc (interpolation) and Nowdoc (no interpolation)
$text = <<<EOT
Hello, $name!
This is a heredoc.
EOT;

$raw = <<<'EOT'
No $interpolation here.
EOT;

Arrays

PHP arrays serve as lists, maps, and everything in between.

// Indexed array
$fruits = ["apple", "banana", "cherry"];
$fruits[] = "date";           // append
count($fruits);               // 4
$fruits[0];                   // "apple"

// Associative array (map)
$user = ["name" => "Alice", "age" => 30];
$user["email"] = "alice@example.com";

// Multi-dimensional
$matrix = [[1, 2], [3, 4]];
$matrix[0][1]; // 2

// Destructuring
[$first, $second] = $fruits;
["name" => $name, "age" => $age] = $user;

// Common functions
in_array("apple", $fruits);              // true
array_search("banana", $fruits);         // 1
array_key_exists("name", $user);         // true
isset($user["email"]);                   // true

// Add / remove
array_push($fruits, "elderberry");       // append (prefer $arr[])
array_pop($fruits);                      // remove last
array_unshift($fruits, "avocado");       // prepend
array_shift($fruits);                    // remove first
array_splice($fruits, 1, 1, ["berry"]); // replace at index

// Sort
sort($fruits);                           // reindex
rsort($fruits);                          // reverse reindex
asort($fruits);                          // preserve keys
arsort($fruits);                         // reverse, preserve keys
ksort($user);                            // sort by key
usort($arr, fn($a, $b) => $a - $b);     // custom sort

// Transform
$doubled = array_map(fn($x) => $x * 2, [1, 2, 3]);   // [2, 4, 6]
$evens   = array_filter([1,2,3,4], fn($x) => $x%2===0); // [2, 4]
$sum     = array_reduce([1,2,3], fn($c,$x) => $c+$x, 0); // 6

// Slice, splice, combine
$slice = array_slice($fruits, 1, 2);     // 2 items from index 1
$merged = array_merge($fruits, ["fig"]);
$keys   = array_keys($user);             // ["name","age","email"]
$vals   = array_values($user);           // values reindexed
$unique = array_unique([1, 2, 2, 3]);    // [1, 2, 3]
$flipped = array_flip(["a"=>1,"b"=>2]); // [1=>"a", 2=>"b"]

// Spread (PHP 8.1+: string keys too)
$a = [1, 2, 3];
$b = [4, 5, 6];
$c = [...$a, ...$b]; // [1,2,3,4,5,6]

Control flow

// if / elseif / else
if ($x > 0) {
    echo "positive";
} elseif ($x < 0) {
    echo "negative";
} else {
    echo "zero";
}

// Match expression (PHP 8) — strict, no fall-through
$label = match(true) {
    $score >= 90 => 'A',
    $score >= 80 => 'B',
    $score >= 70 => 'C',
    default      => 'F',
};

// Switch (legacy, loose comparison)
switch ($status) {
    case 'active':
        // ...
        break;
    case 'inactive':
    case 'banned':
        // fall-through
        break;
    default:
        // ...
}

// Loops
for ($i = 0; $i < 10; $i++) { /* ... */ }

foreach ($fruits as $fruit) { /* ... */ }
foreach ($user as $key => $value) { /* ... */ }

while ($condition) { /* ... */ }
do { /* ... */ } while ($condition);

// Loop controls
break 2;    // break out of 2 nested loops
continue;   // next iteration

// Null coalescing assignment (PHP 7.4+)
$arr['key'] ??= 'default';

Functions

// Basic function with types (PHP 8)
function add(int $a, int $b): int {
    return $a + $b;
}

// Default parameters
function greet(string $name, string $greeting = "Hello"): string {
    return "$greeting, $name!";
}

// Variadic arguments
function sum(int ...$nums): int {
    return array_sum($nums);
}
sum(1, 2, 3, 4); // 10

// Named arguments (PHP 8)
function createUser(string $name, int $age = 0, string $role = 'user'): array {
    return compact('name', 'age', 'role');
}
createUser(name: 'Alice', role: 'admin'); // skip $age

// Return type: void, never, mixed, self
function logMessage(string $msg): void {
    error_log($msg);
    // no return value
}

// Closures
$multiply = function(int $x, int $y): int {
    return $x * $y;
};

// Arrow functions (single-expression, inherit scope)
$factor = 3;
$triple = fn($x) => $x * $factor; // captures $factor automatically
$triple(5); // 15

// Closure binding — use keyword for closures
$add = function(int $n) use ($factor): int {
    return $n + $factor;
};

OOP — Classes and interfaces

// Class with constructor promotion (PHP 8)
class User {
    public function __construct(
        public readonly int    $id,
        public string          $name,
        private string         $email,
        protected int          $age = 0,
    ) {}

    // Getter
    public function getEmail(): string {
        return $this->email;
    }

    // Static method
    public static function fromArray(array $data): static {
        return new static($data['id'], $data['name'], $data['email']);
    }

    // Magic methods
    public function __toString(): string {
        return "User({$this->name})";
    }
}

$user = new User(1, 'Alice', 'alice@example.com');
echo $user->name;       // Alice
echo $user->getEmail(); // alice@example.com
echo $user;             // User(Alice)

// Inheritance
class Admin extends User {
    public function __construct(
        int $id,
        string $name,
        string $email,
        public readonly string $role = 'admin',
    ) {
        parent::__construct($id, $name, $email);
    }
}

// Interface
interface Serializable {
    public function serialize(): string;
    public function unserialize(string $data): void;
}

// Abstract class
abstract class Shape {
    abstract public function area(): float;

    public function describe(): string {
        return sprintf("%s with area %.2f", static::class, $this->area());
    }
}

class Circle extends Shape {
    public function __construct(private float $radius) {}

    public function area(): float {
        return M_PI * $this->radius ** 2;
    }
}

// Traits
trait Timestamps {
    private \DateTimeImmutable $createdAt;
    private \DateTimeImmutable $updatedAt;

    public function touch(): void {
        $this->updatedAt = new \DateTimeImmutable();
    }
}

class Post {
    use Timestamps;
    // ...
}

Enums (PHP 8.1)

// Pure enum
enum Status {
    case Active;
    case Inactive;
    case Banned;
}

$s = Status::Active;
$s === Status::Active; // true
$s->name;             // "Active"

// Backed enum (int or string)
enum Color: string {
    case Red   = 'red';
    case Green = 'green';
    case Blue  = 'blue';

    public function label(): string {
        return ucfirst($this->value);
    }
}

Color::Red->value;          // "red"
Color::from('green');       // Color::Green
Color::tryFrom('purple');   // null (no exception)
Color::cases();             // [Color::Red, Color::Green, Color::Blue]

// Enums implement interfaces
enum Suit: string implements \JsonSerializable {
    case Hearts   = 'H';
    case Diamonds = 'D';
    case Clubs    = 'C';
    case Spades   = 'S';

    public function jsonSerialize(): string {
        return $this->value;
    }
}

Error handling

// try / catch / finally
try {
    $result = riskyOperation();
} catch (\InvalidArgumentException $e) {
    echo "Bad input: " . $e->getMessage();
} catch (\RuntimeException|\LogicException $e) {
    echo "App error: " . $e->getMessage();
} catch (\Throwable $e) {
    // Catches all exceptions AND errors (PHP 7+)
    error_log($e);
    throw $e; // re-throw
} finally {
    // Always runs
    cleanup();
}

// Custom exception
class ValidationException extends \RuntimeException {
    public function __construct(
        string $message,
        private readonly array $errors = [],
        int $code = 0,
        ?\Throwable $previous = null,
    ) {
        parent::__construct($message, $code, $previous);
    }

    public function getErrors(): array {
        return $this->errors;
    }
}

// Throw as expression (PHP 8)
$value = $input ?? throw new \InvalidArgumentException("Input required");

// Error reporting
error_reporting(E_ALL);
ini_set('display_errors', '0');     // never show in production
ini_set('log_errors', '1');
ini_set('error_log', '/var/log/php/error.log');

// Set a global exception handler
set_exception_handler(function (\Throwable $e): void {
    error_log("Unhandled: " . $e);
    http_response_code(500);
    echo json_encode(['error' => 'Server error']);
    exit(1);
});

Database with PDO

Always use PDO with prepared statements — never concatenate user input into SQL.

// Connect (DSN: driver:host=...;dbname=...;charset=utf8mb4)
$pdo = new \PDO(
    'mysql:host=localhost;dbname=myapp;charset=utf8mb4',
    'dbuser',
    'secret',
    [
        \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
        \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
        \PDO::ATTR_EMULATE_PREPARES   => false,
    ]
);

// SELECT — fetch all rows
$stmt = $pdo->prepare("SELECT * FROM users WHERE active = :active");
$stmt->execute(['active' => 1]);
$users = $stmt->fetchAll();                     // array of assoc arrays

// SELECT — fetch single row
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
$user = $stmt->fetch();                         // assoc array | false

// Fetch as object
$stmt->setFetchMode(\PDO::FETCH_CLASS, User::class);
$user = $stmt->fetch();                         // User instance

// INSERT
$stmt = $pdo->prepare(
    "INSERT INTO users (name, email, created_at) VALUES (?, ?, NOW())"
);
$stmt->execute([$name, $email]);
$newId = $pdo->lastInsertId();

// UPDATE
$stmt = $pdo->prepare("UPDATE users SET name = ? WHERE id = ?");
$stmt->execute([$newName, $id]);
$rowCount = $stmt->rowCount();                  // rows affected

// DELETE
$stmt = $pdo->prepare("DELETE FROM users WHERE id = ?");
$stmt->execute([$id]);

// Transaction
$pdo->beginTransaction();
try {
    $pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?")
        ->execute([$amount, $fromId]);
    $pdo->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?")
        ->execute([$amount, $toId]);
    $pdo->commit();
} catch (\Throwable $e) {
    $pdo->rollBack();
    throw $e;
}

Working with JSON, files, and HTTP

// JSON
$data = ['name' => 'Alice', 'scores' => [95, 87, 92]];
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);

$decoded = json_decode($json, associative: true); // assoc array
$obj     = json_decode($json);                    // stdClass

// Always check for errors
if (json_last_error() !== JSON_ERROR_NONE) {
    throw new \RuntimeException("JSON error: " . json_last_error_msg());
}

// Files
$content  = file_get_contents('/path/to/file.txt');
file_put_contents('/path/to/out.txt', $content);    // overwrite
file_put_contents('/path/to/log.txt', "line\n", FILE_APPEND);

// Read line by line (memory-efficient)
$handle = fopen('/path/to/big.csv', 'r');
while (($line = fgets($handle)) !== false) {
    // process $line
}
fclose($handle);

// CSV
$rows = array_map('str_getcsv', file('/path/to/data.csv'));

// HTTP request with cURL
function httpGet(string $url, array $headers = []): string {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_TIMEOUT        => 10,
        CURLOPT_HTTPHEADER     => $headers,
    ]);
    $response = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($response === false || $code >= 400) {
        throw new \RuntimeException("HTTP $code for $url");
    }
    return $response;
}

$body = httpGet('https://api.example.com/data', [
    'Authorization: Bearer ' . $token,
    'Accept: application/json',
]);
$data = json_decode($body, true);

Composer and autoloading

# Install Composer (one-time)
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

# Create project
composer init
composer require guzzlehttp/guzzle
composer require --dev phpunit/phpunit

# Install dependencies
composer install          # installs from composer.lock
composer update           # updates and rewrites composer.lock

# Autoload
composer dump-autoload

Your composer.json autoload section:

{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

Then in PHP:

require_once __DIR__ . '/vendor/autoload.php';

use App\Models\User;
use App\Services\UserService;

Common mistakes

Mistake What happens Fix
== instead of === 0 == "foo" is true in PHP 7, loose comparison surprises Use === for comparisons
Concatenating user input into SQL SQL injection vulnerability Always use PDO prepared statements
mysql_* functions Removed in PHP 7 Use PDO or MySQLi
json_decode without assoc flag Returns stdClass, not array Pass associative: true
strlen() on multibyte strings Counts bytes, not chars Use mb_strlen()
array_map ignoring keys Returns reindexed array Use array_combine(array_keys($in), array_map(...)) to preserve keys
die() / exit() in library code Prevents caller from handling errors Throw exceptions instead

PHP 8 features quick reference

Feature PHP version Example
Named arguments 8.0 fn(arg: $val)
Match expression 8.0 match($x) { 1 => 'one' }
Nullsafe operator 8.0 $obj?->method()
Union types 8.0 int|string
str_contains/starts_with/ends_with 8.0 Built-in string helpers
Fibers 8.1 Cooperative multitasking
Enums 8.1 enum Status { case Active; }
Readonly properties 8.1 public readonly string $name;
Intersection types 8.1 Iterator&Countable
First-class callables 8.1 $fn = strlen(...)
Readonly classes 8.2 readonly class Point { }
DNF types 8.2 (A&B)|null
#[\Override] attribute 8.3 Catch wrong method name override
Typed class constants 8.3 const string NAME = 'foo';

6 FAQ

Q: Should I use require or include?
Use require for files that must exist (it throws a fatal error if missing). Use include only when the file is truly optional. In modern PHP, prefer Composer autoloading over manual require calls entirely.

Q: What is the difference between echo and print?
echo can take multiple arguments and has no return value — it's marginally faster. print always returns 1 and takes exactly one argument. In practice, use echo or just <?= $var ?> in templates.

Q: When should I use match vs switch?
Prefer match for PHP 8+. It uses strict comparison (===), has no fall-through, must be exhaustive (throws UnhandledMatchError by default), and is an expression (returns a value). Use switch only for legacy compatibility.

Q: How do I handle sessions securely?
Call session_start() at the top of every page that needs session data. Set session.cookie_httponly = 1, session.cookie_secure = 1 (HTTPS only), and session.use_strict_mode = 1 in php.ini. Regenerate the session ID after login: session_regenerate_id(true).

Q: What is the difference between static and self in PHP?
self refers to the class where the method is defined. static uses late static binding — it refers to the class that was called at runtime. Use static when you expect the method to be inherited and you want polymorphic behaviour.

Q: How do I set up PHP for production?
Set display_errors = Off, log_errors = On, and point error_log to a writable path. Use opcache.enable = 1 for a 2–5× performance boost. Set expose_php = Off to hide the PHP version. Always run composer install --no-dev --optimize-autoloader in production.

Related tools

Keep reading

All Toolmingotools are free & run in your browser

No sign-up, no upload, no watermark. Your files never leave your device.

Browse all tools