Laravel HasManyThrough via many-to-many relationship - laravel

I have the following Models:
Students
Groups
Assignments
Students and Groups have a many-to-many relationship
Groups to Assignments is a one-to-many relationship
I would like to get a student's assignments using eloquent. My initial thought was to use the hasManyThrough relationship, but that won't work because of the many-to-many relationship between groups and students.
Is there an eloquent solution for this or will I need to write something of my own?
Thanks

Build your models as follows:
// Sample Eloquent Model for Students
class Student extends Model
{
public function groups()
{
return $this->hasMany(Group::class);
}
public function assignments()
{
$assignments = [];
foreach($this->groups as $group)
{
array_push($assignments, ...$group->assignments);
}
return $assignments;
}
}
// Sample Eloquent Model for Groups
class Group extends Model
{
public function students()
{
return $this->hasMany(Student::class);
}
public function assignments()
{
return $this->hasMany(Assignment::class);
}
}
// Sample Eloquent Model for Assignments
class Assignment extends Model
{
public function group()
{
return $this->belongsTo(Group::class);
}
}
And if you want to get students assignments:
$assignments = $student->assignments();

Related

BelongsToMany with one or vice versa relationship

I'm using Laravel and Eloquent.
I have a courses table and a Pivot table that holds the related courses.
My pivot table named relatedCourses has 2 columns, course1 & course2.
In the above example, Course ID 5 is related with Course ID 7.
$data["course"] = course::where("isActive",1)->with('related')->find(5);
This works and brings ID 7 as related.
If i try
$data["course"] = course::where("isActive",1)->with('related')->find(7) it should bring ID 5 as related, this is what i'm trying to achieve.
My code is like this in the model :
class course extends Model
{
public function category()
{
return $this->hasOne('App\courseCategory',"categoryId");
}
public function related()
{
return $this->belongsToMany('App\Models\course', 'relatedCourses', 'course1', 'course2');
}
}
You can define two relationships for this query.
class course extends Model
{
public function category()
{
return $this->hasOne('App\courseCategory',"categoryId");
}
public function relatedCourses()
{
return $this->belongsToMany('App\Models\Course', 'relatedCourses', 'course1', 'course2');
}
public function originalCourses()
{
return $this->belongsToMany('App\Models\Course', 'relatedCourses', 'course2', 'course1');
}
}
Then you can query your relations,
$data["course"] = course::where("isActive",1)->with('relatedCourses')->find(5);
and
$data["course"] = course::where("isActive",1)->with('originalCourses')->find(7);
To merge both relations you can do like this
$course = course::where("isActive",1)->with('originalCourses', 'relatedCourses')->get();
Hope this will help you.

Laravel | Using Eloquent hasManyThrough

I have a table called invoiceDetails that has item_id as foreign key from another table called items which has category_id as foreign key from table called categories.
I want to do that following using eloquent:
$result = InvoiceDetail::groupBy('item_id')
->selectRaw('sum(qty) as qty, item_id')->with('item', 'category')->get();
but I am getting error:
Call to undefined relationship [category] on model [App\InvoiceDetail].
Here's my relation inside Category model:
public function invoiceDetail() {
return $this->hasManyThrough('App\InvoiceDetail', 'App\Item', 'category_id', 'item_id');
}
Any suggestions?
Not sure you would even need a hasManyThrough relation here, unless you want to fetch all InvoiceDatail objects belonging to all items which in turn belong to the Category. That part is not clear from your question.
But in your example you are fetching items with their category from distinct item_id.
The reason this is not working is because you are trying to fetch the category relation from the InvoiceDetail object, which does not exist.
->with('item', 'category')
You want to load the Category based on the item relation, not based on the InvoiceDetail, try the dot notation (given that you did define the other relations)
->with('item.category')
Relations should be like this:
class InvoiceDetail extends Model
{
public function item()
{
return $this->belongsTo(\App\Item::class);
}
}
class Item extends Model
{
public function invoiceDetails()
{
return $this->hasMany(\App\InvoiceDetail::class);
}
public function category()
{
return $this->belongsTo(\App\Category::class);
}
}
class Category extends Model
{
public function items()
{
return $this->hasMany(\App\Item::class);
}
public function invoiceDetails()
{
return $this->hasManyThrough(\App\InvoiceDetail::class, \App\Item::class, 'category_id', 'item_id');
}
}
You would want to use the hasManyThrough if, for example, you have a Category and you want to load all the InvoiceDetails directly.
dd($category->invoiceDetails);

Laravel Eloquent - Get all records of child relation model

My data model is this:
Users > Offices > Organization
This is my model
class Organization extends Model {
protected $table = 'organizations';
public function offices()
{
return $this->hasMany('App\Models\Office');
}
public function users()
{
return $this->offices()->users();
}
....
So.. I want to get all users from an organization (of all the offices).
But I don't know how to do something like
$this->offices()->users();
(Avoiding user a manual collection or map to do that)
Thanks!
So, you have organization ID. You can load all users by using whereHas():
$users = User::whereHas('office', function ($q) use ($organizationId) {
$q->where('organization_id', $organizationId);
})
->get();
Make sure office() relationship is defined correctly in User model:
public function office()
{
return $this->belongsTo('App\Office');
}
Alternatively, you could define hasManyThrough() relationship:
public function users()
{
return $this->hasManyThrough('App\Office', 'App\User');
}
And use it:
$organization->users()

Laravel query multiple tables using eloquent

hi sorry bit of a newbie here but I am have three tables users, profiles, friends. they all have the user_id fields within them and I want fetch all of the fields in one statement using Eloquent and not DB::statement and doing the table joins.
How can I achieve this?
Try this
use the User class and the with method that laravel has to query model relationships
$user = User::with(['profile', 'friend'])->get();
Ensure your models has the correct relationships as follows:
app/models/User.php
public function friend () {
return $this->hasMany('Friend');
}
public function profile () {
return $this->hasOne('Profile');
}
app/models/Profile.php
public function user() {
return $this->belongsTo('User');
}
app/models/Friend.php
public function user() {
return $this->belongsTo('User');
}
use some thing like this:
You should define relations in your models with hasOne, hasMany.
class Review extends Eloquent {
public function relatedGallery()
{
$this->hasOne('Gallery', 'foreign_id', 'local_id');
}
}
class Gallery extends Eloquent {
public function relatedReviews()
{
$this->hasMany('Review', 'foreign_id', 'local_id');
}
}
$gallery = Gallery::with('relatedReviews')->find($id);
Will bring the object Gallery with
$gallery->id
gallery->name
...
$gallery->relatedReviews // array containing the related Review Objects

Many to Many with additional table in L4

I have a schema like that:
And now I want to use it in Laravel 4. So far, I could only achieve getting games for certain user, without touching owntype. Code:
public function games() {
return $this->belongsToMany('Game','games_users','owntype_id','games_id')->where('user_id','1');
}
The only thing I'm getting is onwtype_id. How can I add owntype table to the "equasion"?
You can access extra pivot table columns by specifying them through the withPivot function on the relationship function.
Basically I think you want to do this:
class User extends Eloquent {
public function games()
{
return $this->belongsToMany('Game', 'games_users')->withPivot('owntype_id');
}
}
class Game extends Eloquent {
public function users()
{
return $this->belongsToMany('User', 'games_users')->withPivot('owntype_id');
}
}
class Owntype extends Eloquent {
protected $table = 'owntype';
}
// Now you can do:
foreach ($user->games as $game)
{
// Echo each Owntype description.
echo Owntype::find($game->pivot->owntype_id)->description;
}
For the record... I think you might be taking it too far by creating a new table for owntype. Just set the description as a type column on the pivot table. Also make sure that your pivot table is named game_user (singular, alphabetically) and Laravel will know which pivot table to use automatically.
class User extends Eloquent {
public function games()
{
return $this->belongsToMany('Game')->withPivot('type');
}
}
class Game extends Eloquent {
public function users()
{
return $this->belongsToMany('User')->withPivot('type');
}
}
// Now you can do:
foreach ($user->games as $game)
{
// Echo each ownership type.
echo $game->pivot->type;
}
Some more info about working with pivot tables can be founded in the Laravel 4 docs.

Resources