Getting data from laravel relation on Foreign Key - php

I have to SQL tables: users and roles; The user table consists of an id (PRIMARY), email, password and a role_id (INDEX) column. The role table consists of an id (PRIMARY) and a name column. A user can only have a single role (Admin or User).
This is how my laravel Models look like:
// User Model
public function role()
{
return $this->hasOne(Role::class);
}
// Role model
public function user()
{
return $this->belongsTo(User::class);
}
What i want is, when i get the information of a user, i want to get the corresponding role of that user.
When i place this code in the Artisan Tinker:
// Get user with id=2
App\User::find(2)->role;
This seems logical to me "Find the role belonging to the user with id 2"
But it is throwing this error:
Illuminate\Database\QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'roles.user_id' in 'where clause' (SQL: select * from `roles` where `roles`.`user_id` = 2 and `roles`.`user_id` is not null limit 1)'
How Can i get the role of a User without calling it from the Role model?

Since you have a role_id on users table, you should have belongsTo(Role::class) on User model:
// User Model
public function role()
{
return $this->belongsTo(Role::class);
}
And hasMany(User::class) on role model:
// Role model
public function users()
{
return $this->hasMany(User::class);
}

I believe there should be belongsToMany instead of belongsTo. This should fix the problem. Documentation: https://laravel.com/docs/5.6/eloquent-relationships

Unknown column 'roles.user_id'
This is the error. Your roles table should have user_id column.

Related

How can I get this many-to-many relationship work in Laravel 5.5?

I am getting an error with a many to many relationship in eloquent in Laravel 5.5
Illuminate \ Database \ QueryException (42000)
SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'users' (SQL: select users.*, users.roles_id as pivot_roles_id, users.users_id as pivot_users_id, users.id as pivot_id, users.created as pivot_created, users.updated as pivot_updated, users.deleted as pivot_deleted from users inner join users on users.id = users.users_id where users.roles_id = 2)
I have a users table, roles table and a user_role table (pivot table). The user_role table has the following columns: id, users_id(fk from users table),roles_id (fk from roles table),created,updated,deleted.
In the User model I have
public function roles(){
return $this->belongsToMany(\App\roles::class,'roles','users_id','roles_id','id','id')->withPivot(['id','created','updated','deleted']);
}
In the roles model I have
public function users(){
return $this->belongsToMany(\App\User::class,'users','roles_id','users_id','id','id')->withPivot(['id','created','updated','deleted']);
}
In my controller I have
$roles = $this->rolesObject->whereNull('deleted')->orderBy('role')->get();
//Just for testing how to view the relationship won't be real code in the end
foreach($roles as $role){
foreach($role->users as $user){
dump($user->display_name);
}
}
Looking through the documentation and it looks like i am setting up the relationship correctly but obviously I'm not and I have no idea what I am doing wrong
The second parameter to belongsToMany method is a relation table name(docs), you have to pass role_user rather than users.
public function roles(){
return $this->belongsToMany(\App\roles::class,'role_user','users_id','roles_id','id','id')->withPivot(['id','created','updated','deleted']);
}
...
public function users(){
return $this->belongsToMany(\App\User::class,'role_user','roles_id','users_id','id','id')->withPivot(['id','created','updated','deleted']);
}
Your code thinks that your second parameter users is a relation table name, that's the reason of the error.

Query table from model or controller in Laravel

I have table role_user which has two columns user_id and role_id. user_id is the user id from users table and role_id is the id from roles table.
I want to query role_user and show the role name next to each user. Example
table users
user_id username ...
1 Test user
table roles
role_id role_name
1 Admin
table role_user
user_id role_id
1 1
I want to show on page
Test user - Admin
I have added this in my Users model
public function role()
{
return $this->hasOne('App\Role', 'user_id', 'role_id');
}
and this in the controller
public function users()
{
$userRole = User::find(1)->role;
return View::make('users', [
'userRole' => $userRole
]);
}
Currently I've got this which is obvious why:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'roles.user_id' in 'where clause' (SQL: select * from roles where roles.user_id is null and roles.user_id is not null limit 1)
The question is how to query role_user table from controller or from model and while displaying the users to display role name too.
You have defined your table so one user can have many roles (using a pivot which is your role_user table.
If a user can only have one role you can remove the role_user table and add a column role_id to your users table.
Using your current implementation change role relationship in user model to following.
public function roles()
{
return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
}
In your controller
public function users()
{
$users= User::with('roles')->get();
return View::make('users', [
'users' => $users
]);
}
To simply show the names of roles use implode method of returned collection
#foreach ($users as $user)
{{ $user->roles->implode('name', ',') }}
#endforeach
You are using a pivot table to maintain the relationship so you need to
belongsToManyrelation and defining a custom accessor for it, like so:
//User model file
public function roles()
{
return $this->belongsToMany(App\Role::class);
}
public function getRoleAttribute()
{
return $this->roles()->first();
}

Eager Loading is not working laravel 5.3

I have three related models.
1.User model
public function users_wishlst(){
return $this->hasMany('App\Users_wishlst');
}
2.Product Model
public function users_wishlst(){
return $this->belongsTo('App\Users_wishlst');
}
3.Users_wishlst model
public function user(){
return $this->belongsTo('App\User');
}
public function product(){
return $this->hasMany('App\Product');
}
in users_wishlsts table i have the followibg columns
id
user_id
product_id
I want to get the product info of an users wishlist. I have tried this
public function showWishList(){
$id= Auth::id();
$WishList = wishlist::with('product')->where(['user_id'=>$id])->get();
return json_encode($WishList);
}
But this gives me the following error
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'products.users_wishlst_id' in 'where clause' (SQL: select * from
products where products.users_wishlst_id in (1, 2, 3))
what is the problem
Without knowing all about your database structure this seems like a problem with your foreign keys. Eloquent tries to automatically guess the key. Based on the error it seems like your products table doesn't contain a users_wishlst_id column (maybe you named it different?). Try looking at you Database and give Laravel the correct foreign_key.
https://laravel.com/docs/5.3/eloquent-relationships#one-to-many

Laravel 5.3 hasManyThrough through an intermediate table

I have the following table relationship:
organizations
id - integer
organization_users
organization_id - integer (FK)
user_id - integer (FK)
users
id - integer
I am trying to get all the users of an organization through eloquent relationships. Here is my Organization.php model with its relationships:
class Organization extends Model
{
public function Users(){
return $this->hasManyThrough('App\User', 'App\OrganizationUser',
'organization_id', 'user_id', 'id');
...
}
I have tried many combinations of that relationship such as
return $this->hasManyThrough('App\User', 'App\OrganizationUser',
'user_id', 'organization_id', 'id');
But all turn up somewhat the same error (this one is from the first query):
Illuminate\Database\QueryException with message 'SQLSTATE[42S22]: Column not
found: 1054 Unknown column 'organization_users.id' in 'on clause' (SQL: select
`users`.*, `organization_users`.`organization_id` from `users` inner join
`organization_users` on `organization_users`.`id` = `users`.`user_id` where
`organization_users`.`organization_id` = 1)'
Is it possible that I can have the relationship retrieve the user_id to query on the users table instead of Laravel trying to retrieve organization_users.id? If not is there another way around this?
This is many to many relationship.
User Model:
public function organizations()
{
return $this->belongsToMany('App\Organization','organization_users');
}
Organization Model:
public function users()
{
return $this->belongsToMany('App\User','organization_users');
}
To, get all the users with their organizations:
$users=User::with('organizations')->get();
foreach($users as $user)
{
print_r($user->name);
foreach($user->organizations as $organization)
{
print_r($organization->name);
}
}
What you are describing looks like it may be a 'Many-to-Many' relationship.
https://laravel.com/docs/5.3/eloquent-relationships#many-to-many

Retrieve distant relation through has-many-through for many-to-many relation in Laravel

I have the following models in my application
User
Group
Task
which have the following relationships
User and Group have a many-to-many relationship
Task and Group have a many-to-many relationship
So basically a user can belong to more than one group and each group can have more than one task.
Following is the table structure.
users
id
name
groups
id
name
tasks
id
name
group_user
id
group_id (foreign key with groups table)
user_id (foreign key with users table)
group_tasks
id
group_id (foreign key with groups table)
task_id (foreign key with tasks table)
Now I want to retrieve all the tasks for the user.
I tried the following approaches and both didn't work.
Approach 1
$user->groups() gives the list of groups for a user
$group->tasks() gives the list of tasks for a group
So I tried
$user->groups()->tasks() but it didn't work.
Approach 2
I tried Has Many Through by adding this to my User model
public function tasks()
{
return $this->hasManyThrough(Task::class, Group::class);
}
but even that didn't work. The following is the error that I am getting
QueryException in Connection.php line 713:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'groups.user_id' in 'field list' (SQL: select `tasks`.*, `groups`.`user_id` from `tasks` inner join `groups` on `groups`.`id` = `tasks`.`group_id` where `groups`.`user_id` = 1)
My guess is that this is happening because it is expecting one-to-many relationship, but I have a many-to-many relationship.
So is there a way to retrieve it without getting all groups and then looping through them?
User Model
public function groups()
{
return $this->belongsToMany('App\Group');
}
Group Model
public function tasks()
{
return $this->belongsToMany('App\Task');
}
Task Model
public function groups()
{
return $this->belongsToMany('App\Group');
}
Retrieving all tasks for a user.
$user = User::find(1);
$user->load('groups.tasks');
$tasks = $user->groups->pluck('tasks')->collapse();
You can also take a look at the extension of the HasManyThrough here: https://github.com/staudenmeir/eloquent-has-many-deep
It helps you to retrieve many sub-levels of your relationships.
In your case, it would be
User -> belongsToMany(Groups) -> blongsToMany (Tasks)
just add your method to the user model like:
public function tasks()
{
return $this->hasManyDeep(
'App\Task',['App\Group']
);
}

Categories