Extracting Relations to Traits in Laravel Models

Extracting Relations to Traits in Laravel Models
Gregory Shein
Extracting Relations to Traits in Laravel Models

Hey maybe it’s just me, but maybe you also noticed that once the project becomes big, models tend to grow exponentionally. While this is not bad by itself, but up to 80% of the code is Laravel relations which eat up all the screen space and you have to constantly scroll through them to get to the spot that you really need. Also, they don’t change much. Like if you have a store and user has many orders, there’s not likely that much will change down the road right?

So let’s take the usual blog model to illustrate what to be done.

So we have three good ol’ models: user, post and comment.

So here’s User.php:

class User extends Authenticatable
{  
/// I've removed $hidden, $fillable etc
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

Here’s Comment.php:

class Comment extends Model
{
    public function post()
    {
        $this->belongsTo(Post::class);
    }
    public function user()
    {
        $this->belongsTo(User::class);
    }
}

And here’s Post.php

class Post extends Model
{
    public function user()
    {
        $this->belongsTo(User::class);
    }
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

Nothing wrong with that, but you already have to scroll and this code doesn’t even do anything but state the obvious, and most likely it will never change and you’ll have to just scroll through it until the project is finished.

What we can do is to create Relations folder and extract all this code there. So

Relations\BelongsToUser.php

trait BelongsToUser
{
    /**
     * @property $this \Illuminate\Database\Eloquent\Model
     */
    public function user()
    {
        return $this->belongsTo(User::class)->withDefault([new User()]);
    }
}

withDefault() is a convenitent helper to get rid of all those null pointers I’m sure you’ll getting (or again, it’s JUST me)

 

So there’s also Relations\HasManyPosts.php

trait HasManyPosts
{
    /**
     * @property $this \Illuminate\Database\Eloquent\Model
     */
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

So there’s also Relations\HasManyComments.php

trait HasManyComments
{
    /**
     * @property $this \Illuminate\Database\Eloquent\Model
     */
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

Finally Relations\BelongsToPost

trait BelongsToPost
{
    /**
     * @property $this \Illuminate\Database\Eloquent\Model
     */
    public function post()
    {
        $this->belongsTo(Post::class);
    }
}

So after cleaning up, our models look much cleaner:

User.php

class User extends Authenticatable
{
    use Notifiable;
    use HasManyComments, HasManyPosts;
}

Post.php

class Post extends Model
{
    use BelongsToUser, HasManyComments;
}

Comment.php

class Comment extends Model
{
    use BelongsToUser, BelongsToPost;
}

I guess one might say that we didn’t really shorten the code, we just shoved it all in a separate folder. But we actually did shorten it if relations repeat themselves (and let’s face it in a big project a lot of stuff belongs to a user). And also I would argue that Relations folder will be the one you will hardly ever look into.

But there’s a downside, of course. Say you’d want to make things a bit more interesting let’s make comments polymorphic so that not only posts can have them, but users. So you can leave your enlightened “u retarded lol” or “do u even code” comment not only to this post but to my person in general.

In that case comment()->user() will be not very intuitive and can cause errors, so one might argue it’d be better to call this relation ->author()

But to be honest you need to think does storing comments to users and posts in the same table even makes sense.

 

 

Ecommerce info block
Contact us to learn more

Hire a eCommerce Web or App Developer

Custom eCommerce development starts with your needs. No matter what size your business is, crafting killer websites or robust applications with Nomadic Soft is a winning strategy. Our development team will always use the latest tech tools to build your business interactive and engaging web interfaces and applications.

Contact Us

By sending this form I confirm that I have read and accept Nomadic soft Privacy Policy
×
Thanks!
Sent!
×
Error!