PHP Syntax, Types, and Data Handling
Strong fundamentals prevent a surprising number of production bugs. Modern PHP gives you tools to make intent explicit while still keeping the language approachable.
On This Page
Start New Files With Strict Types
<?php
declare(strict_types=1);
function calculateTax(float $subtotal, float $rate): float
{
return round($subtotal * $rate, 2);
}
echo calculateTax(125.00, 0.06);
Strict mode reduces silent scalar coercion when calling functions. It does not validate user input for you, but it makes internal contracts more predictable.
Common Types
| Type | Use | Example |
|---|---|---|
string | Text and identifiers that are not calculated | $invoiceNumber = 'INV-2026-0042'; |
int | Whole numbers | $seatCount = 28; |
float | Approximate decimal values | $distanceMiles = 17.4; |
bool | True/false state | $isActive = true; |
array | Ordered maps and lists | $roles = ['admin', 'dispatcher']; |
object | State plus behavior | $customer = new Customer(...); |
Nullable and Union Types
<?php
declare(strict_types=1);
function normalizePhone(string|null $phone): ?string
{
if ($phone === null || trim($phone) === '') {
return null;
}
return preg_replace('/\D+/', '', $phone) ?: null;
}
function displayId(int|string $id): string
{
return (string) $id;
}
Use nullable types when “no value” is meaningful. Do not use broad union types merely to avoid deciding what a function should accept.
String Handling and Output Context
<?php
declare(strict_types=1);
$name = trim($_POST['name'] ?? '');
$safeName = htmlspecialchars($name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
echo "<p>Welcome, {$safeName}.</p>";
Escaping belongs at output time because the correct escaping depends on context: HTML text, an HTML attribute, JSON, SQL, a shell command, and a URL all have different rules.
Dates and Time Zones
<?php
declare(strict_types=1);
$displayZone = new DateTimeZone('America/New_York');
$storedUtc = new DateTimeImmutable('2026-07-16 13:30:00', new DateTimeZone('UTC'));
$local = $storedUtc->setTimezone($displayZone);
echo $local->format('F j, Y g:i A T');
Store timestamps in UTC when possible, retain the applicable time-zone identifier for scheduled events, and convert only when displaying or interpreting local wall time.
Normalize at the Edge
Convert raw request data into predictable internal values once. Trim strings, validate identifiers, map checkboxes to booleans, parse dates explicitly, and reject ambiguous values.
<?php
declare(strict_types=1);
$rawQuantity = $_POST['quantity'] ?? null;
$quantity = filter_var(
$rawQuantity,
FILTER_VALIDATE_INT,
['options' => ['min_range' => 1, 'max_range' => 100]]
);
if ($quantity === false) {
throw new InvalidArgumentException('Quantity must be between 1 and 100.');
}