datavoredan
datavoredan

Reputation: 3746

Laravel Eloquent - accessing second level model relationship

This question extends the example Eloquent : Working With Pivot Tables provided in the Laravel Documentation.

The relationship here is that a User has many Role objects that it can relate to. In this extension, each Role will relate to a number of Task objects, giving us a second level many-to-many relationship.

Using Eloquent ORM, what would be the neatest way of accessing the Tasks that a user relates to?

Specifically, the following method should return an array of task_ids

User::get_tasks($user_id)

Upvotes: 2

Views: 3695

Answers (3)

Ray
Ray

Reputation: 649

I believe the neatest way is to use hasManyThrough relationship as follows:

class User extends Eloquent {
    public function get_tasks()
    {
        return $this->hasManyThrough('Tasks', 'Roles');
    }
}

You only need to modify Tasks and Roles to your named corresponding model. It shall return you a list of tasks. Hope this helps.

Upvotes: 1

lukasgeiter
lukasgeiter

Reputation: 152890

Even though @JosephSilber's answer looks great it unfortunately didn't work when I tested it, so here's something that worked on my installation:

public static function get_tasks($id){
    $tasks = static::with('roles.tasks')->find($id)->roles->lists('tasks');
    $collection = new \Illuminate\Database\Eloquent\Collection();
    foreach($tasks as $roleTasks){
        $collection = $collection->merge($roleTasks);
    }
    return $collection;
}

Personally I'd change the syntax a bit to this:

public function getTasks(){
    $this->load('roles.tasks');
    $tasks = $this->roles->lists('tasks');
    $collection = new \Illuminate\Database\Eloquent\Collection();
    foreach($tasks as $roleTasks){
        $collection = $collection->merge($roleTasks);
    }
    return $collection;
}

User::find($user_id)->getTasks();

Upvotes: 0

Joseph Silber
Joseph Silber

Reputation: 219938

use Illuminate\Database\Eloquent\Collection;

class User extends Eloquent {

   // ... relation methods...

    public function get_tasks($id)
    {
        $tasks = static::with('roles.tasks')->find($id)->roles->lists('tasks');

        return (new Collection(array_flatten($tasks)))->unique();
    }

}

Upvotes: 2

Related Questions