PHP: Modern PHP, Composer & Best Practices
Composer
# Install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
# Create project
composer init
composer create-project laravel/laravel myapp
# Install packages
composer require guzzlehttp/guzzle
composer require --dev phpunit/phpunit psalm/psalm
# Update dependencies
composer update
composer update guzzlehttp/guzzle # single package
# Autoloading (PSR-4)
# composer.json:
# "autoload": { "psr-4": { "App\\": "src/" } }
composer dump-autoload
# Scripts
# composer.json: "scripts": { "test": "vendor/bin/phpunit", "lint": "vendor/bin/psalm" }
composer test
composer lintPHP 8.x Features
<?php
// Named arguments (PHP 8.0)
array_slice(array: $arr, offset: 1, length: 3, preserve_keys: true);
// Match expression (PHP 8.0) — strict, no fallthrough, exhaustive
$label = match($status) {
'active', 'enabled' => 'Active',
'inactive' => 'Inactive',
default => throw new \ValueError("Unknown status: $status"),
};
// Nullsafe operator (PHP 8.0)
$country = $user?->getAddress()?->getCountry()?->getName();
// Union types (PHP 8.0)
function parseId(int|string $id): User { ... }
// Intersection types (PHP 8.1)
function process(Iterator&Countable $collection): void { ... }
// Readonly properties (PHP 8.1)
class Point {
public function __construct(
public readonly float $x,
public readonly float $y,
) {}
}
// Fibers (PHP 8.1) — cooperative concurrency
$fiber = new Fiber(function (): void {
$value = Fiber::suspend('first'); // yields 'first', receives next value
echo "Resumed with: $value\n";
Fiber::suspend('second');
});
$val1 = $fiber->start(); // 'first'
$val2 = $fiber->resume('hello'); // 'second'
// First class callables (PHP 8.1)
$fn = strlen(...);
$fn("hello"); // 5
// Readonly classes (PHP 8.2)
readonly class Money {
public function __construct(
public int $amount,
public string $currency,
) {}
}
// Typed class constants (PHP 8.3)
class Config {
const string VERSION = '1.0.0';
const int MAX_RETRIES = 3;
}Best Practices
Use strict_types: add declare(strict_types=1) at the top of every PHP file — prevents type coercion bugs.
Type declarations everywhere: parameters, return types, properties. Use union types and nullable (?) where needed.
Use PDO with prepared statements always — never concatenate user input into SQL queries.
Hash passwords with password_hash() and verify with password_verify() — never md5 or sha1.
Validate and sanitize all input: filter_input(), FILTER_VALIDATE_*, or a validation library.
Use Composer for all dependencies. Never copy-paste vendor code into your project.
Follow PSR-12 coding standard. Use PHP_CodeSniffer or PHP-CS-Fixer for enforcement.
Use a static analyzer: PHPStan (level 8+) or Psalm catches type errors without running the code.
Major frameworks: Laravel (most popular, batteries-included), Symfony (enterprise, modular), Slim (microframework for APIs).
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free