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
Related
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.
I'm trying to select a 'Site' from a Users 'Organisation'.
I can successfuly retrieve a User's Organisation (as an Organisation object) by using
$user->organisation
but when I try to retrieve the sites belonging to the organisation using:
$user->organisation->sites
I get every site in my DB returned (as a collection).
My User Model's organisation relationship:
public function organisation()
{
return $this->belongsTo('App\Models\Organisation', 'organisation_id');
}
My Organisation Model's User and Site relationships:
public function users()
{
return $this->hasMany('App\Models\User');
}
public function sites()
{
return $this->hasMany('App\Models\Site');
}
My Site Model's Organisation relationship:
public function organisation()
{
return $this->belongsTo('App\Models\Organisation');
}
User Table
id
organisation_id
name
email
password
last_login
persist_code
reset_password_code
remember_token
created_at
updated_at
deleted_at
responsible_to
Organisations
id
name
created_at
updated_at
deleted_at
Sites
id
organisation_id
name
address
account_code
created_at
updated_at
deleted_at
I've included everything I think will be useful here but I've missed anything I will add it as requested.
I have the following workaround in place but I am still unhappy with why the above is not working as expected.
$organisation = Organisation::where('id', $user->organisation->id)->first();
$site = Site::where('organisation_id', $organisation->id)->first();
The above workaround returns the first site from my table that does genuinely have a relationship with my user model.
If I remove ->first() I get a collection of sites that are associated with my user through the organisation rather than all from the table.
Thanks
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.
The relevant portion of my application is set up as follows:
A Users table, with unique user IDs
A Teams table, with unique team IDs
A Team_Membership table, with
a unique ID and a column for a User ID and a Team ID, to denote
that a user belongs to a team.
A user can be on an unlimited number of teams.
I have a function to retrieve an array of the teams a given user belongs to. It would generally be called in the scope of the current logged in user to get their active teams, but will also be used in administrative functions to return the teams of a given user ID.
My first thought was to make the function callable from the user model, so for a given user object, I could do as follows
$teams = $user->get_teams();
or
$teams = User::get_teams($user_id);
But I'm not sure if this is generally considered best practice in Laravel for this type of functionality. Where should this function be located?
Actually, you are talking about something that laravel already does for you if you are using Eloquent.
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'users';
public function teams()
{
return $this->belongsToMany(Team::class);
}
}
class Team extends Model
{
protected $table = 'teams';
public function users()
{
return $this->belongsToMany(User::class);
}
}
In addition to the users and teams table you would make a pivot table:
team_user
id - integer
team_id - integer
user_id - integer
and laravel does the rest.
$userId = 1;
$user = User::with('teams')->find($userId);
$teams = $user->teams;
I am trying to build a messaging system for a job site using Laravel 5 and using the Eloquent ORM. The basic premise is that someone posts up a job, and people can respond to that job via a message. The MySQL database is structured as so:
**users table**
id
username
password
**jobs table**
id
user_id (FK with id on Users table)
slug
title
description
**conversations table**
id
job_id (FK with id on Jobs table)
**messages table**
id
conversation_id (FK with conversations table)
user_id (FK with id on users table)
message
last_read
**conversation_user table**
conversation_id (FK with id on Conversation table)
user_id (FK with id on Users table)
When a user finds a job they like, they can send a message to the job creator which will in turn create a new conversation. The newly created conversation id is then used passed to the messages table (alongside the message text itself) and then the conversation_user pivot table is updated with the conversation id as well as the two users who are participating in the conversation (i.e. the person who posted the job and the person sending the message)
I have a model for each table and a summary of the relationships are:
**Job.php**
HasMany - Conversation model
BelongsTo - User model
**Conversation.php**
BelongsTo - Job model
HasMany - Message model
BelongsToMany - User model
**Message.php**
BelongsTo - Conversation model
BelongsTo - User model
**User.php**
HasMany - Job model
HasMany - Message model
BelongsToMany - Conversation model
I have setup a query scope in Conversation.php (my Eloquent model for the Conversations table) which accomplishes the task of displaying the conversations that the authenticated user is participating in:
public function scopeParticipatingIn($query, $id)
{
return $query->join('conversation_user', 'conversations.id', '=', 'conversation_user.conversation_id')
->where('conversation_user.user_id', $id)
->where('conversation_user.deleted_at', null)
->select('conversations.*')
->latest('updated_at');
}
and via my Conversations Repository, I pass on the results of the query scope to my view in my MessagesController like so:
public function __construct(ConversationInterface $conversation)
{
$this->middleware('auth');
$this->conversation = $conversation;
}
public function index()
{
$currentUser = Auth::id();
$usersConversations = $this->conversation->ParticipatingIn($currentUser, 10);
return view('messages.index')->with([
'usersConversations' => $usersConversations
]);
}
and for reference the ConversationInterface is bounded to my ConversationsRepo:
public $conversation;
private $message;
function __construct(Model $conversation, MessageInterface $message)
{
$this->conversation = $conversation;
$this->message = $message;
}
public function participatingIn($id, $paginate)
{
return $this->conversation->ParticipatingIn($id)->paginate($paginate);
}
My question is, given I have what I believe are the right relationships, how I can pass the title of the specific job from the job_id on the conversations table and also the first few words of the last message that was sent within the conversation?
I'm sorry if I'm stating the obvious, but:
Conversation model belongs to Job Model. As you already has the conversation object/id, just do this:
//Controller
$conversation = App\Conversation::find($id);
return view('your view', compact('conversation'));
//View
$conversation->job->title; //the conversation belongs to a job, so requesting the job will return an instance of the job model, which can be asked for the title.
You can also use this on the view to get the first chars from the message:
substr($conversation->messages->last()->message,0,desired lenght);