PHP 8: Modern PHP Development · Errors, Exceptions and Robust Code

Input Validation and Value Objects

Validate at the boundary and model domain rules with small immutable types.

Validate untrusted input (HTTP requests, CLI args, files, APIs) at the boundary and convert it into typed objects; inside the domain, rely on those types. Value objects like EmailAddress, Money or DateRange validate in their constructor so invalid states are impossible. Use filter_var() for basic formats or a validation library (Symfony Validator, Laravel validation, Respect\Validation) for complex rules, and return all errors at once to API clients.

<?php
final readonly class EmailAddress
{
    public string $value;

    public function __construct(string $value)
    {
        $normalized = strtolower(trim($value));
        if (filter_var($normalized, FILTER_VALIDATE_EMAIL) === false) {
            throw new InvalidArgumentException("Invalid email: {$value}");
        }
        $this->value = $normalized;
    }
}

// At the HTTP boundary
$errors = [];
try { $email = new EmailAddress($_POST['email'] ?? ''); } catch (InvalidArgumentException $e) { $errors['email'] = $e->getMessage(); }
$age = filter_var($_POST['age'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 13, 'max_range' => 120]]);
if ($age === false) { $errors['age'] = 'Age must be between 13 and 120'; }

Common pitfalls

  • Validating only on the client side.
  • Passing raw $_POST arrays deep into the application.
  • Rejecting valid but unusual data (international names, plus-addressing in emails).

Key points

  • Validate at the boundary, then use types
  • Value objects make invalid states unrepresentable
  • Return all validation errors together

Further reading: PHP manual: validate filters

Practice questions

What is a value object?

Answer

A small immutable object defined by its value (not identity), such as Money or EmailAddress. It validates itself on construction, so any instance is guaranteed valid, and equality compares values.

Why shouldn't $_POST arrays be passed around your application?

Answer

They're untyped and unvalidated, so every consumer must re-check them and mistakes slip through. Converting them once into validated objects centralizes rules and gives type safety.

Open in the app to mark lessons complete, take notes and track your progress.