Table Of Contents
Problem
You need conditional logic with multiple cases but switch statements are verbose, allow fall-through, and don't return values directly.
Solution
// Traditional switch statement
function getStatusMessage($status) {
switch ($status) {
case 'pending':
return 'Order is pending';
case 'processing':
return 'Order is being processed';
case 'shipped':
return 'Order has been shipped';
case 'delivered':
return 'Order delivered';
default:
return 'Unknown status';
}
}
// Match expression (cleaner)
function getStatusMessage($status) {
return match ($status) {
'pending' => 'Order is pending',
'processing' => 'Order is being processed',
'shipped' => 'Order has been shipped',
'delivered' => 'Order delivered',
default => 'Unknown status'
};
}
// Multiple values per case
function getDiscount($customerType) {
return match ($customerType) {
'premium', 'vip' => 0.20,
'regular', 'standard' => 0.10,
'new' => 0.05,
default => 0.0
};
}
// Type-safe matching (strict comparison)
function processValue($value) {
return match ($value) {
1 => 'Integer one',
'1' => 'String one',
true => 'Boolean true',
1.0 => 'Float one',
default => 'Something else'
};
}
echo processValue(1); // Integer one
echo processValue('1'); // String one
echo processValue(true); // Boolean true
// Complex expressions
function calculateShipping($weight, $zone) {
return match (true) {
$weight <= 1 && $zone === 'local' => 5.00,
$weight <= 1 && $zone === 'national' => 8.00,
$weight <= 5 && $zone === 'local' => 10.00,
$weight <= 5 && $zone === 'national' => 15.00,
default => 25.00
};
}
// Enum matching (PHP 8.1+)
enum Status {
case PENDING;
case APPROVED;
case REJECTED;
}
function getStatusColor(Status $status): string {
return match ($status) {
Status::PENDING => 'yellow',
Status::APPROVED => 'green',
Status::REJECTED => 'red'
};
}
// Object matching
class HttpResponse {
public function __construct(public int $code) {}
}
function handleResponse(HttpResponse $response): string {
return match ($response->code) {
200, 201 => 'Success',
400, 422 => 'Client error',
401, 403 => 'Authentication error',
404 => 'Not found',
500, 502, 503 => 'Server error',
default => 'Unknown response'
};
}
// Array patterns (PHP 8.0+)
function analyzeArray($data): string {
return match (count($data)) {
0 => 'Empty array',
1 => 'Single item: ' . $data[0],
2 => 'Two items: ' . implode(', ', $data),
default => 'Multiple items (' . count($data) . ')'
};
}
// Function calls in match arms
function processOrder($type) {
return match ($type) {
'express' => calculateExpressShipping(),
'standard' => calculateStandardShipping(),
'pickup' => 0,
default => throw new InvalidArgumentException('Unknown order type')
};
}
function calculateExpressShipping(): float {
return 25.00;
}
function calculateStandardShipping(): float {
return 10.00;
}
// Exception throwing
function validateAge($age) {
return match (true) {
$age < 0 => throw new InvalidArgumentException('Age cannot be negative'),
$age < 18 => 'Minor',
$age < 65 => 'Adult',
default => 'Senior'
};
}
// Class instantiation
abstract class Logger {
abstract public function log(string $message): void;
}
class FileLogger extends Logger {
public function log(string $message): void {
file_put_contents('app.log', $message . PHP_EOL, FILE_APPEND);
}
}
class DatabaseLogger extends Logger {
public function log(string $message): void {
// Log to database
}
}
function createLogger($type): Logger {
return match ($type) {
'file' => new FileLogger(),
'database' => new DatabaseLogger(),
default => throw new InvalidArgumentException('Unknown logger type')
};
}
// API response formatting
function formatApiResponse($data, $format) {
return match ($format) {
'json' => json_encode($data),
'xml' => simplexml_load_string($data)->asXML(),
'csv' => implode(',', $data),
'text' => is_array($data) ? implode("\n", $data) : (string)$data,
default => $data
};
}
// Database operation routing
function executeQuery($operation, $table, $data = []) {
return match ($operation) {
'select' => "SELECT * FROM $table",
'insert' => "INSERT INTO $table VALUES (" . implode(',', $data) . ")",
'update' => "UPDATE $table SET " . implode(',', $data),
'delete' => "DELETE FROM $table",
default => throw new InvalidArgumentException('Unsupported operation')
};
}
// Configuration management
function getConfig($environment) {
return match ($environment) {
'development' => [
'debug' => true,
'database' => 'dev_db',
'cache' => false
],
'staging' => [
'debug' => true,
'database' => 'staging_db',
'cache' => true
],
'production' => [
'debug' => false,
'database' => 'prod_db',
'cache' => true
],
default => throw new InvalidArgumentException('Unknown environment')
};
}
// HTTP method routing
function routeRequest($method, $path) {
return match ([$method, $path]) {
['GET', '/'] => 'showHomePage()',
['GET', '/users'] => 'listUsers()',
['POST', '/users'] => 'createUser()',
['GET', '/users/profile'] => 'showProfile()',
['PUT', '/users/profile'] => 'updateProfile()',
['DELETE', '/users/profile'] => 'deleteProfile()',
default => 'show404Page()'
};
}
// Validation rules
function validateInput($field, $value) {
return match ($field) {
'email' => filter_var($value, FILTER_VALIDATE_EMAIL) !== false,
'url' => filter_var($value, FILTER_VALIDATE_URL) !== false,
'age' => is_numeric($value) && $value >= 0 && $value <= 150,
'phone' => preg_match('/^\+?[\d\s\-\(\)]+$/', $value),
'password' => strlen($value) >= 8,
default => !empty($value)
};
}
// Performance comparison
$iterations = 1000000;
// Match expression timing
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$result = match ($i % 3) {
0 => 'zero',
1 => 'one',
2 => 'two'
};
}
$matchTime = microtime(true) - $start;
// Switch statement timing
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
switch ($i % 3) {
case 0:
$result = 'zero';
break;
case 1:
$result = 'one';
break;
case 2:
$result = 'two';
break;
}
}
$switchTime = microtime(true) - $start;
echo "Match: {$matchTime}s, Switch: {$switchTime}s\n";
Explanation
Match expressions provide strict comparison, no fall-through, and direct value returns. They're more concise than switch statements and prevent common bugs.
Use match for simple value mapping and switch for complex multi-statement logic. Match expressions must be exhaustive or include a default case.
Share this article
Add Comment
No comments yet. Be the first to comment!