PHP 8.x is a different language from PHP 5/7 era code — typed properties, enums, attributes, first-class callables, readonly classes,
fibers, and JIT compilation. Always start a file with declare(strict_types=1); — without it,
"int $x" still accepts strings. Modern frameworks: Laravel /
Symfony for full-stack, Slim / Hyperf for micro / async. Static analysis is mandatory —
PHPStan at level 8 or Psalm catches what the runtime won’t.
Install · ComposerSetup
bash
# Install
brew install php@8.3 # macOS
sudo apt install php8.3-cli php8.3-mbstring php8.3-curl php8.3-xml
# Windows: https://windows.php.net/download/
# Composer (the dep manager)
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
# New project
mkdir myapp && cd myapp
composer init # interactive — fills composer.json
composer require slim/slim guzzlehttp/guzzle
composer require --dev phpunit/phpunit phpstan/phpstan
# Run
php -S 127.0.0.1:8000 -t public # built-in dev server
php script.php # run a CLI script
# Daily commands
composer dump-autoload # regenerate autoloader
vendor/bin/phpunit
vendor/bin/phpstan analyse --level=max src
vendor/bin/php-cs-fixer fix
PSR-4 · autoloadingFiles & namespaces
<?php declare(strict_types=1);
Every PHP file starts here. Don’t close with ?> in pure-PHP files.
namespace App\Models;
Namespace declaration. Must be first non-declare statement.
use App\Services\Mailer;
Import a class. Aliases via use Foo as Bar.
use function App\Util\slugify;
Import a function.
use Foo\{A, B, C};
Group use. Cleaner imports.
require __DIR__ . '/vendor/autoload.php';
Bootstrap Composer’s autoloader.
composer.json autoload.psr-4
Map App\\ → src/ directory.
spl_autoload_register(…)
Custom autoloader. Composer handles this for you.
Scalars · unions · nullableTypes
Scalars
$x = 5;
Local. Sigils are required.
int, float, string, bool, array, object, mixed
Built-in scalar / aggregate types.
?int
Nullable int. Equivalent to int|null.
int|string
Union type.
A&B
Intersection type. Must satisfy both.
true, false, null
Literal types (PHP 8.2+).
never
Bottom type. For functions that always throw / exit.
void
Returns nothing. Don’t use return $x;.
self, static, parent
In method signatures — this class, late-static-bound, parent class.
Strings
"hi $name" / "hi {$obj->name}"
Double-quoted interpolation. Braces for expressions.
Turn on strict_types=1 in every file.
Without it, PHP coerces '5' to 5, hiding bugs at type boundaries. Strict mode turns silent coercion into typed errors.
Mark classes final and properties readonly by default.
Both fight unrelated bugs — subclass surprises and accidental mutation. Open them up only when a concrete need arises.
Run PHPStan at level 8 or Psalm in CI.
The runtime is forgiving; static analysis isn’t. Most "PHP bugs" are typos and null deref that these tools catch instantly.
Common trapsWatch out for
Sort functions return bool and mutate in place.$sorted = sort($xs); assigns true to $sorted and reorders $xs. Use usort + a copy when you want a new array.
Loose equality (==) is a minefield.'0' == 'false' is true. [] == null is true. Always use === unless you have a specific reason not to.
String concatenation with + is silent type coercion.
In PHP, + is numeric — "hi" + "bye" is 0. Use . for concatenation.
PHP is a server-side scripting language designed for web development and now widely used for backend APIs, CLI tools, and CMS platforms. It powers WordPress, Laravel, Symfony, and roughly 75% of all websites with a known server-side language. Modern PHP 8.x is type-safe, object-oriented, and performant with JIT compilation.
How does PHP handle types?
PHP is dynamically typed by default. Add declare(strict_types=1) at the top of each file to enforce type coercion rules for function arguments. Type declarations (int, string, ?float, array, MyClass) annotate function parameters and return types. Union types (int|string), intersection types (A&B), and never return type arrived in PHP 8.x.
What are PHP enums and when should I use them?
PHP 8.1 added native enums — use them instead of class constants to represent a fixed set of named values. Pure enums (enum Status) have no backing value. Backed enums (enum Status: string) have a string or int value you can use for serialisation. Enums can implement interfaces and have methods, making them much more powerful than constants.
What is Composer and why does every PHP project use it?
Composer is the dependency manager for PHP, analogous to npm for Node or pip for Python. Run composer require vendor/package to add a dependency, composer install to restore from composer.lock, and composer dump-autoload to regenerate the PSR-4 class autoloader. Every modern PHP project uses Composer to manage third-party packages and autoloading.
How do namespaces work in PHP?
Declare a namespace at the top of a PHP file with namespace App\Models. Import other namespaces with use App\Services\UserService. PSR-4 autoloading maps namespace paths to directory paths — App\Models\User maps to src/Models/User.php. Use aliases to resolve collisions: use App\Models\User as UserModel.
What are PHP attributes and how do I use them?
PHP 8.0 attributes (previously called annotations) are structured metadata placed above classes, methods, properties, or parameters using the #[Attribute] syntax. Frameworks like Symfony and Laravel use them for routing (#[Route("/api")]), validation (#[Assert\NotBlank]), and dependency injection (#[Inject]). Read them at runtime with the Reflection API.