Clean Code in PHP: Principles and Practical Examples
\nClean code is not a luxury, but a necessity for any professional PHP developer. When you write code that is easy to read, understand, and modify, you save time for yourself and your team. In this article, we will break down the key principles of Clean Code in PHP with specific examples that you can immediately apply in your projects.
\n\nWhy is Clean Code Important for PHP Projects?
\nPHP is a flexible language, but this flexibility often leads to chaos if code quality is not maintained. Clean code helps to:
\n- \n
- Find and fix bugs faster; \n
- Easily add new features without the risk of breaking existing logic; \n
- Reduce onboarding time for new developers; \n
- Increase the overall stability of the application. \n
Let's move on to specific principles and examples.
\n\nProper Variable and Function Names
\nThe first step to clean code is meaningful names. The name should answer the question "What is this?" or "What does it do?".
\n\nBad Example
\n<?php\n$a = 86400;\n$b = $a * 7;\n$c = $b * 0.8;\n\nGood Example (Clean Code)
\n<?php\n$secondsPerDay = 86400;\n$weeklySeconds = $secondsPerDay * 7;\n$discountedWeeklySeconds = $weeklySeconds * 0.8;\n\nPrinciple: Names should be descriptive and not require comments. Avoid abbreviations (except for commonly accepted ones, e.g., $i for a loop counter).
Example for Functions
\n<?php\n// Bad\nfunction calc($a, $b) {\n return $a + $b * 1.2;\n}\n\n// Good\nfunction calculateTotalWithTax(float $price, float $taxRate = 0.2): float {\n return $price * (1 + $taxRate);\n}\n\nSingle Responsibility Principle (SRP) in Classes
\nOne of the SOLID principles states: "A class should have only one reason to change." This means that each class should be responsible for one specific task.
\n\nSRP Violation
\n<?php\nclass OrderProcessor {\n public function process(Order $order) {\n // Order validation\n if (empty($order->items)) {\n throw new Exception("Empty order");\n }\n \n // Save to database\n $this->saveToDatabase($order);\n \n // Send email\n mail($order->email, "Order placed", "Thank you for your purchase!");\n \n // Generate PDF invoice\n $this->generateInvoice($order);\n }\n}\n\nClean Implementation with SRP
\n<?php\nclass OrderValidator {\n public function validate(Order $order): void {\n if (empty($order->items)) {\n throw new Exception("Empty order");\n }\n }\n}\n\nclass OrderRepository {\n public function save(Order $order): void {\n // Database save logic\n }\n}\n\nclass EmailNotifier {\n public function sendOrderConfirmation(Order $order): void {\n mail($order->email, "Order placed", "Thank you for your purchase!");\n }\n}\n\nclass InvoiceGenerator {\n public function generate(Order $order): string {\n // PDF generation\n return "invoice_".$order->id.".pdf";\n }\n}\n\n// Usage\nclass OrderProcessor {\n public function __construct(\n private OrderValidator $validator,\n private OrderRepository $repository,\n private EmailNotifier $notifier,\n private InvoiceGenerator $invoiceGenerator\n ) {}\n \n public function process(Order $order): void {\n $this->validator->validate($order);\n $this->repository->save($order);\n $this->notifier->sendOrderConfirmation($order);\n $this->invoiceGenerator->generate($order);\n }\n}\n\nNow each class is responsible for its own area of responsibility, which simplifies testing and maintenance.
\n\n