Laravel relationship with one-to-one - php

I have the following users table structure:
id
email
....
status // foreign key from tbl_status
Now in my tbl_status:
id
name
description
Now I would like to create a relationship such that if I have a status of 1 in the users table I would like to get its name. I have tried:
In my User model:
class User extends Model
{
protected $fillable = [
'name', 'email', 'password', 'status'
];
public function userstatus()
{
return $this->hasOne('App\Status', 'id', 'status');
}
}
In the Status model:
class Status extends Model
{
protected $fillable = [
'name', 'description'
];
}
When fetching records via...
return User::with("userstatus")->paginate(10);
...it always returns the status as null even though each user has a default status of 1 and the status table has an ID of 1 with a value.

This relationship is backwards. Placing the status foreign key on the users table creates the following relationships:
User belongs to Status
Status has many Users
However, the question shows a hasOne() relation on the User model for userstatuses(). For this to work, tbl_status will need a user_id field, but this means that a Status can only belong to one User.
Instead, the correct relation for userstatus() on User should be belongsTo():
public function userstatus()
{
return $this->belongsTo(App\Status::class, 'status');
}
Then we can use the proper relations on the User model:
$user = User::with('userstatus')->find(1);
$user->status; // 1 (foreign key ID)
$user->userstatus->name; // "status name"
$user->userstatus->description // "This is the status description."

I think the best way to do it will be to add a user_id column that references the users id column as the foreign key instead of status. That should fix it.

Related

Laravel relationship on a second level pivot table

I have the following tables:
Cards:
id (PK)
label
company_user_id (FK, Unique) (Foreign key on column Companies_Users.id )
Companies_Users:
id (PK)
company_id
user_uuid
Users:
uuid (PK)
name
Companies:
id (PK)
name
Every user can have one card per company. If a user is in multiple companies, he can have multiple cards.
Every card can be owned by one and only one user.
I need to set the relationship on the Card model that would get me the User owning the card.
What I did is:
class Card extends Model
{
use HasFactory;
protected $table = 'cards';
public $primaryKey = 'id';
public $incrementing = true;
public function user(){
return $this->hasOneThrough(User::class, CompanyUser::class, "user_uuid", "uuid", "company_user_id", "user_uuid");
}
}
But $card->user is always returning null.
How can I make it so I can fetch the user of a card without doing $card->companyUser->user. I need it to work directly using $card->user.
Thank you

Laravel hasManyThrough 2 tables

i have two tables as below:
users table:
|id|name|email|password|created_at|updated_at
messages table:
|id|sender_id|receiver_id|message|created_at|updated_at
User model:
public function threads()
{
return $this->hasManyThrough(Message::class, User::class,'id','sender_id');
}
i'm trying retrieve message threads
which isn't working. any help appreciated.
This is an example from laravel eloquent relationship
class Country extends Model
{
public function posts()
{
return $this->hasManyThrough(
'App\Post',
'App\User',
'country_id', // Foreign key on users table...
'user_id', // Foreign key on posts table...
'id', // Local key on countries table...
'id' // Local key on users table...
);
}
}
can you review your code
It seems that you want to retrieve all messages that belongs to a single thread (list of users) using hasMany relationship Through User model, to do that You have to define hasManyThrough inside Thread model not in User model, here is an example:
User:
|id|name|email|password|created_at|updated_at|thread_id
Note thread_id foreign key because thread is a list of users
Thread:
class Thread extends Model {
public function messages() {
return $this->hasManyThrough(Message::class, User::class,'thread_id','sender_id', 'id', 'id');
}
}
Example from laravel doc

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']
);
}

Laravel foreign key relation

I've got a strange problem.
I've a users table and a company table. A User belongsTo a company and a company hasMany users.
Both primary keys of the table are id.
In the laravel documentation I read the following:
Additionally, Eloquent assumes that the foreign key should have a
value matching the id column of the parent.
I've got this in my CompanyModel:
protected $table = 'company';
public function users()
{
return $this->hasMany(UserModel::class);
}
When I try this:
$users = CompanyModel::find(1)->users;
dd($users);
It's not working. When I add a foreign key in my relation it works!?:
protected $table = 'company';
public function users()
{
return $this->hasMany(UserModel::class, 'id');
}
This is strange right? What on earth am I doing wrong.
--EDIT--
In my users table I've got a company_id column!
Firstly, I would suggest you rename your Model from CompanyModelto Company and from UserModel to User.
Then ensure you have company_id in your users table. And in your users migration file connect the users table with the companies table as such:
$table->integer('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
Don't forget to refresh your database.
Then in your models, define the relationships as such:
// User model
// Laravel will automatically identify and use the `company_id` field in your reference
public function company(){
return $this->belongsTo(Company::class);
}
// Company model
public function users(){
return $this->hasMany(User::class);
}
You can then fetch your records in your controller as such:
$user = User::find(1);
$user_company = $user->company; // This might not be necessary in your controller, you can do it in your view
dd($users, $user_company);

How build a ternary relationship in Laravel 5

I have three entities:
User
Profile
Status
Summarized, users has a profile foreach status.
EXAMPLE
Users table records
user
id | name
1 user1
2 user2
3 user3
Status table records (this records is previously seeded)
status
id (PK) | title (string)
1 student
2 collaborator
3 teacher
Profile table structure
PROFILE
user_status_id (PK) (FK)
institution (string)
year (timestamp)
user1 is registered as student and fill your profile based on this status. After, he change your status to collaborator and fill another profile referred to this new status.
With that, i want to know:
When user1 was student?
the user1 was already collaborator ever?
Which institution user1 had frequented when he was student?
My first problem is:
How to model this relationship?
I'm not sure but think the above situation is a ternary relatinoship case, right?
And Second problem:
How build using Laravel Eloquent Relationships?
Let's start with relationship
class User extends Eloquent{
protected $table = 'user';
public $timestamps = true;
use SoftDeletingTrait;
public function status(){
return $this->hasOne(Status::class, 'user_id', 'id');
}
public function profile(){
return $this->hasMany(Profile::class,'user_id','id');
}
}
class Status extends Eloquent{
protected $table = 'status';
public $timestamps = true;
use SoftDeletingTrait;
public function user(){
return $this->belongsTo(User::class,'user_id','id');
}
}
class Profile extends Eloquent{
protected $table = 'profile';
public $timestamps = true;
use SoftDeletingTrait;
public function user(){
return $this->belongsTo(User::class,'user_id','id');
}
}
Above relation would somehow will get you what you need but just writing this relation made me question your table structure.
Suggestion DB Change For Better Relation
User
id, username, email, ........
Status
id, status, description, ........
Institutions
id, name, address, ............
User_Status_Institution
user_id,status_id,institution_id,timestamp,.......
This structure allows us that we can have Institution details even if there is no user_profile for that institution. Previous structure you had you can only have institution (name only) detail if and only if there is user profile. Also you can change institution (Name/address/phone etc) at one place and it will update it for all users.
As much as possible try that you can make information to be independent if possible because that reflects in models, object and relations.
Hope it makes sense.

Categories