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$message2 ->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.
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}
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.