How to eagerload an array of values from a belongsTo relationship - laravel

I have 3 tables representing a many to many (belongsToMany) relationship between User and Group and GroupUser as the pivot table. What I would like to do is simply display all users that are NOT a member of group_id 2.
User model GroupUser model (pivot table) Group model
ID|name ID|user_id|group_id ID|group_name
1 |Mark 1| 1 |2 1| the sharks
2 |Sam 2| 3 |1 2| the tigers
3 |Sally 3| 2 |3 3| the whales
4 |Tim 4| 4 |2
My solution
Create a belongsTo (hasMany) relationship between User and GroupUser so GroupUser belongsTo User and then eager load all users that are not a member of group_id 2.
How would I go about writing the code in my controllers and viewing this in blade?
Before I use the WhereNotIn condition I'm trying to simply eager load all users. So far I have this but for some reason it's only reading the last line in the group_user table.
foreach (GroupUser::with('belongstomethod')->get() as $query)
{
$query->belongstomethod->name;
}
The result from the code above is Tim

This will display all the users that are not part of group_id = 2.
Controller or repository:
$group_id = 2;
$users = User::whereHas('groups',function($query) use($group_id) {
$query->where('id','!=',$group_id);
})->get();
return view('your_view',compact('users')); //this will pass the $users collection to the view.
View (using blade):
#foreach($users as $user)
{{$user->name}}
{{$user->etc}}
#endforeach
This code assumes you have a public method called "groups" on your User Model. And that the method returns a belongsToMany relationship.

Related

Filter query in Meta table Laravel

users Tabel
**id|name**
1|xx
users_meta Table
id | user_id | metaKey | metavalue
1 | 1 | city | kolkata
2 |2 |city | london
3 |8 |city |london
My moto is to return users belongs to city London.How can i achive this??
You can query using whereHas:
User::whereHas('users_meta', function ($query) {
$query->where('metavalue', 'london');
})->get();
Lets say u have a relationship with Users and user_meta
Than simply
User::with(['userMeta' => function($query){
$query->where('metaKey', 'city')
$query->where('metavalue', 'london')
}]);
Hope this helps

Laravel running multiple queries instead of join in Eloquent

I am trying to run join between my pages table and users table. Means one user can create multiple pages and in pages table created_by column belongs to my users table column id.
Table Structure:
---------------------------------------------
id | page_title | page_desc | created_by |
---------------------------------------------
1 | Testing | Descripti | 1 |
---------------------------------------------
2 | New Page | Desc | 2 |
User table
-------------------------------------------
id | name | email | pass | created_at |
-------------------------------------------
1 | A | a#g.c | 123 | 2017-10-21 |
-------------------------------------------
2 | B | b#g.c | 123 | 2017-10-21 |
in my Page model i used:
public function createdBy(){
return $this->belongsTo('App\User','created_by','id');
}
now when i am trying to get the data with:
$model = Page::all()
foreach($model as $key => $value){
echo $value->createdBy->name."<br/>";
}
laravel generating multiple queries to get name of each user is that any way to run the join instead of multiple queries?
You're running into the N+1 problem. You need to eager load your relationship to resolve this. You can read more on eager loading here.
Use the with() method on the page query to eager load all the related user records for each page:
$model = Page::with('createdBy')->get();
foreach ($model as $key => $value) {
echo $value->createdBy->name."<br/>";
}
This will now only run 2 queries: one to get all the pages, and one to get all the users related to each page.
For that reason Laravel provides eager Loading
Eager Loading
When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property. However, Eloquent can "eager load" relationships at the time you query the parent model
For more info just check this link.
OR Just Use Laravel's database query builder
You can perform join directly on your Table and fetch directly the data
$users = DB::table('pages')
->join('users', 'pages.created_by', '=', 'users.id')
->select('users.name','users.email', 'pages.*') //Specify what parameters you want.
->get();
To Join queries you can use laravel query builder like below
$pages = DB::table('pages')
->join('users', 'pages.created_by', '=', 'users.id')
->select('users.*', 'pages.*')
->get();

How in query Eloquent specify condition with relations

I have 2 tables:
articles
id | title | category_id | created_at | updated_at |
and categories
id | name | descriptions | created_at | updated_at |
Relations : category hasMany-> articles and articles belongsTo -> category.
how simple way make query something like :
public functions getArticles ($category) {
$articles = Articles::where('category', '=', $category);
}
In documentations exist example with Id (http://laravel.com/docs/4.2/eloquent#one-to-many ) , but I want select articles, knowing name category.
How in query specify condition with relations ?
If exist such methods, please help me.
Thanks ;)
You can use whereHas method. Like:
$articles = Articles::whereHas('category', function($query)use($category){
$query->where('name', $category->name);
});
I suppose that should work. Or you can just create a scope and join categories table and then check by it.

Laravel 4 - Simple join with Eloquent?

I'm simply trying to join 2 tables with Laravel 4's Eloquent ORM. The tables are:
TABLE: PRODUCTS
ID | CATEGORY_ID | NAME
-------------------------
1 | 2 | Hammer
2 | 2 | Saw
3 | 1 | Apple
TABLE: CATEGORIES
ID | NAME
-----------
1 | Food
2 | Tools
Of course this can be done with SQL:
SELECT products.name, categories.name
FROM products
INNER JOIN categories ON products.category_id = categories.id
And this will output:
Hammer | Tools
Saw | Tools
Apple | Food
But is there an easier way to get the same result using Laravel's Eloquent, maybe using the build-in table relationships?
Set up a many-to-one relation in your models:
Category.php
public function products() {
return $this->hasMany('Product');
}
Product.php
public function category() {
return $this->belongsTo('Category');
}
Then call:
$products = Product::with('category')->get();
For each element of the result, $products->name and $products->category->name will contain your fields.

Laravel - Get an user who has specific relationships

I have a user with countries relationship. (hasMany)
user_id 1
country_id 1
user_id 1
country_id 2
...
What I want is to get those users who have both countries (country 1 and country 2) How can I do this? I'm reading http://laravel.com/docs/eloquent#querying-relations but I'm not very sure what to do.
edit: almost the solution
$users = \User::whereHas('countries', function($query) {
$countries_ids = [1, 2, 4];
$query->whereIn('users_countries.country_id', $countries);
})->get();
This will work as long as there are no duplicates in the pivot table (unique index for pair of fk keys for example):
$countries = [1,5,9];
User::whereHas('countries', function ($q) use ($countries) {
$q->whereIn('users_countries.country_id', $countries);
}, '=', count($countries) )->get();
In case there are duplicates, like:
user_id | country_id
1 | 1
1 | 2
1 | 1
Then you would need raw count(distinct ...) so you couldn't use whereHas, so I suggest this, which will be much faster:
$countries = [1,5,9];
User::join('users_countries as uc','uc.user_id', '=', 'users.id')
->whereIn('uc.country_id', $countries)
->having(DB::raw('count(distinct uc.country_id)'), '=', count($countries))
->groupBy('users.id')
->get(['users.*']);
You can do it the other way. Make the query on the country model. Add a function in the country model
public function user(){
return $this->belongsTo('user');//or if there is no user_id column in the countries table, use the ('model','local_key','foreign_key') pattern.
}
Then create an array with the country_ids, and que the country model.
$country_ids=array(4,67);
$countries=Country::where('id',$country_ids[0])->where('id',$country_ids[1])->get();
In order to get the users you should loop through like this
foreach($countries->user as $user)

Resources