Home » Php » Laravel Eloquent: How to automatically fetch relations when serializing through toArray/toJson

Laravel Eloquent: How to automatically fetch relations when serializing through toArray/toJson

Posted by: admin October 29, 2017 Leave a comment

Questions:

I figures this works for automatically fetching user and replies when I am serializing my object to JSON, but is overriding toArray really the proper way of doing this?

<?php

class Post extends Eloquent
{
    protected $table = 'posts';
    protected $fillable = array('parent_post_id', 'user_id', 'subject', 'body');

    public function user()
    {
        return $this->belongsTo('User');
    }

    public function replies()
    {
        return $this->hasMany('Post', 'parent_post_id', 'id');
    }

    public function toArray()
    {
        $this->load('user', 'replies');
        return parent::toArray();
    }
}
Answers:

Instead of overriding toArray() to load user and replies, use $with.

Here’s an example:

<?php

class Post extends Eloquent
{
    protected $table = 'posts';
    protected $fillable = array('parent_post_id', 'user_id', 'subject', 'body');

    protected $with = array('user', 'replies');


    public function user()
    {
        return $this->belongsTo('User');
    }

    public function replies()
    {
        return $this->hasMany('Post', 'parent_post_id', 'id');
    }

}

Also, you should be using toArray() in your controllers, not your models, like so:

Post::find($id)->toArray();

Hope this helps!

Questions:
Answers:

I must submit a new answer since I’m a SO pleb. A more proper way to accomplish this for those finding this on Google like I did would be to avoid using protected $with if you don’t have to and instead move that with() call to your retrieval.

<?php

class Post extends Eloquent
{
    protected $table = 'posts';
    protected $fillable = array('parent_post_id', 'user_id', 'subject', 'body');


    public function user()
    {
        return $this->belongsTo('User');
    }

    public function replies()
    {
        return $this->hasMany('Post', 'parent_post_id', 'id');
    }

}

And then you could modify the Post call to pre-load as needed:

Post::with('user','replies')->find($id)->toArray();

This way, you won’t be including un-needed data every time you grab a record, if you don’t need it.