I have a Laravel 7 project with the need of a lot of data transformation from the model to the views before being displayed.
I thought about using Laravel Accessors and use them directly in my blade.php files.
But when I finished dealing with a simple html table, I looked at my code and I think there is too many accessors and even some of them have a difficult name to read.
Blade view
@foreach($races as $race)
<tr>
<td>{{ $race->display_dates }}</td>
<td>{{ $race->display_name }}</td>
<td>{{ $race->type->name }}</td>
<td>{{ $race->display_price }}</td>
<td>{{ $race->display_places }}</td>
<td>{{ $race->online_registration_is_open ? 'Yes' : 'No' }}</td>
</tr>
@endforeach
Controller
public function show(Group $group)
{
$races = $group->races;
$races->loadMissing('type'); // Eager loading
return view('races', compact('races'));
}
Model
// Accessors
public function getOnlineRegistrationIsOpenAttribute()
{
if (!$this->online_registration_ends_at && !$this->online_registration_starts_at) return false;
if ($this->online_registration_ends_at < now()) return false;
if ($this->online_registration_starts_at > now()) return false;
return true;
}
public function getNumberOfParticipantsAttribute()
{
return $this->in_team === true
? $this->teams()->count()
: $this->participants()->count();
}
// Accessors mainly used for displaying purpose
public function getDisplayPlacesAttribute()
{
if ($this->online_registration_ends_at < now()) {
return "Closed registration";
}
if ($this->online_registration_starts_at > now()) {
return "Opening date: " . $this->online_registration_starts_at;
}
return "$this->number_of_participants / $this->max_participants";
}
public function getDisplayPriceAttribute()
{
$text = $this->online_registration_price / 100;
$text .= " €";
return $text;
}
public function getDisplayDatesAttribute()
{
$text = $this->starts_at->toDateString();
if ($this->ends_at) { $text .= " - " . $this->ends_at->toDateString(); }
return $text;
}
public function getDisplayNameAttribute()
{
$text = $this->name;
if ($this->length) { $text .= " $this->length m"; }
if ($this->elevation) { $text .= " ($this->elevation m)"; }
return $text;
}
This code is working but I think it has a lot of cons : readability, mistake are possible, for example if the associated DB table has a name
column while I am creating a getDisplayNameAttribute
accessor here.
And that's only a start, I think I will need 30-40 more accessors for the other views...
Also, I will need to use some of them many time, for example getDisplayNameAttribute
could be used in a regular page and an admin page (and maybe more).
I also looked at JsonResource and ViewComposer but JsonResource
seems to be for APIs
while ViewComposer
seems to be especially for Views
.
I also thought about prefixing the accessors with something like acc_
to reduce mistakes with existing db column :
public function getAccDisplayNameAttribute() { ... };
But I really don't think that's a solution, I'm not even sure if what I am doing is right or wrong. I also searched for best practices over the internet, without success.