Overview
The Fluent Interface pattern is a Behavioural design pattern that provides a chainable and expressive API for interacting with objects. It allows methods to return the same object, enabling a sequence of method calls to be made in a single statement. This simplifies the code and makes it more readable, while abstracting the complexity of interacting with the underlying object.
Think about when you’ve built a database query, configured a service, or set up routes in a framework like Laravel. You’ve probably chained methods together to create clear, expressive, and compact code. That’s a Fluent Interface in action!
Example
Let’s explore how the Fluent Interface pattern can make building queries more expressive and readable. We'll use a Query class to construct SQL-like queries.
Here is a class definition:
class Query
{
private string $query = '';
public function select(string $columns): self
{
$this->query .= sprintf('SELECT %s ', $columns);
return $this;
}
public function from(string $table): self
{
$this->query .= sprintf('FROM %s ', $table);
return $this;
}
public function where(string $condition): self
{
$this->query .= sprintf('WHERE %s ', $condition);
return $this;
}
public function orderBy(string $column, string $direction = 'ASC'): self
{
$this->query .= sprintf('ORDER BY %s %s ', $column, $direction);
return $this;
}
public function getQuery(): string
{
return trim($this->query);
}
}With this implementation, you can chain method calls to build a query:
$query = new Query();
$sql = $query->select('id, name')
->from('users')
->where('age > 18')
->orderBy('name')
->getQuery();
// Output: SELECT id, name FROM users WHERE age > 18 ORDER BY name
echo $sql;An alternative version without chaining would require invoking each method individually and managing state manually:
$query = new Query();
$query->select('id, name');
$query->from('users');
$query->where('age > 18');
$query->orderBy('name');
$sql = $query->getQuery();
// Output: SELECT id, name FROM users WHERE age > 18 ORDER BY name
echo $sql;See the difference? Let’s do a quick comparison:
Fluent Interface
Pros:
Clean and expressive code.
Reduces boilerplate and repetitive statements.
Encourages a logical flow of operations.
Cons:
May be harder to debug if one step fails in a long chain.
Non-Chained Version
Pros:
More explicit and straightforward for debugging.
Easier to modify intermediate steps if needed.
Cons:
Requires more code to achieve the same result.
Can lead to a cluttered and less expressive implementation.
That’s it! Design patterns aren’t scary, they’re actually pretty simple (and cool!).
Want to see the Fluent Interface Pattern in action? Check out this a few simple PHP examples: Github
The Grumpy Dev is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.
