Table Of Contents
Problem
PHP's default type juggling can cause unexpected behavior when functions receive wrong data types, leading to hard-to-debug issues.
Solution
<?php
declare(strict_types=1);
// Without strict types (default behavior)
function addNumbers($a, $b) {
return $a + $b;
}
// These would work in non-strict mode but cause type errors in strict mode
// addNumbers("5", "10"); // TypeError in strict mode
// addNumbers(true, false); // TypeError in strict mode
// With strict types - specify exact types
function addNumbersStrict(int $a, int $b): int {
return $a + $b;
}
// Only accepts integers
echo addNumbersStrict(5, 10); // 15
// String type enforcement
function greetUser(string $name): string {
return "Hello, " . $name;
}
echo greetUser("Alice"); // Hello, Alice
// greetUser(123); // TypeError: must be string
// Float type enforcement
function calculateTax(float $amount, float $rate): float {
return $amount * $rate;
}
echo calculateTax(100.0, 0.08); // 8.0
// Boolean type enforcement
function toggleFeature(bool $enabled): string {
return $enabled ? "Feature enabled" : "Feature disabled";
}
echo toggleFeature(true); // Feature enabled
echo toggleFeature(false); // Feature disabled
// Array type enforcement
function processItems(array $items): int {
return count($items);
}
echo processItems(['a', 'b', 'c']); // 3
// Object type enforcement
class User {
public string $name;
public int $age;
public function __construct(string $name, int $age) {
$this->name = $name;
$this->age = $age;
}
}
function welcomeUser(User $user): string {
return "Welcome, " . $user->name;
}
$user = new User("Bob", 25);
echo welcomeUser($user); // Welcome, Bob
// Nullable types
function formatMessage(?string $message): string {
return $message ?? "No message";
}
echo formatMessage("Hello"); // Hello
echo formatMessage(null); // No message
// Union types (PHP 8.0+)
function processValue(int|float|string $value): string {
return "Processing: " . $value;
}
echo processValue(42); // Processing: 42
echo processValue(3.14); // Processing: 3.14
echo processValue("text"); // Processing: text
// Return type enforcement
function getUsers(): array {
return [
['name' => 'Alice', 'age' => 30],
['name' => 'Bob', 'age' => 25]
];
}
function getUserCount(): int {
return count(getUsers());
}
// Mixed type for flexibility
function logValue(mixed $value): void {
error_log("Value: " . print_r($value, true));
}
logValue("string");
logValue(123);
logValue(['array']);
// Class with strict types
class Calculator {
public function add(int|float $a, int|float $b): int|float {
return $a + $b;
}
public function divide(int|float $a, int|float $b): float {
if ($b === 0) {
throw new InvalidArgumentException("Division by zero");
}
return $a / $b;
}
public function factorial(int $n): int {
if ($n < 0) {
throw new InvalidArgumentException("Factorial of negative number");
}
$result = 1;
for ($i = 2; $i <= $n; $i++) {
$result *= $i;
}
return $result;
}
}
// Interface with strict types
interface PaymentProcessor {
public function processPayment(float $amount, string $currency): bool;
public function refund(string $transactionId, float $amount): bool;
}
class StripePaymentProcessor implements PaymentProcessor {
public function processPayment(float $amount, string $currency): bool {
// Process payment logic
return true;
}
public function refund(string $transactionId, float $amount): bool {
// Refund logic
return true;
}
}
// Checking types at runtime
function validateInput(mixed $value): string {
return match(gettype($value)) {
'string' => "Valid string: $value",
'integer' => "Valid integer: $value",
'double' => "Valid float: $value",
'boolean' => "Valid boolean: " . ($value ? 'true' : 'false'),
'array' => "Valid array with " . count($value) . " elements",
default => "Unknown type: " . gettype($value)
};
}
// Migration strategy for existing code
// 1. Add declare(strict_types=1) to new files
// 2. Gradually add type hints to existing functions
// 3. Test thoroughly after enabling strict types
// Example of gradual migration
function oldFunction($data) {
// Original function without types
return strtoupper($data);
}
function newFunction(string $data): string {
// Migrated version with strict types
return strtoupper($data);
}
// Error handling with strict types
try {
$calc = new Calculator();
$result = $calc->divide(10, 2);
echo "Result: $result\n";
} catch (TypeError $e) {
echo "Type error: " . $e->getMessage();
} catch (InvalidArgumentException $e) {
echo "Invalid argument: " . $e->getMessage();
}
Explanation
declare(strict_types=1)
must be the first statement in a PHP file. It enforces exact type matching for function parameters and return values.
Strict types prevent automatic type conversion, catching type-related bugs early. Use type hints consistently and handle TypeError
exceptions for better error handling.
Share this article
Add Comment
No comments yet. Be the first to comment!