logo
podcast Podcast
get help Get Unstuck

Making better use of docblocks

An improvement on a previous tip

Joel Clermont
Joel Clermont
2024-09-24

Last week, I shared an approach I use to get better types in API resources.

In short, I used a temporary variable in order to add a docblock, so I could add the model's type to the resource.

Between posts on social media and direct email replies, I got at least 20 responses saying that while they like the better typing, they suggested a better way to do it. There were basically two different suggestions, but the one thing they had in common is that they didn't introduce a variable just to decorate it with a docblock.

One approach was to use a docblock on the resource class to add a type to the property:

/** @property Note $resource */
class NoteResource extends JsonResource
 {
     /**
      * @return array<string, mixed>
      */
     public function toArray(Request $request): array
     {
        // removed for simplicity
     }
 }

The other suggested approach was to use the class docblock to specify a "mixin" for the whole class:

/** @mixin Note */
class NoteResource extends JsonResource
 {
     /**
      * @return array<string, mixed>
      */
     public function toArray(Request $request): array
     {
        // removed for simplicity
     }
 }

Both approaches work, but let's discuss the mixin approach a bit more.

What is a mixin? It's essentially saying "this Resource class also has all the properties and methods as a Note model".

Hold on, is this true? Since the resource class uses the DelegatesToResource trait, any calls to the model which don't exist on the resource will get passed to the resource's model class. So it is mostly true, unless there happens to be a collision between a property or method name on the model and one on the resource.

Which one of these two approaches would I use? Both are valid, but personally, I would rather type the property instead of relying on the mixin.

In fact, if I prefer to access all model methods and properties via $this->resource instead of through $this and avoiding the call forwarding.

In both cases, it just seems more explicit as to what is intended.

Here to help,

Joel

P.S. We just published three volumes of Laravel tips as downloadable ebooks. Go check it out!

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼
email
No spam. Only real-world advice you can use.