What if I told you that Builder is a design pattern you already use daily without even noticing?
Take a look at this code.
$user = User::query() ->where('is_active', 1) ->orderBy('updated_at', 'desc') ->first();
Wait, it's a typical Eloquent query. It's not any Builder pattern, right? Well, not exactly.
You see, this pattern is exactly about that: building an object and adding methods to it, like in the example above.
So, we have an Eloquent model, and then we're building the query on top of it, finally calling the ->first()
to retrieve the data.
If we take a look at the source of the ->where()
method, we find this:
/** * Add a basic where clause to the query. * * @param \Closure|string|array|\Illuminate\Database\Query\Expression $column * @param mixed $operator * @param mixed $value * @param string $boolean * @return $this */public function where($column, $operator = null, $value = null, $boolean = 'and'){ if ($column instanceof Closure && is_null($operator)) { $column($query = $this->model->newQueryWithoutRelationships()); $this->query->addNestedWhereQuery($query->getQuery(), $boolean); } else { $this->query->where(...func_get_args()); } return $this;}
As you can see, it called some methods and returns the object itself: return $this;
. This is exactly the behavior of the Builder pattern. And isn't it a coincidence that it's called a Query Builder?
So, essentially, you use a Builder pattern if you have a class with internal methods that change the behavior of the class object and return the object itself.
It means that when using the class, you can chain the methods, building more and more functionality of the object.
Have you seen this code in Laravel docs for Notifications?
public function toMail(object $notifiable): MailMessage{ $url = url('/invoice/'.$this->invoice->id); return (new MailMessage) ->greeting('Hello!') ->line('One of your invoices has been paid!') ->lineIf($this->amount > 0, "Amount paid: {$this->amount}") ->action('View Invoice', $url) ->line('Thank you for using our application!');}
See, we're building the MailMessage object, adding more and more methods to it in a chain.
And look what's inside the greeting()
or action()
methods, for example:
Illuminate/Notifications/Messages/SimpleMessage.php:
class SimpleMessage{ public $greeting; public $actionText; public $actionUrl; // ... more properties and methods public function greeting($greeting) { $this->greeting = $greeting; return $this; } public function action($text, $url) { $this->actionText = $text; $this->actionUrl = $url; return $this; }}
See that return $this
. Does it feel familiar now?
Ok, cool, now you understand that Query/Mail Builder is following a Builder pattern, so what?
The thing is that you can choose to adopt this pattern in your classes.
Let's take a look at an example...