Andy Hinkle

Andy Hinkle

Laravel Developer


Using Conditional Traits for Clean Queries

February 2, 2025

Have you ever wrote a query and had a bunch of if filled with conditions? Such as you need to update a field, but only if it's filled. Looks something like this:

        
1if ($request->filled('title')) {
2 $message->title = $request->title;
3}
4 
5if ($request->filled('description')) {
6 $message->description = $request->description;
7}
8 
9if ($request->filled('completed')) {
10 $message->completed_at = now();
11}
12 
13if ($request->has('contacts')) {
14 $message->contacts()->syncWithoutDetaching($request->contacts);
15}
16 
17$message->save();

While this works, it can get messy if you add more conditions. A better way is to use conditional traits, which would change the code to look like this:

        
1$message
2 ->fillWhenPresent([
3 'title',
4 'description',
5 'completed' => fn ($message) => $message->completed_at = now(),
6 ])
7 ->attachWhenPresent('contacts')
8 ->save();

This is much cleaner and easier to read. Let's take a look at how this works.

Fill When Present

The fillWhenPresent method accepts an array of attributes to fill. If the attribute is present in the request, it will be filled. You can also pass a closure as the value, which will be executed if the attribute is present. This is useful for attributes that require some processing, such as setting a timestamp.

        
1namespace App\Models\Concerns;
2 
3trait HasConditionalFills
4{
5 public function fillWhenPresent(array $fields): self
6 {
7 collect($fields)->each(function ($value, $key) {
8 $field = is_numeric($key) ? $value : $key;
9 
10 if (request()->filled($field)) {
11 is_callable($value)
12 ? $value($this)
13 : $this->{$field} = request()->input($field);
14 }
15 });
16 
17 return $this;
18 }
19}

Attach When Present

The attachWhenPresent method is useful for attaching relationships. It will attach the relationship if it's present in the request. This is useful for many-to-many relationships, such as attaching speakers to a message.

        
1namespace App\Models\Concerns;
2 
3trait HasConditionalRelations
4{
5 public function attachWhenPresent(string $relation, ?string $field = null): self
6 {
7 $field = $field ?? $relation;
8 
9 if (request()->has($field)) {
10 $this->{$relation}()->syncWithoutDetaching(request($field));
11 }
12 
13 return $this;
14 }
15}

Conditional traits are a great way to keep your code clean and readable. They allow you to easily add conditions without cluttering your code with if statements.