I have the following tables :
users
id|name|username
Areas
id|name
user_area
id|user_id|area_id
Buildings
id|name|area_id
In User models i want to call query that every users have his assigned areas and his assigned areas has many buildings, so i created a method in User model that query the user assigned buildings.
In App\User Model:
public function areas()
{
return $this->belongsToMany('App\Area','area_user');
}
public function UserBuildings(){
return $this>hasManyThrough('App\Building','App\Area','user_id','area_id');
}
In App\Area Model:
public function users(){
return $this->belongsToMany('App\User','area_user','area_id','user_id');
}
public function buildings(){
return $this->hasMany('App\Building');
}
In App\Building Model:
public function areas(){
$this->belongsTo('App\Area');
}
How can i structure a relationship method in User Model that get the user assigned buildings.
Thanks
You can't use hasManyThrough here, but you can use nested whereHas() to get all buildings assigned to authenticated user:
Building::whereHas('area', function ($q) {
$q->whereHas('users', function ($q) {
$q->where('id', auth()->id());
});
})->get();
Also, you should rename areas relationship to area in Building model, since each building belongs to only one area.
Related
I need advice about my model relationships,
Logic
Group has many users
Group has many admins
User has many groups (as user)
User has many groups (as admin)
Database Structure
Group Table
User Table
Group_Users table (save id of user and id of group)
Group_Admins table (save id of user and id of group)
Relationship Code
User model
public function groupsUser() {
return $this->hasMany(GroupUser::class);
}
public function groupsAdmin() {
return $this->hasMany(GroupAdmin::class);
}
Group model
public function users() {
return $this->hasMany(GroupUser::class);
}
public function admins() {
return $this->hasMany(GroupAdmin::class);
}
GroupUser model
public function group() {
return $this->belongsTo(Group::class);
}
public function user() {
return $this->belongsTo(User::class);
}
GroupAdmin model
public function group() {
return $this->belongsTo(Group::class);
}
public function user() {
return $this->belongsTo(User::class);
}
Help wanted
Basically as the relationships between users and groups is many to many normally I shouldn't need models of GroupUser and GroupAdmin and then just using sync() function in order to add/remove users and group id's from those tables.
What is my concerns then?
Normally I use that type of connection when I want input bulk ids into database (let say adding tags to posts, suddenly relate 10 tags id to 1 post) that moment using sync() and removing GroupUser and GroupAdmin models makes sense but in my case as users joins/adds to groups one by one, what do you suggest for this relationships?
Is my current approach makes sense?
Is is better if I remove those GroupUser and GroupAdmin models and add them to user, group model like:
public function users()
{
return $this->hasMany(User::class, 'group_users', 'user_id', 'id');
}
and such so?
What do you think is the best practice?
users and groups is many to many
your tables like this?
users, user_group , groups ?
How about use 'belongsToMany' relation?
Laravel many to many relation
// User model
public function groups() {
return $this->belognsToMany(Group::class);
}
// Group model
public function users() {
return $this->belognsToMany(User::class);
}
And use like.
User::find(1)->groups; // return user 1 groups
User::find(1)->groups()->sync($groupIds); // relate user and groups
Group::find(1)->users; // return group 1 users
If you have role column in your users table, you cold add relation like.
// Group model
public function users() {
return $this->belognsToMany(User::class)->where('role', 'the role of normal user');
}
public function admins() {
return $this->belognsToMany(User::class)->where('role', 'the role of admin user');
}
Hope it helps you.
I'm still trying to wrap my head around whereHas() method. My case is this. I want to pull all users that belong to class
This is relations
Classes model
public function users() {
return $this->belongsToMany('App\User')->withTimestamps();
}
User model
public function classes() {
return $this->belongsToMany('App\Classes')->withTimestamps();
}
controller
$class_us = User::whereHas('classes', function ($query) {
$query->where('class',1);
})->get();
When I do dd($class_us) I get an empty collection.
How can I resolve this problem?
Thanks.
in whereHas clouse the builder instance is coming from the related model so,
$class_us = User::whereHas('classes', function ($query) {
// here the builder belongs to Class model not User model
$query->where('id',1); // id because classes table has column as id
})->get();
my tables:
every part contain many of card.
every card belong to many of part.
now,using laravel eloquent model how can fetch all card for a part without add more column to database
You need to define your relationships like below:
class Part extends Model
{
public function cards()
{
return $this->belongsToMany('App\Cards', 'user_cards');
}
}
Then you can fetch all the cards for a part like below:
$cards = Part::with('cards')->find($part_id);
Part::whereHas('cards', function($query) use ($cardId){
$query->where('id', $cardId);
})->get();
And your model relation should contain like this, for Part.php
public function cards(){
return $this->belongsToMany('App\Card');
}
And for Card.php
public function parts(){
return $this->belongsToMany('App\Part');
}
Here are my relationships:
User
id
Collection
id
UserCollection
user_id
collection_id
How can I get something like $user->collections to return all Collection objects that belongs to the user? A UserCollection simply links a User to a Collection. This allows a user to have multiple collections, but also allows a collection to belong to multiple users.
What I'm currently trying is to specify that UserCollection belongs to a User on user_id, and belongs to a Collection on collection_id.
// UserCollection
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function collection()
{
return $this->belongsTo(Collection::class, 'collection_id');
}
Then specifying that a User has many Collections through UserCollection.
// User
public function collections()
{
return $this->hasManyThrough(Collection::class, UserCollection::class);
}
I've also tried explicitly setting the column names of the hasManyThrough relationship, but the join tries to use an id column on the UserCollection model, which does not exist as there is no primary key:
public function collections()
{
return $this->hasManyThrough(Collection::class, UserCollection::class, 'user_id', 'collection_id');
}
You're overcomplicating things here. You don't need hasManyThrough. What you need is belongsToMany() for a many-to-many relationship.
First, get rid of your UserCollection model. You don't need it.
Then change your relations to this:
public function collections(){
return $this->belongsToMany('Collection', 'user_collections');
}
public function users(){
return $this->belongsToMany('User', 'user_collections');
}
For more information take a look at the official docs on relations
I have three tables like this:
**Users**
id
**Posts**
id
user_id
**Favorites**
id
user_id
post_id
Currently, I made it so when I query my posts for display, it pulls all the related user data who created the post with that row which is great! But what I'm trying to do now is also add to see if the user Authorized (Logged in) has favorited the post (row) so I can display to that they already favorited it. I don't want to re-query for every post (i think its called the N+1 problem?). I'm using Laravel4
Post model
class Post extends Eloquent{
public function user(){
return $this->belongsTo('User');
}
User model
public function posts(){
return $this->hasMany('Post');
}
PostsController
public function index()
{
$posts = Post::with('user')->paginate(25);
return View::make('index', compact('posts'));
}
Step 1. Add favorites relationship in Post model.
public function favorites() {
return $this->hasMany('Favorite');
}
When querying the Model.
$auth_user_id = Auth::user()->id;
$posts = Post::with(array('user', 'favorites' => function($query) use ($auth_user_id){
$query->where('user_id', '=', $auth_user_id);
}))->get();
For more information refer to the eager load constraints,
http://laravel.com/docs/eloquent#eager-loading
Adding a many-to-many relationship using the favorites table as pivot would be one approach.
Add favorites relationship in User model:
public function favorites() {
return $this->belongsToMany('Post', 'favorites');
}
You should then be able to get all favorites by simply accessing
Auth::user()->favorites
To find whether the current post is a favorite, use
$isFavorite = Auth::user()->favorites->has($post->id);