What is Clean Code and why is it important in PHP?
Clean Code is not just a trendy term, but a development philosophy that helps write programs that are understandable not only to machines but also to humans. In the context of PHP, where code is often maintained for years by different teams, following clean code principles becomes a critically important skill.
Clean code has several key characteristics:
- It is easy to read and understand without comments
- It is predictable and does not cause "surprises" during execution
- It is easy to modify without the risk of breaking other parts of the system
- It contains minimal duplication (DRY principle)
In this article, we will break down the main Clean Code principles using specific PHP code examples.
1. Naming variables and functions
Bad example: what is wrong with this code?
// ❌ Bad code$a = 5;$b = 10;$c = $a * $b;
function calc($x, $y) { return $x + $y * 0.2;}
$d = calc($a, $b);In this example, it is completely unclear what the variables $a, $b, $c mean and what the function calc does. In a month, you yourself won't remember why you wrote this code.
Good example: meaningful names
// ✅ Good code$productPrice = 5;$quantity = 10;$totalCost = $productPrice * $quantity;
function calculatePriceWithTax(float $basePrice, float $taxRate = 0.2): float { return $basePrice + ($basePrice * $taxRate);}
$finalPrice = calculatePriceWithTax($totalCost);Naming rules in PHP:
- Use nouns for variables (
$userName,$orderTotal) - Use verbs for functions (
getUser(),calculateTotal()) - Do not abbreviate names (write
$customerAddress, not$custAddr) - Avoid single-letter variables (except for loop counters
$i,$j) - Start boolean variables with
is,has,can($isActive,$hasPermission)
2. Small functions and the Single Responsibility Principle (SRP)
Problem: the Swiss Army knife function
// ❌ Bad code: function does everything at oncefunction processOrder(array $orderData): array { // Validation if (empty($orderData['email'])) { throw new Exception('Email required'); } // Saving to DB $pdo = new PDO('mysql:host=localhost;dbname=shop', 'root', ''); $stmt = $pdo->prepare("INSERT INTO orders (email, total) VALUES (?, ?)"); $stmt->execute([$orderData['email'], $orderData['total']]); // Sending email mail($orderData['email'], 'Order confirmed', 'Thank you!'); // Logging file_put_contents('log.txt', 'Order processed: ' . date('Y-m-d H:i:s') . PHP_EOL, FILE_APPEND); return ['status' => 'success'];}This function violates the Single Responsibility Principle. It handles validation, database work, sending mail, and logging. Any change in one of these processes will require changing the entire function.
Solution: decomposition into small functions
// ✅ Good code: each function is responsible for one actionfunction validateOrderData(array $orderData): void { if (empty($orderData['email'])) { throw new InvalidArgumentException('Email is required'); }}
function saveOrderToDatabase(array $orderData): int { $pdo = new PDO('mysql:host=localhost;dbname=shop', 'root', ''); $stmt = $pdo->prepare("INSERT INTO orders (email, total) VALUES (?, ?)"); $stmt->execute([$orderData['email'], $orderData['total']]); return (int)$pdo->lastInsertId();