Laravel many to many relationship with pivot table - laravel

if I try the following the page is loading endless:
$user_departments = User::find(1)->departments();
There are the following tables:
- users
- user_department
- departments
The pivot table user_department has got this two foreign keys:
- department_id
- user_id
In my user model:
public function departments()
{
return $this->belongsToMany('App\Department', 'user_department', 'user_id', 'department_id')->withTimestamps();
}
In my department model:
public function users()
{
return $this->belongsToMany('App\User', 'user_department', 'department_id', 'user_id')->withTimestamps();
}
By the way: The following code is working:
$user->departments()->syncWithoutDetaching($department->id);
But I can't get the departments of the user without breaking my page.
Any ideas?

When fetching the departments of a user. You should actually get() the results. With $user->departments() you are getting the query builder which isn't a collection of results.
Alternatively of using the get() method ($user->departments()->get()) You could use a shortcut: $user->departments.

Use below syntax to get user departments :
$user->departments;
to insert :
$user->departments()->attach($department->id);
to remove :
$user->departments()->detach($department->id);
and for sync :
$arr=array(13,25,12);
$user->departments()->sync($arr);

Related

Retrieve grouped relation with Eloquent ORM

I have a relationship which looks like this:
User
- id
Menu
- id
- appetizer_id
- main_course_id
- dessert_id
User_Menu
- user_id
- menu_id
and corresponding models:
class User
{
public function menus()
{
return $this->belongsToMany('App\Models\Menu', 'user_menu', 'user_id', 'menu_id');
}
}
class Menu
{
public function dessert()
{
return $this->belongsTo('App\Models\Dessert', 'dessert_id');
}
}
In other words there are users and menus with a many to many relationship. Now I would like to retrieve all the distinct desserts for a given user. I've tried using group by, but it does not allow me to select and group by a single column, because the pivot columns are always included in the query:
$desserts = User::find(1)->menus()
->select('dessert_id')
->groupBy('dessert_id')
->with('dessert')
->get();
throws the following error:
'User_Menu.user_id' isn't in GROUP BY
$desserts = User::join('User_Menu', 'User.id', '=', 'User_Menu.user_id')
->join('Menu', 'User_Menu.menu_id', '=','Menu.id')
->get();

Get only one column from relation

I have found this: Get Specific Columns Using “With()” Function in Laravel Eloquent
but nothing from there did not help.
I have users table, columns: id , name , supplier_id. Table suppliers with columns: id, name.
When I call relation from Model or use eager constraints, relation is empty. When I comment(remove) constraint select(['id']) - results are present, but with all users fields.
$query = Supplier::with(['test_staff_id_only' => function ($query) {
//$query->where('id',8); // works only for testing https://laravel.com/docs/6.x/eloquent-relationships#constraining-eager-loads
// option 1
$query->select(['id']); // not working , no results in // "test_staff_id_only": []
// option 2
//$query->raw('select id from users'); // results with all fields from users table
}])->first();
return $query;
In Supplier model:
public function test_staff_id_only(){
return $this->hasMany(User::class,'supplier_id','id')
//option 3 - if enabled, no results in this relation
->select(['id']);// also tried: ->selectRaw('users.id as uid from users') and ->select('users.id')
}
How can I select only id from users?
in you relation remove select(['id'])
public function test_staff_id_only(){
return $this->hasMany(User::class,'supplier_id','id');
}
now in your code:
$query = Supplier::with(['test_staff_id_only:id,supplier_id'])->first();
There's a pretty simple answer actually. Define your relationship as:
public function users(){
return $this->hasMany(User::class, 'supplier_id', 'id');
}
Now, if you call Supplier::with('users')->get(), you'll get a list of all suppliers with their users, which is close, but a bit bloated. To limit the columns returned in the relationship, use the : modifier:
$suppliersWithUserIds = Supplier::with('users:id')->get();
Now, you will have a list of Supplier models, and each $supplier->users value will only contain the ID.

Why is the ID replaced with a value from another table? Laravel BelongsTo

I have 4 tables. Championships, Users, Roles and users_roles.
One user belongs to championship as judge. But I have to select only users who have role 'Judge'.
For this, I created new column in championships table which is called "main_judge" and created new relationship
class Championship extends Model
{
...
public function mainJudge()
{
return $this->hasOne('App\User', 'id', 'main_judge');
}
...
}
Then I add to query some code
$query->join('users_roles', 'users.id', '=', 'users_roles.user_id')
->join('roles', 'users_roles.role_id', '=', 'roles.id')
->where('roles.alias', '=', 'judge');
when I print query as sql I got (see screen)
http://joxi.ru/a2X45M1Sw0RpE2
and after $query->get() instead of user ID i got a role ID (see screen)
http://joxi.ru/bmoxMaDs3NVoE2
I would suggest using eloquent rather than the query builder as it will remove the need to manually define any joins.
You should just be able to do this:
$championship = Championship::find($id);
$judge = $championship->mainJudge;
If you then dd($judge) you should end up with the appropriate User object.

Laravel: How to write a join count query on belongsToMany relationships?

I got the following:
User, Role, with a role_user pivot table and a belongsToMany
relationship
User, Location, with a location_user pivot table and a belongsToMany relationship
There's 2 roles for the user: owner & gardener
Location has a 'gardeners_max' field
In model Location:
protected $appends = ['is_full'];
public function getIsFullAttribute()
{
return $this->attributes['name'] = $this->remainingGardeners() <= 0;
}
public function countGardeners()
{
return $this->gardeners()->count();
}
public function remainingGardeners()
{
return $this->gardeners_max - $this->countGardeners();
}
Now, doing that :
Location::all();
I get that :
[
{
name: 'LocationA',
gardeners_max: 3,
owners: [...],
garderners: [...]
...
is_full: false
}
]
which is cool. BUT... it's not possible to do a WHERE clause on the appended attribute.
Location::where('is_full',true)->get() // Unknown column 'is_full' in 'where clause'
So i'd like to write a join query so I can do a where clause on is_full
And I just can't find the way. Any help will be greatly appreciated!
IMPORTANT:
I know the filter() method to get the results but I need to do a single scopeQuery here
You could try to manipulate the Collection after loading the object from database:
Location::get()->where('is_full', true)->all();
(You have to use get first then all, not sure it works otherwise)
Not sure it's optimized thought.
You can make scope in your location model like this
public function scopeFull(Builder $query)
{
return $query->where('is_full', true);
}
Now you just get all location like this
Location::full()->get();

Get Collection With HasOne Relationship

In my User model in Laravel 5.2 I have a relationship setup with their status to the company.
public function companyStatus()
{
return $this->hasOne('CompanyUser')->select('status');
}
The CompanyUser table has a company_id, user_id, and status field
Then in my controller I do the following:
$company = Company::find($company_id);
$users = CompanyUser::where('company_id', $company_id)->pluck('user_id')->toArray();
$user_data = User::with('companyStatus')->find($users);
but when I dump the user_data array it has all of the users related to the company, but just shows null for their status relationship
{
"id":2,
"name":"Moderator",
"email":"mod#company.com",
"created_at":"2016-09-08 15:26:20",
"updated_at":"2016-09-08 15:26:25",
"company_status":null
}
If I however return just the User collection to the view, and iterate over each user and run
$user->companyStatus->status
the value displays, but I am trying to include this within the collection for a JSON API to consume.
UPDATE
I tried adding the foreign key to the select call on my relationship method:
public function companyStatus()
{
return $this->hasOne('CompanyUser')->select('status', 'user_id');
}
and it now returns the following:
{
"id":2,
"name":"Moderator",
"email":"mod#company.com",
"created_at":"2016-09-08 15:26:20",
"updated_at":"2016-09-08 15:26:25",
"company_status": {"status":"1","user_id":"2"}
}
Not sure if this is the best/correct method or not though.
Okay I figured it out.
I tried adding the foreign key to the select call on my relationship method:
public function companyStatus()
{
return $this->hasOne('CompanyUser')->select('status', 'user_id');
}
Then that returns:
{
"id":2,
"name":"Moderator",
"email":"mod#company.com",
"created_at":"2016-09-08 15:26:20",
"updated_at":"2016-09-08 15:26:25",
"company_status": {"status":"1","user_id":"2"}
}
Without the foreign key Laravel obviously can't determine the related data on the other table.

Resources