Convert (User,Role,user_role) SQL Raw Query to Eloquent In Laravel - php

Respected sir,I have to fetch user role name from user_role pivot table.
I successfully done by this using Sql Raw Query.but i have to use Eloquent.
Please convert below raw sql code into Eloquent,Please help me
sir i am new in laravel.
$role = DB::table('users')
->join('user_roles', 'users.id', '=', 'user_roles.user_id')
->join('roles', 'roles.id', '=', 'user_roles.role_id')
->select('roles.name')->where('users.id', '=',$user->id)
->get();

you could try Laravel Eloquent's manyToMany relationship. It's the same exact setup as you have here with a pivot table.
Add this method to your User model
function roles {
return $this->belongsToMany('App\Role', 'user_roles', 'user_id', 'role_id');
}
In your controller you could use
$roles = User::with('roles:name')->where('id', $user->id)->get();
Do try this method, you dont have to change anything to you db just adjust your model and controller.
For more info here's the documentation

Related

Laravel Spatie Query Builder - Wrong query when make join

I have a problem with packages spatie/Laravel-query-builder. I used this package for easy way to filter and sort my query but it's not like that :D
I trying to filter result who have two relation - shop and employee. In short, it wants to filter a list of store reports
Look, this is my code. When I use join method then in response receives data with incorrect ID. When comment join methods all it's okey but I need sorting by relation.
return ReportControlResource::collection(
QueryBuilder::for(Report::class)
->with(['employee', 'shop'])
->allowedFilters('shop.name', 'employee.name')
->join('employees', 'employees.id', '=', 'reports.employee_id')
->join('shops', 'shops.id', '=', 'reports.shop_id')
->allowedSorts(['employees.name'])
->get()
);
My relation in Report model:
public function shop(): BelongsTo
{
return $this->belongsTo(Shop::class);
}
public function employee(): BelongsTo
{
return $this->belongsTo(Employee::class);
}
Relation in Shop model:
public function reports()
{
return $this->hasMany(Report::class);
}
And in Employee model
public function reports()
{
return $this->hasMany(Report::class);
}
Do you have any ideas?
I noticed that the ID is being overwritten, but not shop_id and employee_id, but the ID why??
I think the problem is with the library itself. The creators did not take into account the reverse situation of joining tables as in my case.
Look at example from Doc:
$addRelationConstraint = false;
QueryBuilder::for(User::class)
->join('posts', 'posts.user_id', 'users.id')
->allowedFilters(AllowedFilter::exact('posts.title', null, $addRelationConstraint));
And my join
->join('employees', 'employees.id', '=', 'reports.employee_id')
But this join work like this
->join('employees', 'reports.id', '=', 'reports.employee_id')
But why? I checked the order in many ways, even disconnecting filtering and it did not change anything
I found solution for the problem. I had to select a column and now all works fine :-)
return EvidenceControlResource::collection(
QueryBuilder::for(EvidenceControl::class)
->allowedIncludes('employee', 'shop')
->select('evidence_controls.*', DB::raw('employees.id as employee_id'))
->join('employees', 'evidence_controls.employee_id', '=', 'employees.id')
->select('evidence_controls.*', DB::raw('shops.id as shop_id'))
->join('shops', 'evidence_controls.shop_id', '=', 'shops.id')
->allowedFilters('shop.name', 'employee.name')
->allowedSorts(['employees.name', 'shops.name'])
->get()
);
This is not clean code, but when create own class with implements Sort the code might look a lot better.
Thanks Guy's for help! Good luck! :-)

Laravel Eloquent: Relationships multiple have issue & Eloquent “select” method not working with using “with” method

I am try to made Eloquent: Relationships for three model. Please have a look on my code.
$account = Account::select(['id', 'is_sign_contract', 'restaurant_name', 'state', 'phone_no', 'email', 'one_time_pick_up', 'sign_contract_date', 'created_at', 'oil_on_hand', 'binsize'])
->with(['completedservice' => function($c) {
//$c->select('id');
}])
->with(['accountService' => function($q) {
$q->with(['serviceProvider' => function($qs) {
$qs->select('id', 'company_name');
}])->select('account_id', 'service_provider_id', 'service_id');
}])
->whereRaw($where)
->orderBy('id', 'ASC')->offset(54)->limit(1)->get();
if i remove that //$c->select('id'); select form above relation then i get data if i am using it display blank relationship block.
below image for response in last image whole function there
In short without select it works fine, but if I am using select then not working.
Laravel loads the relations after the first query is run. In order for it to attach the related model to the parent you need to select the foreign key on the related table so Laravel knows which model to attach the child to after the query is run.
The accountService works because ytou are selecting account_id on that model to attach it to Account and serviceProvider works because you are selecting id on serviceProvider as well as service_provider_id on accountService so after all queries are run Laravel knows which models get attached where.
Your query is not working because you are not selecting the account_id on the child model.
The following will work:
$account = Account::select(['id', 'is_sign_contract', 'restaurant_name', 'state', 'phone_no', 'email', 'one_time_pick_up', 'sign_contract_date', 'created_at', 'oil_on_hand', 'binsize'])
->with(['completedservice' => function($c) {
$c->select('id', 'account_id');
}])
->with(['accountService' => function($q) {
$q->with(['serviceProvider' => function($qs) {
$qs->select('id', 'company_name');
}])
->select('account_id', 'service_provider_id', 'service_id');
}])
->whereRaw($where)
->orderBy('id', 'ASC')->offset(54)->limit(1)->get();
You need to have the foreign key selected along with any other fields you wish to select. Without which you'll get an empty relationship. So it should be something similar to $c->select('id', 'account_id');

Get role name for admin user

I have table for admin user and its roles with their relations. I want admin user listing with their respective role.
I tried below query
$adminusers = Admin::whereHas('roles', function($q)
{
$q->where('roles.name', '<>', 'Superadmin');
$q->select('roles.name as roles');
})->select('id', 'name')->where('admins.status', 'A')->where('admins.is_delete', '0')->paginate(15);
but i am not able to retrieve role name from it.
So how can i get the role name from above query?
You can't select from a whereHas closure. whereHas in this scenario is used to limit the results of admins, not to retrieve the roles.
You can query a relationship of a specific model like so:
$singleAdmin->roles()->where('roles.name', '<>', 'Superadmin')->get();
Or you can put constraints during eager loading:
Admin:::with(['roles' => function ($query) {
$q->where('roles.name', '<>', 'Superadmin');
}])->get();
https://laravel.com/docs/5.4/eloquent-relationships#constraining-eager-loads
Once eager loaded, you would need to access the collection of roles from $singleAdmin->roles.
In some cases, it makes sense to just use a join.
You can use the leftJoin method.
`$admins = Admin::leftJoin('roles','admin.role_id','=','roles.id')
->select('id', 'name')
->where('admins.status', 'A')
->where('admins.is_delete', '0')
->paginate(15)`
Or you can do it in model file
`public function role()
{
return $this->hasOne(\App\Models\Roles::class, 'id', 'role_id');
}`

Laravel OrderBy Nested Collection

I'm using a Roles package (similar to entrust). I'm trying to sort my User::all() query on roles.id or roles.name
The following is all working
User::with('roles');
This returns a Collection, with a Roles relation that also is a collection.. Like this:
I'm trying to get all users, but ordered by their role ID.
I tried the following without success
maybe because 'roles' returns a collection? And not the first role?
return App\User::with(['roles' => function($query) {
$query->orderBy('roles.id', 'asc');
}])->get();
And this
return App\User::with('roles')->orderBy('roles.id','DESC')->get();
None of them are working. I'm stuck! Can someone point me in the right direction please?
You can take the help of joins like this:
App\User::join('roles', 'users.role_id', '=', 'roles.id')
->orderBy('roles.id', 'desc')
->get();
Hope this helps!
You can make accessor which contains role id or name that you want to sort by.
Assume that the accessor name is roleCode. Then App\User::all()->sortBy('roleCode') will work.
Here's the dirty trick using collections. There might be a better way to achieve this(using Paginator class, I guess). This solution is definitely a disaster for huge tables.
$roles = Role::with('users')->orderBy('id', 'DESC')->get();
$sortedByRoleId = collect();
$roles->each(function ($role) use($sorted) {
$sortedByRoleId->push($role->users);
});
$sortedByRoleId = $sortedByRoleId->flatten()->keyBy('id');
You can sort your relations by using the query builder:
notice the difference with your own example: I don't set roles.id but just id
$users = App\User::with(['roles' => function ($query) {
$query->orderBy('id', 'desc');
}])->get();
See the Official Laravel Docs on Constraining Eager Loading
f you want to order the result based on nested relation column, you must use a chain of joins:
$values = User::query()->leftJoin('model_has_roles', function ($join)
{
$join>on('model_has_roles.model_id', '=', 'users.id')
->where('model_has_roles.model_type', '=', 'app\Models\User');})
->leftJoin('roles', 'roles.id', '=', 'model_has_roles.role_id')
->orderBy('roles.id')->get();
please note that if you want to order by multiple columns you could add 'orderBy' clause as much as you want:
->orderBy('roles.name', 'DESC')->orderby('teams.roles', 'ASC') //... ext
check my answer here:
https://stackoverflow.com/a/61194625/10573560

Laravel 5.1 Where Condition In Many To Many relationships

Hello I'm very new in Laravel and, I'm having the following models :
organizations
-----------------
id
name
public function users()
{
return $this->belongsToMany( 'App\User' );
}
users
-----------------
id
name
organization_user
------------------
user_id
organization_id
The there is a many to many relationship between organization and user. Now I want to find the organization where the user belongs to. How can I add a where condition for the user in the relationship.
For example I want to find all the organization of the logged in user. I'm trying the following :
$organisations = Organisation::where('user_id' , '=' , $user->id)->paginate(10);
But its not working because user_id is in my Pivot Table. Please help and Thanks in advance.
I think you need to use wherePivot() function in your code like
$organisations = Organisation::with(array('user'=> function($query) use ($user){
$query->wherePivot('user_id' , '=' , $user->id);
}) )->paginate(10);
May be this can help
I think below code may help you
$organisations = Illuminate\Support\Facades\DB::table('organizations')
->join('organization_user', 'organizations.id', '=', 'organization_user.organization_id')
->join('users', 'users.id', '=', 'organization_user.user_id')
->where('users.id', '=', $user->id)
->paginate(10);
I think you need to add this to your User Model
public function organizations()
{
return $this->belongsToMany('App\Organization');
}
and then will be something simple like this
$organizations = Auth()->user()->organizations;
First of all add your relations in your models:
User.php
public function organizations()
{
return $this->hasMany(organization_user::class);
}
Or
public function organizations()
{
return $this->hasManyThrough(organizations::class,organization_user::class);
}
I recommend the second one. For more information follow this:
Laravel hasManyThrough
Please note that use same idea for organization model to create the relation

Categories