Laravel Eloquent HasManyThrough relationship - laravel

Trying to get locations through a user. Currently I'm getting an error, so either my hasManyThrough is setup incorrectly or my data structure is. It's still a new project so I don't mind restructuring the database to make the default hasManyThrough work properly.
$user = User::with('locations')->find(Auth::user()->id);
echo '<pre>';
die(print_r($user->locations,true));
Models:
User:
class User extends Authenticatable
{
protected $fillable = [
'name', 'email', 'password',
];
public function locations() {
return $this->hasManyThrough(
Location::class,
UserLocations::class,
);
}
}
UserLocations
class UserLocations extends Model
{
protected $fillable = [
'user_id',
'location_id',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function location()
{
return $this->belongsTo(Location::class);
}
}
Locations
class Location extends Model
{
protected $fillable =
[
'city',
'name',
'timezone',
'email',
'state',
'address',
'address1',
'zip_code',
];
public function user_locations()
{
return $this->hasMany(UserLocations::class);
}
}
Data Structure
Users:
-id
-name
-email
-password
UserLocations:
-id
-user_id
-location_id
Locations:
-id
-name
-city

You should not have used hasManyThrough for this since UserLocations already contains the location_id. In your user model, use hasManyRelationship to UserLocation.
public function locations()
{
return $this->hasMany(UserLocation::class, 'user_id');
}
And then to include the location information, just eager load it.
$user = User::with(['locations.location'])->where('id', Auth::user()->id)->first();

Related

Laravel complexe relationships

I need help please, to figure out for convenient ways to link between User/Staff/Parent/Student.
A Staff/Parent/Student is a user.
A Staff can be a Parent too. Similarly, a Parent may be a Staff too.
A student belongsToMany Parent, and a Parent belongsToMany Student.
Here are the models I've created :
App\Models\Student.php
protected $fillable = [
'name',
'email',
'student_user_id',
'created_at',
'updated_at',
'deleted_at',
];
public function student_user()
{
return $this->belongsTo(User::class, 'student_user_id');
}
public function guardians()
{
return $this->belongsToMany(StudentGuardian::class);
}
==========================================================
App\Models\StudentGuardian.php
protected $fillable = [
'name',
'email',
'guardian_user_id',
'is_staff',
'guardian_staff_id',
'created_at',
'updated_at',
'deleted_at',
];
public function students()
{
return $this->belongsToMany(Student::class);
}
public function guardian_user()
{
return $this->belongsTo(User::class, 'guardian_user_id');
}
public function guardian_staff()
{
return $this->belongsTo(Staff::class, 'guardian_staff_id');
}
=====================================
App\Models\Staff.php
protected $fillable = [
'name',
'email',
'staff_user_id',
'staff_guardian_id',
'is_student_guardian',
'created_at',
'updated_at',
'deleted_at',
];
public function staff_user()
{
return $this->belongsTo(User::class, 'staff_user_id');
}
public function staff_guardian()
{
return $this->belongsTo(StudentGuardian::class, 'staff_guardian_id');
}
In the StudentsController, I don't know how to call the students related to the authenticated user
you can use polymorphic relation to handle it.
https://laravel.com/docs/9.x/eloquent-relationships#polymorphic-relationships

nested relation with condition in laravel

I have 3 models
User - Role- Permission
User
class User extends Model
{
protected $fillable = [
'name', 'email', 'password',
];
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
Role
class Role extends Model
{
protected $fillable = ['name' , 'label'];
public function users()
{
return $this->belongsToMany(User::class);
}
public function permissions()
{
return $this->belongsToMany(Permission::class);
}
}
Permission
class Permission extends Model
{
protected $fillable = ['name' , 'label'];
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
I want get List of users whose permissions were updated on a specific date
I know I sould use something like below but I dont know exatly how to use Where
$users = User::with('roles.permissions')->orderBy('name', 'asc')->paginate(25);
thanks alot
Use whereHas():
$users = User::whereHas('roles.permissions', function($query) use($date) {
$query->whereDate('permission_role.updated_at', $date);
})->orderBy('name', 'asc')->paginate(25);

How to get value from child table using eloquent in Laravel?

I have two table : users and profile.
A user may have one or multiple profile. I want to access the combined data of both table: 'ID' in user table is foreign key in profile table
User model :
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'first_name','last_name', 'email', 'password','phone','user_type',
];
protected $hidden = [
'password', 'remember_token',
];
public function profile()
{
return $this->hasMany(profile::class);
}
}
Profile model is :
class profile extends Model
{
protected $fillable = [
'id','relationship_status','dob','height',
'weight','primary_language'
];
protected $primaryKey = 'profile_id';
public function User()
{
return $this->belongsTo(User::class,'id','id');
}
}
Change your user model profile relationship like this
User Model
public function profile()
{
return $this->hasOne(Profile::class); //assuming your user has single profile
}
Profile model
class Profile extends Model
{
protected $fillable = [
'id', 'user_id', 'relationship_status','dob','height',
'weight','primary_language'
];
//add user_id field in profiles table
//protected $primaryKey = 'profile_id'; //no need of this, because you have id field in profiles table
public function user()
{
return $this->belongsTo(User::class);
}
}
after that you can fetch data like this
$user = User::find(2);
dd($user);
dd($user->profile)
When fetching multiple users details, then use eager loading
$users = User::with('profile')->get();
foreach($users as $user){
dd($user->profile)
}
Check details https://laravel.com/docs/5.6/eloquent-relationships#one-to-one

laravel eloquent doesn't use protected table name

In my model i added protected $table, but when i'm going to use it laravel does't use it. This is my role models:
class Role extends Model
{
protected $table = 'role';
protected $primaryKey = 'ROLE_ID';
protected $casts = [
'ACTIVE' => 'boolean',
];
protected $fillable = [
'ROLE', 'ACTIVE', 'TYPE'
];
public $timestamps = false;
public function groups()
{
return $this->belongsToMany(Group::class, GroupRole::class, 'ROLE_ID', 'GROUP_ID');
}
}
And this is Group model:
class Group extends Model
{
protected $table = 'groups';
protected $primaryKey = 'GROUP_ID';
protected $fillable = [
'GROUP_ID', 'GROUP_NAME', 'PARENT_GROUP', 'ACTIVE'
];
protected $casts = [
'ACTIVE' => 'boolean',
];
public $timestamps = false;
public function type()
{
return $this->belongsTo(GroupType::class, 'TYPE', 'TYPE_ID');
}
public function roles()
{
return $this->belongsToMany(Role::class, GroupRole::class, 'GROUP_ID', 'ROLE_ID');
}
}
And this is group_role table model. It handles many to many relation between role and group:
class GroupRole extends Model
{
protected $table = 'group_role';
protected $primaryKey = 'GROUP_ROLE_ID';
protected $fillable = [
'COMMENT', 'ROLE_ID', 'GROUP_ID'
];
public $timestamps = false;
}
Problem begin when i want to use this models. For example:
$role = App\Role::first();
$groups = $role->groups;
Laravel returns this error messages:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'favian_mydb.App\GroupRole' doesn't exist (SQL: select groups.*, App\GroupRole.ROLE_ID as pivot_ROLE_ID, App\GroupRole.GROUP_ID as pivot_GROUP_ID from groups inner join App\GroupRole on groups.GROUP_ID = App\GroupRole.GROUP_ID where App\GroupRole.ROLE_ID = 1)
I tried to replace App\GroupRole with group_role and executing in mysql. It works fine. Am i missing something?
The Problem is in your roles relation:
public function roles()
{
return $this->belongsToMany(Role::class, GroupRole::class,'GROUP_ID','ROLE_ID');
}
The belongsToMany expects the intermediate table name as second argument, not the class name.
So you have to define it like this:
public function roles()
{
return $this->belongsToMany(Role::class, 'group_role','GROUP_ID','ROLE_ID');
}
I think the problem is in you relation functions. Try to use strings instead of Model::class.
Example:
return $this->return $this->belongsTo('App\GroupType', 'TYPE', 'TYPE_ID');
Hope this works.

Eloquent Model has parent model

I have a Model called User with stuff like name, country and some relationships.
Now I want a Model, e.g. Vendor, having all the same functions and variables as a User including some More stuff
I thought I could to it this was:
class User extends Model implements AuthenticatableContract
{
use Authenticatable; SoftDeletes;
protected $dates = ['deleted_at', 'last_login'];
protected $fillable = [
'name',
'password',
'country',
];
protected $hidden = ['password'];
public function logs()
{
return $this->hasMany('App\Log');
}
}
And the Vendor Model:
class Vendor extends User
{
protected $fillable = [
'description'
];
public function user() {
return $this->belongsTo('App\User');
}
public function products()
{
return $this->hasMany('App\Product', 'vendor_id');
}
The Controller checks the role of the user and loads a user model or a vendor model:
if(Auth::user()->role > 1)
$user = Vendor::where('user_id', Auth::user()->id)->first();
else
$user = Auth::user();
return $user->load('logs');
But the load call fails for a vendor. I was able to join the fields of a user inside a vendor but I also need the functions of it.
The problem was that the logs function checks a field that doesn't exists.
Using this functions works:
public function logs()
{
return $this->hasMany('App\Log', 'user_id', get_called_class() !== get_class() ? 'user_id' : 'id');
}

Resources