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.
Entrepreneur and full-stack web developer capable of multitasking and completing large-scale projects in a short period of time. Founder of moy-razmer.ru and nomadicsoft.io, large experience in e-commerce and various SaaS projects
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.