PHP cheat sheet
A scannable PHP reference: 20 short snippets across 8 topics, each linking back to the lesson it came from.
At a glance
| Topic | What it covers | |
|---|---|---|
| PHP: getting started | PHP executes on the server and sends the resulting HTML to the browser. The visitor never sees your source — only its | lesson |
| PHP variables and strings | Variables are dynamically typed and prefixed with $. Since PHP 7 you can also declare strict types per file with | lesson |
| PHP arrays | One array type serves both roles because PHP arrays are ordered maps. Iteration preserves insertion order | lesson |
| Forms, sessions and safety | Handling GET and POST, validating input, keeping sessions, and the defences against the classic web attacks | lesson |
| A modern PHP toolchain with Composer | Install a current PHP, serve it locally, and let Composer handle dependencies, PSR-4 autoloading and the tooling around | lesson |
| Modern PHP 8 features in practice | The pipe passes the left-hand value as the argument of the callable on the right, so a chain reads in execution order | lesson |
| Composer, dependencies and coding standards | Version constraints and the lockfile, scripts, autoload optimisation, PSR-12 formatting, PHPStan and Rector in one | lesson |
| Testing, frameworks and deployment | PHPUnit and Pest, unit versus feature tests, a tour of Laravel and Symfony routing, and shipping with OPcache, PHP-FPM | lesson |
Quick snippets
PHP: getting started
A server-side language
<?php
// everything between these tags runs on the server
$name = "world";
echo "Hello, " . $name;
Mixing PHP and HTML
<!DOCTYPE html>
<html>
<body>
<h1><?php echo htmlspecialchars($title); ?></h1>
<ul>
<?php foreach ($items as $item): ?>
<li><?= htmlspecialchars($item) ?></li>
<?php endforeach; ?>
</ul>
</body>
</html>
Running it
php -v
php -S localhost:8000 # built-in dev server
php script.php # run a CLI scriptFull lesson: PHP: getting started →
PHP variables and strings
Variables
$count = 10; // no declaration keyword
$price = 19.99;
$label = "cart";
$active = true;
$nothing = null;
echo gettype($count); // integer
var_dump($count); // type + value, best for debugging
Strings
$name = "Ada";
echo "Hello $name"; // double quotes interpolate
echo 'Hello $name'; // single quotes do not
echo "Sum: {$arr['total']}"; // braces when the expression is ambiguous
$multi = <<<TEXT
Line one
Line two: $name
TEXT;
echo nl2br(htmlspecialchars($multi));
Loose versus strict comparison
var_dump(0 == "a"); // false in PHP 8 (was true in PHP 7!)
var_dump("1" == "01"); // true - numeric strings compared numerically
var_dump("10" == "1e1");// true
var_dump(100 == "1e2"); // true
var_dump("1" === 1); // false - type differsFull lesson: PHP variables and strings →
PHP arrays
Lists and associative arrays
$list = [1, 2, 3]; // indexed
$user = ["id" => 7, "name" => "Ada"]; // associative
$list[] = 4; // append
echo $user["name"];
echo $list[0] ?? "missing"; // null-coalescing for missing keys
$id = 7;
$h = "id";
echo $user[$h]; // variable key
Array functions worth knowing
$adults = array_filter($people, fn($p) => $p["age"] >= 18);
$names = array_map(fn($p) => $p["name"], $adults);
$total = array_reduce($items, fn($sum, $i) => $sum + $i["price"], 0);
usort($people, fn($a, $b) => $a["age"] <=> $b["age"]);
$ids = array_column($people, "id");
Arrays and JSON
$json = json_encode($user, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
$back = json_decode($json, true); // true = associative arrays
if (json_last_error() !== JSON_ERROR_NONE) {
throw new RuntimeException(json_last_error_msg());
}
Forms, sessions and safety
Reading request data
$email = filter_input(INPUT_POST, "email", FILTER_VALIDATE_EMAIL);
$page = filter_input(INPUT_GET, "page", FILTER_VALIDATE_INT, ["options" => ["min_range" => 1]]);
if ($email === null || $email === false) {
http_response_code(422);
exit("Invalid email");
}
// never: $email = $_POST["email"]; then use it directly in SQL or HTML
The classic attacks and their fixes
// SQL injection, fixed
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();
// CSRF token
$_SESSION["csrf"] = bin2hex(random_bytes(32));
// in the form: <input type="hidden" name="csrf" value="<?= $_SESSION['csrf'] ?>">
// on submit: hash_equals($_SESSION["csrf"], $_POST["csrf"] ?? "")Full lesson: Forms, sessions and safety →
A modern PHP toolchain with Composer
PHP 8.4 or 8.5, served locally
php -v # aim for 8.4 or 8.5
php -m # extensions actually loaded
php -i | grep "Loaded Configuration" # which php.ini is in use
php -S localhost:8000 -t public # built-in server, docroot public/
Composer and PSR-4 autoloading
composer init --name=acme/blog --require=php:^8.4
composer require monolog/monolog:^3 # production dependency
composer require --dev phpunit/phpunit:^11 # development only
composer install # installs exactly what composer.lock pins
composer update monolog/monolog # deliberately move one package forward
Composer and PSR-4 autoloading
<?php
// public/index.php - the single entry point the web server hands requests to
require __DIR__ . '/../vendor/autoload.php';
use Acme\Blog\Post; // resolves to src/Post.php through the psr-4 rule
$post = new Post();
echo $post->title();Full lesson: A modern PHP toolchain with Composer →
Modern PHP 8 features in practice
Pipe operator and clone-with
$slug = $title
|> trim(...)
|> strtolower(...)
|> (fn(string $s): string => preg_replace('/[^a-z0-9]+/', '-', $s));
// equivalent without the pipe, read inside out
$slug = preg_replace('/[^a-z0-9]+/', '-', strtolower(trim($title)));
$draft = clone($post, ["status" => Status::Draft, "publishedAt" => null]);Full lesson: Modern PHP 8 features in practice →
Composer, dependencies and coding standards
Constraints that mean what you think
composer require "monolog/monolog:^3.7" # >=3.7.0 <4.0.0
composer require "phpunit/phpunit:~11.2" # >=11.2.0 <11.3.0 (patch-level safety)
composer show monolog/monolog # installed version and its own requirements
composer why-not php 8.3 # which package blocks that downgrade
composer outdated --direct
composer audit # known security advisories
composer validate --strict
Scripts and autoload performance
{
"scripts": {
"test": "phpunit",
"stan": "phpstan analyse src tests --level=6",
"lint": "php-cs-fixer fix --dry-run --diff",
"check": ["@lint", "@stan", "@test"]
},
"config": {
"optimize-autoloader": true,
"sort-packages": true
}
}
Scripts and autoload performance
composer check # one command a reviewer can trust
composer dump-autoload -o # build a class map: no filesystem lookups at runtime
composer dump-autoload --classmap-authoritative # never fall back to scanning
composer dump-autoload --apcu # cache the map in shared memory when APCu is presentFull lesson: Composer, dependencies and coding standards →
Testing, frameworks and deployment
Unit and feature tests
<?php
// Pest: the same two tests, with closures and expectations
it("slugifies a title", function () {
expect((new Slugger())->slug("Hello World"))->toBe("hello-world");
});
it("rejects an empty string", function () {
(new Slugger())->slug(" ");
})->throws(InvalidArgumentException::class);
Shipping it
# a release directory per build, switched with a symlink
composer install --no-dev --optimize-autoloader
php bin/console cache:warmup # Laravel: php artisan optimize
ln -sfn /srv/releases/2026-09-18-1 /srv/current
systemctl reload php8.5-fpm # new opcache, zero dropped requestsFull lesson: Testing, frameworks and deployment →
FAQ
Is this PHP cheat sheet free to use?
Where do the examples come from?
How do I go deeper than a cheat sheet?
Related cheat sheets
Node.js Java HTTP Go Rust Spring Boot
Last refreshed 2026-09-27.