I have the following database:
teams
-----
id
user_id
users
-----
id
pages
-----
id
user_id
team_id -> (nullable)
So a User can create a Team, and create a Page
Currently, I have the following relationships setup (replace with $this)
teams_owned() -> $user->hasMany(Team::class); // Teams a user owns
pages() -> $user->hasMany(Page::class); // Page a user created
user() -> $team->belongsTo(User::class); // User who created team
user() -> $page->belongsTo(User::class); // User who created the Page
However, a User can join a team by creating a Page for that team. In this case the pages table will fill in the team_id. Where a page is created and is not for a team, the team_id value will be null
I wanted to add a relationship for User to get the Teams joined. As explained above, you are part of Team if you have created a Page for it.
I have tried the following:
public function teams_joined()
{
return $this->hasManyThrough(Team::class, FundraisingPage::class);
}
I'm not sure if I should be using a HasManyThrough in this situation
As a backup I have the following:
public function teams_joined()
{
$uniqueTeamIds = $this->pages()->onlyForTeams()->get()->pluck('id')->unique();
return Team::whereIn('id', $uniqueTeamIds)->get();
}
where onlyForTeams() is defined on Page as
public function scopeOnlyForTeams($query) {
return $query->whereNotNull('team_id');
}
But I wanted to use a proper relationship so was wondering if I should be using HasManyThrough or something else for this situation.
Use a BelongsToMany relationship:
public function teams_joined()
{
return $this->belongsToMany(Team::class, 'pages');
}
Related
I have a website build in Laravel.
I have two tables - Groups and Group members.
For each group_member, the row in the table has id, group_id and user_id.
The groups have a name and a description.
When a user joins a group, a row is created in the group_member table.
But I now need to get the groups that a user is part of.
So if I have user_id = 5, I need to get all the rows in group_member where user_id = 5, and then get the corresponding group, so I can query the groups.
I need to do something like $groups = Groups::whereGroup_member ...
But I cant query the model like that, because in Groups there is no where it specificies who the members are, it is just the group details - the members are specificed in group_member table.
How do I get the groups, which a member is part of using the laravel query standards?
In your User.php Model
public function group_member(){
return $this->hasMany(GroupMember::class,'user_id','id;);
}
In your GroupMember.php Model
public function group(){
return $this->belongsTo(Group::class,'group_id','id');
}
Your query will be
$users = User::with('group_member.group')->find($user_id);
You should use Many-to-Many relation:
class Group
...
public function members() {
return $this->belongsToMany(User::class); // Users (members) that belongs to Group
}
class User
...
public function groups() {
return $this->belongsToMany(Group::class, 'group_member', 'user_id', 'group_id'); // Groups that User belongs to
}
And at controller, when You have user id:
$groups = User::where('id', $user_id)->groups;
More about this written at official docs: https://laravel.com/docs/5.4/eloquent-relationships#many-to-many
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
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;
The Issue
I want to get all users who are not managers of a company.
The Relationships
I have a User model, that can have one CompanyGroup. The CompanyGroup can have many Managers. Managers can manage different types of entity, not just CompanyGroups, so this is a polymorphic relationship (however, not directly relevant to my question).
User Model
public function group()
{
return $this->belongsTo('App\CompanyGroup', 'company_group_id');
}
Company Group
public function managers()
{
// This is polymorphic, as a manager can manage different types of entity.
return $this->morphMany('App\Manager', 'managable');
}
Manager
public function user()
{
return $this->belongsTo('App\User', 'user_uuid', 'uuid');
}
What i've tried:
// Get all users, with a relationship of 'group', and the group's 'managers'
$users = $this->user->whereHas('group.managers', function($query)use($group)
{
// Exclude any users where the user's UUID is present in the managers table
$query->where('exp_members.uuid', '!=', 'managers.user_uuid');
})->get();
What this produced
Nothing! It didn't list any users at all. The managers table is currently empty, so it should return all users that have the $group->id assigned to them. If i enter a random record in the managers table, it returns all of the users that have the group id assigned to them, but it doesn't filter out those who are managers.
I was trying to get the attendance of each user in a course where the users and the courses have many to many relationship and the attendance table is based on the relationship.
But i couldn't call $user->pivot->attendance(); directly i had to call for the pivot object it self so i can call a function to it as you can see in the answer
The Following is a sample of my Database scheme
I need to run
$users=$course->users;
foreach($users as $user)
{
$user->pivot->attendance(); //error in this line
}
this line gives and error
Call to undefined method
Illuminate\Database\Query\Builder::attendance()
users
id
name
etc
courses
id
name
startDate
endDate
course_user
id
course_id
user_id
payment
regDate
status
userattendance
id
course_user_id
time
inOrOut
And here is the CourseUserPivot Class
class CourseUserPivot extends Eloquent {
protected $table ="course_user";
public function course()
{
return $this->belongsTo('Course');
}
public function user()
{
return $this->belongsTo('User');
}
public function attendance()
{
return $this->hasMany('Userattendance','course_user_id');
}
}
P.S: $user->pivot->payment works and displays the attribute but i cant call methods
You can't use $user->pivot->attendance(); as this calls attendance on the user object not on the pivot object
You will have to fetch the pivot object then call the function like so
CourseUserPivot::find($user->pivot->id)->attendance();
make user that where you used withPivot() function you include the id in the array
like in
class Course{
...
...
public function users()
{
return $this->belongsToMany('Candidate')
->withPivot('id',
'summary',
'status',
'payment'
);
}
}
I was trying to accomplish the same thing, and I was having trouble getting it to work like I wanted until I included the 'id' column of my custom pivot model in the withPivot() method.
For some context, my database structure is:
User table
id
Items Table
id
Sets table (defines a set and the items that can be in an instance of it)
id
Set_User table (Custom Pivot Model, instances of a set created by a user)
id, set_id, user_id
Items_SetUser table (items that belong to a set instance that belong to a user)
item_id, setuser_id
I do this in the controller to get all the sets that user has made an instance of, with custom pivot table data:
$user_sets = \Auth::user()->sets()->withPivot('id', 'name')->get();
And then in blade I can access the items associated with each set instance like this:
$set->pivot->set_items()->count()
Without including 'id' in the call to withPivot(), the above is not possible. Note that set_items() is a method on the custom pivot model that defines a relationship with the items table.