PHP Builder Design Pattern Creational Pattern

PHP Builder Pattern

A short screencast: the Builder pattern in PHP — assembling an immutable object through a fluent method chain without touching its constructor.

Builder Pattern — open the lesson page

Overview

In this screencast we assemble a pizza without a long constructor. The Pizza class is immutable: all data is passed to the constructor at once. The PizzaBuilder class accumulates parameters step by step (size(), addTopping()), every step returns $this for method chaining, and build() finally creates the finished product.

UML diagram

classDiagram class Pizza { -string size -array toppings +__construct(size: string, toppings: array) +describe() string } class PizzaBuilder { -string size = "medium" -array toppings = [] +size(size: string) PizzaBuilder +addTopping(topping: string) PizzaBuilder +build() Pizza } PizzaBuilder ..> Pizza : builds

Code

Pizza.php

class Pizza
{
    public function __construct(
        private readonly string $size,
        private readonly array $toppings
    ) {}

    public function describe(): string
    {
        return $this->size . ' pizza with ' . implode(', ', $this->toppings);
    }
}

PizzaBuilder.php

class PizzaBuilder
{
    private string $size = 'medium';
    private array $toppings = [];

    public function size(string $size): self
    {
        $this->size = $size;
        return $this;
    }

    public function addTopping(string $topping): self
    {
        $this->toppings[] = $topping;
        return $this;
    }

    public function build(): Pizza
    {
        return new Pizza($this->size, $this->toppings);
    }
}

demo.php

require_once 'Pizza.php';
require_once 'PizzaBuilder.php';

$pizza = (new PizzaBuilder())
    ->size('large')
    ->addTopping('pepperoni')
    ->addTopping('olives')
    ->build();

echo $pizza->describe();

Note: why a Builder

Constructors with a dozen parameters are hard to read, and their overloads that "skip" arguments are known as telescoping constructors. The Builder solves both: the method chain reads like a sentence, and the immutable product is produced in one build() call. On top of that, each step can validate its input before the object exists — a bad recipe never yields a half-baked pizza.

Example output

Running php demo.php in the terminal produces:

large pizza with pepperoni, olives

Advantages

  • Builds a complex object step by step, readably.
  • Separates construction from representation: one process yields different objects.
  • Removes "telescoping" constructors with a dozen parameters.
  • Handy for optional parts and default values.

When to use

  • When an object has many optional parts or parameters.
  • When an object is assembled over several steps rather than one call.
  • When one construction algorithm must produce different representations.
  • When you want to avoid long constructors.

Usage in Laravel

In Laravel the builder is Illuminate\Database\Query\Builder and Illuminate\Database\Eloquent\Builder: methods such as where(), join() and orderBy() assemble the SQL step by step, and it runs only when get() is called. The same approach powers Illuminate\Bus\PendingBatch for configuring a batch of jobs and Illuminate\Testing\TestResponse, where assertions are chained.