Builder Pattern in laravel

Khaled RahmanKhaled Rahman
4 min read

Imagine you're building a Lego house. It can get tricky if you have a ton of pieces and steps to follow. The Builder Pattern is like a special instruction sheet that helps you build things piece by piece, nice and easy.

Why use the Builder Pattern?

  • Complex creations: Building a complex object (like our Lego house) is easier with clear steps. The Builder Pattern keeps all the instructions in one place, making your code cleaner.

  • Easy to read and change: Just like clear Lego instructions, the Builder Pattern makes your code easier to understand and update later.

  • No mistakes: With the Builder Pattern, you build the object step-by-step without messing anything up, like keeping all your Lego pieces separate until you need them.

  • Reuse instructions: Built one Lego house? You can use the same instructions (with some changes) to build a different one! The Builder Pattern lets you reuse instructions for different variations of the same object.

  • Organized and tidy: The Builder Pattern keeps your building instructions (code) separate from the actual house (object) itself. This makes things more organized.

  • Build it how you like: The Builder Pattern is flexible, like Lego instructions that let you build different things. You can build different versions of the same object with the same basic instructions.

When to use the Builder Pattern?

  • Lots of building steps: If building your object is complicated, the Builder Pattern can break it down into easier steps.

  • Many variations: If your object can be built in different ways, the Builder Pattern lets you handle those variations easily.

  • Easy to understand code: The Builder Pattern makes your code clear and simple to maintain.

  • Unbreakable objects: If you want your object to be unchangeable after it's built (like a finished Lego house), the Builder Pattern helps with that.

Example: Building a Customer in Laravel

Imagine you're creating a customer profile in Laravel. There are many details, like name, email, phone number, and address, but some might be optional. Using a bunch of options in the beginning can be confusing. The Builder Pattern lets you add these details one by one, making it easier to manage.

Example 1:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Customer extends Model
{
    protected $fillable = ['name', 'email', 'phone', 'address'];

    public static function createBuilder(): self
    {
        return new self();
    }

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

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

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

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

    public function build(): self
    {
        return $this;
    }
}

$customer = Customer::createBuilder()
                    ->withName('Khaled Rahman')
                    ->withEmail('khaled@test.com')
                    ->withPhone('01680000000')
                    ->withAddress('Dhaka, bangladesh ')
                    ->build();

$customer->save();

In the example above, we added the builder pattern code to the Model. However, it's better to use a separate function for createBuilder, as shown in the example below. We use the builder pattern here because we are trying to build some additional, complex queries that will support the main query:

namespace App\Builders;

use App\Models\User;

class UserBuilder
{
    protected $user;

    public function __construct()
    {
        $this->user = new User();
    }

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

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

    public function withProfile(array $profile): self
    {
        $this->user->profile = $profile;
        return $this;
    }

    public function withSettings(array $settings): self
    {
        $this->user->settings = $settings;
        return $this;
    }

    public function build(): User
    {
        return $this->user;
    }
}

// Usage
$user = (new UserBuilder())
    ->withName('Khaled Rahman')
    ->withEmail('khaled@test.com')
    ->withProfile(['bio' => 'Developer', 'twitter' => '@khaled'])
    ->withSettings(['theme' => 'dark', 'notifications' => true])
    ->build();

$user->save();

In the example below, we have added another real-world scenario for handling notifications with different parameters.

// NotificationBuilder.php
namespace App\Builders;

use App\Notifications\CustomNotification;

class NotificationBuilder
{
    protected $notification;

    public function __construct()
    {
        $this->notification = new CustomNotification();
    }

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

    public function withRecipient($recipient): self
    {
        $this->notification->recipient = $recipient;
        return $this;
    }

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

    public function build(): CustomNotification
    {
        return $this->notification;
    }
}

// Usage
$notification = (new NotificationBuilder())
    ->withMessage('You have a new message!')
    ->withRecipient($user)
    ->withChannel('email')
    ->build();

$user->notify($notification);

Conclusion: Here, we provide some examples in Laravel using the builder pattern concept. We created user profiles step-by-step with optional details, built database queries by selecting the parts you need, and set up notifications by customizing who gets which message.

2
Subscribe to my newsletter

Read articles from Khaled Rahman directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Khaled Rahman
Khaled Rahman

Hi, I am a full-stack developer with some real-world experience. Lets share knowledge with each other.