Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Eloquent and complex relationships

Laravel seems like a very nice PHP framework, bundled with a good ORM (Eloquent). However, the laravel docs are some what lacking. Only the basic stuff is present in the doc.

Anyway, I have a problem when it comes to Eloquent and model relationships when it spans more than 2 models.

For example, I have the following scenario.

I have four database tables namely: users, locations, users_locations, packages. And the relationship between the model/tables are as follows:

User can belong to many Location and vice-versa. A location can have many packages.

And my corresponding model relationships are as follows:

//User Model:
public function locations(){
    return $this->belongsToMany('Location', 'users_locations', 'user_id', 'location_id');
}

//Location Model:
public function users(){
    return $this->belongsToMany('User', 'users_locations', 'location_id', 'user_id');
}
public function packages(){
    return $this->hasMany('Package', 'location_id');
}

//Package Model:
public function location(){
    return $this->belongsTo('Location', 'location_id');
}

What do I want to do?: I want to get all the packages belong to a user. A user belongs to locations, and packages also belong to locations. So from all the locations that belong to the user, I want to retrieve the packages those belong to those locations of the user. I also want the result set to be paginated.

I have tried the following:

//get the logged in user ID
$userId = Auth::user()->id
//first get all the locations of the user
$locations= User::with('locations')->find($userId)->locations;
//declare an empty array to store the packages
$packages = array();
//now loop through the locations
foreach($locations as $location){
    //since each location can have many packages, we also have to loop through the packages
    foreach($location->packages as $package){
        //store the plan in the array
        $packages[] = $package;
    }
}
//ok now we got the list of packages
return $packages;

The problem is, with the above, I cannot implement pagination on the packages. Does anyone know how to do it properly and in an efficient manner using Eloquent? Or is it just not possible?

like image 320
WebNovice Avatar asked Oct 15 '13 17:10

WebNovice


1 Answers

//get the logged in user ID
$userId = Auth::user()->id
//first get all the locations of the user
$locations= User::with('locations')->find($userId)->locations;


/* perhaps you can alternatively use lists() function to get the ids
 something like: $loc_ids = DB::table('locations')->where('user_id',$userId)->lists('id'); */
$loc_ids = array();
foreach($locations as $location)
{
   $loc_ids[] = $location->id;
}

$packages = Package::whereIn('location_id', $loc_ids)->skip($offset)->take($page_size)->get();

return $packages;
like image 75
Glad To Help Avatar answered Oct 07 '22 15:10

Glad To Help