title: Laravel - Lot of Accessors (Mutators) for rendering Views with Blade
body: <p>I have a Laravel 7 project with the need of a lot of data transformation from the model to the views before being displayed.</p>
  
  <p>I thought about using <a href="https://laravel.com/docs/7.x/eloquent-mutators#defining-an-accessor" rel="noreferrer">Laravel Accessors</a> and use them directly in my blade.php files.<br>
  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.  </p>
  
  <h1>Blade view</h1>
  
  <pre><code>@foreach($races as $race)
  &lt;tr&gt;
      &lt;td&gt;{{ $race-&gt;display_dates }}&lt;/td&gt;
      &lt;td&gt;{{ $race-&gt;display_name }}&lt;/td&gt;
      &lt;td&gt;{{ $race-&gt;type-&gt;name }}&lt;/td&gt;
      &lt;td&gt;{{ $race-&gt;display_price }}&lt;/td&gt;
      &lt;td&gt;{{ $race-&gt;display_places }}&lt;/td&gt;
      &lt;td&gt;{{ $race-&gt;online_registration_is_open ? 'Yes' : 'No' }}&lt;/td&gt;
  &lt;/tr&gt;
  @endforeach
  </code></pre>
  
  <h1>Controller</h1>
  
  <pre><code>public function show(Group $group)
  {
      $races = $group-&gt;races;
      $races-&gt;loadMissing('type'); // Eager loading
      return view('races', compact('races'));
  }
  </code></pre>
  
  <h1>Model</h1>
  
  <pre><code>// Accessors
  public function getOnlineRegistrationIsOpenAttribute()
  {
      if (!$this-&gt;online_registration_ends_at &amp;&amp; !$this-&gt;online_registration_starts_at) return false;
      if ($this-&gt;online_registration_ends_at &lt; now()) return false;
      if ($this-&gt;online_registration_starts_at &gt; now()) return false;
      return true;
  }
  
  public function getNumberOfParticipantsAttribute()
  {
      return $this-&gt;in_team === true
          ? $this-&gt;teams()-&gt;count()
          : $this-&gt;participants()-&gt;count();
  }
  
  // Accessors mainly used for displaying purpose
  public function getDisplayPlacesAttribute()
  {
      if ($this-&gt;online_registration_ends_at &lt; now()) {
          return "Closed registration";
      }
      if ($this-&gt;online_registration_starts_at &gt; now()) {
          return "Opening date: " . $this-&gt;online_registration_starts_at;
      }
      return "$this-&gt;number_of_participants / $this-&gt;max_participants";
  }
  
  public function getDisplayPriceAttribute()
  {
      $text = $this-&gt;online_registration_price / 100;
      $text .= " €";
      return $text;
  }
  
  public function getDisplayDatesAttribute()
  {
      $text = $this-&gt;starts_at-&gt;toDateString();
      if ($this-&gt;ends_at) { $text .= " - " . $this-&gt;ends_at-&gt;toDateString(); }
      return $text;
  }
  
  public function getDisplayNameAttribute()
  {
      $text = $this-&gt;name;
      if ($this-&gt;length) { $text .= " $this-&gt;length m"; }
      if ($this-&gt;elevation) { $text .= " ($this-&gt;elevation m)"; }
      return $text;
  }
  </code></pre>
  
  <p>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 <code>name</code> column while I am creating a <code>getDisplayNameAttribute</code> accessor here.<br>
  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 <code>getDisplayNameAttribute</code> could be used in a regular page and an admin page (and maybe more).</p>
  
  <p>I also looked at <a href="https://laravel.com/docs/7.x/eloquent-resources#concept-overview" rel="noreferrer">JsonResource</a> and <a href="https://laravel.com/docs/7.x/views#view-composers" rel="noreferrer">ViewComposer</a> but <code>JsonResource</code> seems to be for <code>APIs</code> while <code>ViewComposer</code> seems to be especially for <code>Views</code>.</p>
  
  <p>I also thought about prefixing the accessors with something like <code>acc_</code> to reduce mistakes with existing db column :</p>
  
  <pre><code>public function getAccDisplayNameAttribute() { ... };
  </code></pre>
  
  <p>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.</p>