How to write clean PHP code: fundamental rules

Writing clean PHP code means reducing bugs, speeding up maintenance, and making projects more sustainable over time. In this guide, we’ll cover the fundamental rules: PSR-12 standards, formatting and naming, types and strict mode, error handling, testing, and SOLID principles applied to real-world cases, with concrete examples.

Workspace di uno sviluppatore PHP con codice pulito e linee guida di sviluppo – ©fullpress.it fpai
Workspace di uno sviluppatore PHP con codice pulito e linee guida di sviluppo – ©fullpress.it fpai

“Clean code” in PHP is not an aesthetic whim: it’s a technical choice that impacts maintenance, bugs, development time, and collaboration. In practice, it’s what allows you to return to a project after months (or hand it over to another developer) without having to “decipher” it like a message in a bottle.

In this guide, we’ll clarify the fundamental rules for writing clean code in PHP: formatting standards and conventions, types and strict mode, error handling, project organization, testing, and applied SOLID principles. The goal is one: to write code that is more readable, more predictable, and easier to change.

1) Start with a standard: PSR-12 and consistency over style

The first step towards clean code is simple: choose a standard and always stick to it. In PHP, the most common standard for code style is PSR-12 (PHP-FIG), which defines guidelines on indentation, spacing, declarations, code organization, and much more. :contentReference[oaicite:0]{index=0}

The standard isn’t for “winning arguments” within the team: it’s for reducing friction, making code uniform, and allowing automated tools to do the dirty work (formatting and checks).

Practical rules (that really make a difference)

  • Consistent indentation (typically 4 spaces, no tabs).
  • Readable spacing around operators and between logical blocks.
  • A blank line between methods to separate sections.
  • Visibility always declared (public/private/protected) for properties and methods.

These guidelines are often summarized as good formatting practices for classes and methods, as in the reference example that cites PSR-12 as the official standard. :contentReference[oaicite:1]{index=1}

2) Naming: if a name is vague, the code is already harder

Clean code starts with names. A wrong name “hides” the meaning and forces the reader to mentally reconstruct the intent. In PHP, a widely used convention is:

  • Classes in PascalCase (e.g. OrderService)
  • Methods and variables in camelCase (e.g. calculateTotal())

It’s a simple rule, but above all, consistency matters. Here too, basic guidelines (PascalCase classes, camelCase methods) are a cornerstone of organized formatting. :contentReference[oaicite:2]{index=2}

Naming checklist (quick and useful)

  • Prefer specific names (not $data, but $orderData).
  • Methods should start with a verb (create, build, validate).
  • Avoid cryptic abbreviations: they save 2 characters and cost 20 minutes.

3) Types and strict mode: less ambiguity, fewer bugs

PHP today allows for much more robust typing than in the past. If you want clean code, take advantage of:

  • type hints for parameters and returns
  • strict_types when it makes sense
  • property types and constructor promotion
<?php
declare(strict_types=1);

final class PriceCalculator
{
    public function calculateTotal(float $net, float $vatRate): float
    {
        return $net * (1 + $vatRate);
    }
}

This approach makes the class API clearer, reduces implicit conversions, and helps static analysis tools.

4) Small functions, single responsibilities: the principle that always pays off

An immediate indicator of “dirty code” is a function that does too many things: validates, transforms, saves to DB, sends emails, and maybe writes logs. When everything is in the same method, any change becomes risky.

Here comes the first SOLID principle, the Single Responsibility Principle (SRP): a class should have only one reason to change. :contentReference[oaicite:3]{index=3}

Example (before: everything together, difficult to maintain)

final class OrderController
{
    public function checkout(array $payload): void
    {
        // valida input
        // calcola totali
        // salva ordine
        // invia email
        // logga operazione
    }
}

After: separate responsibilities (cleaner, testable)

final class CheckoutService
{
    public function __construct(
        private OrderValidator $validator,
        private OrderRepository $repository,
        private Mailer $mailer,
        private LoggerInterface $logger
    ) {}

    public function checkout(OrderRequest $request): void
    {
        $this->validator->validate($request);

        $order = Order::fromRequest($request);

        $this->repository->save($order);
        $this->mailer->sendOrderConfirmation($order);
        $this->logger->info('Order created', ['id' => $order->id()]);
    }
}

It’s not “longer”: it’s clearer. And most importantly, it’s easier to test.

5) SOLID in PHP: what really changes in practice

The SOLID principles are five object-oriented design (OOP) guidelines designed to make code more maintainable, extensible, and robust. :contentReference[oaicite:4]{index=4}

S – Single Responsibility (one responsibility)

A class should not become a “catch-all”. If it grows too large, break it down into smaller, focused components.

O – Open/Closed (open for extension, closed for modification)

When adding a feature, try to extend without modifying existing behavior (reduces regressions). Typical example: strategies, handlers, providers.

L – Liskov Substitution (substitutability)

If a subclass breaks the expectations of the base class, the hierarchy is wrong. If you feel like “throwing exceptions” because a method doesn’t make sense in the subclass, you’re signaling a design problem.

I – Interface Segregation (small interfaces)

Better to have more small interfaces than one huge one that forces classes to implement useless methods.

D – Dependency Inversion (depend on abstractions)

High-level classes should depend on interfaces, not concrete classes. This reduces coupling and improves testability.

If you want a clear summary of the five principles and their definitions, a concise source (with a complete list and the meaning of each letter) is also useful. :contentReference[oaicite:5]{index=5}

6) Avoid “magic numbers” and scattered constants

Another classic of difficult code: numbers and strings repeated everywhere. If a value is significant, give it a name.

final class Invoice
{
    private const VAT_STANDARD = 0.22;

    public function vatRate(): float
    {
        return self::VAT_STANDARD;
    }
}

It’s a simple best practice, frequently mentioned in code formatting and organization rules. :contentReference[oaicite:6]{index=6}

7) Error handling: exceptions, clear messages, no silence

Clean code also means clean errors. Practical guidelines:

  • Use exceptions for “exceptional” errors, not for normal flow.
  • Do not suppress errors with@.
  • Write messages that truly help understand the problem.
throw new DomainException('Order total cannot be negative.');

If an error leaves no trace, it becomes a “ghost” bug: costly.

8) Comments: fewer, but better

Comments should not explain “what the code does” if the code is already clear. They should explain:

  • why a choice was made
  • a business constraint
  • a non-obvious edge case

Even code formatting guidelines emphasize clear and concise comments for complex logic. :contentReference[oaicite:7]{index=7}

9) Automate style: formatters and linters

Manual discipline doesn’t scale. In a real project, it’s beneficial to automate:

  • PHP-CS-Fixer o PHP_CodeSniffer (with PSR-12 rules)
  • PHPStan o Psalm for static analysis
  • pre-commit hook or CI to block non-compliant code

Result: fewer discussions in reviews and more time for architecture and quality.

10) Test: the true multiplier of cleanliness

If code isn’t testable, it’s often not clean. Not because “tests are missing”, but because it’s too coupled, too large, or too environment-dependent.

When you apply principles like SRP and Dependency Inversion, unit tests become easier. And when tests are easy, refactoring becomes sustainable.

Conclusion

Writing clean code in PHP means adopting standards (like PSR-12), taking care of naming and formatting, reducing ambiguity with types, handling errors explicitly, and designing with clear responsibilities. SOLID principles aren’t theory: they are a practical compass for writing code that is simpler to maintain, extend, and test over time. If you want a concrete goal: make code readable, predictable, and boring (in the best sense). That’s how it becomes professional.

Pubblicato in

Se vuoi rimanere aggiornato su How to write clean PHP code: fundamental rules iscriviti alla nostra newsletter settimanale

Be the first to comment

Leave a Reply

Your email address will not be published.


*