Laravel select only categories wherein product ids - laravel

Hi i have a categories and products table with one to many relation. I want to select categories with products which are in product_ids(which it will get from other query). I tried
$categories = Category::with(['products' => function ($query) use($product_ids) {
$query->whereIn('id', $product_ids);
}])
->get();
the above query will select all the categories even if the product not in product_ids ( empty array if not in produc_id) but i just want to select those categories which has the products in the product_ids.please help

I just Solved it by adding whereHas
$categories = Category::with(['products' => function ($query) use($product_ids) {
$query->whereIn('id', $product_ids);
}])
->whereHas('products', function ($q) use($product_ids) {
$q->whereIn('id', $product_ids);
})
->get();

Use whereHas
$categories = Category::whereHas('products', function ($query) use($product_ids) {
$query->whereIn('id', $product_ids);
})
->get();

Related

Laravel eloquent with and with condition

I'm trying to get category and selected items from category. Here is my code:
$reqItems = $request->items; //array - selected item
$categories = Category::where('type_id', 1)
->whereHas('items', function ($query) use ($reqItems){
$query->whereIn('id', $reqItems);
})
->with('items');
->get();
But this will return all the items, even not in selected item.
And i tried with foreach, its return null
$reqItems = $request->items; //array - selected item
$categories = Category::where('type_id', 1)->with('items');
foreach($reqItems as $reqItem) {
$categories = $categories->whereHas('items', function ($query) use ($reqItem){
$query->where('id', '=', $reqItem);
});
}
$categories = $categories->get();
How to return only selected items?
As suggested by #lagbox, here the working code:
$reqItems = $request->items;
$categories = Category::where('type_id', 1)
->with(['items' => function ($query) use ($reqItems){
$query->whereIn('id', $reqItems);
}])->get();
when you wish to eager load a relationship and specify additional query conditions for the eager loading query. You can accomplish this by passing an array of relationships to the with method where the array key is a relationship name and the array value is a closure that adds additional constraints to the eager loading query:
$categories = Category::where('type_id', 1)
->whereHas('items', function ($query) use ($reqItems){
$query->whereIn('id', $reqItems);
})
->with(['items'=>function ($query) use ($reqItems){
$query->whereIn('id', $reqItems);
}])
->get();

i need pagination with sortBy in laravel

I have 3 tables products, prices, cats.
I need to filter product by cats and sort by price but I have a problem:
this code work very well but needs pagination.
$products = Product::with('photo', 'price', 'brand')
->whereHas('cats', function ($q) use ($cat) {
$q->where('cat_id', $cat->id);
})
->get()
->sortByDesc(function($query) {
return $query->price->price;
});
at first I did it like this:
$products = Product::with('photo', 'price', 'brand')
->whereHas('cats', function ($q) use ($cat) {
$q->where('cat_id', $cat->id);
})
->paginate($page)
->sortByDesc(function ($query) {
return $query->price->price;
});
but links() did not work.
After i did it like this:
$products = Product::with('photo', 'price', 'brand')
->whereHas('cats', function ($q) use ($cat){
$q->where('cat_id', $cat->id);
})
->paginate($page);
$products->setCollection(
$products->sortBy(function ($query) {
return $query->price->id;
})
);
but sortBy does not work.
so I can't use orderBy() by join prices table
because when I do it I can show all products and I can't filter product by categories
my mind does not work, if someone can to help me, I will be very grateful
I believe you can also do:
Product::join('price', 'price.id', '=', 'photo.price_id')
->orderBy('price.price', 'asc')
->select('photo.*')
->paginate(10);

Pluck the values from WITH Eloquent in Laravel

I have a dropdown box that shows only the user with collector and borrower's role. Here's my code
public function create()
{
$users = User::whereHas('roles', function ($q) {
$q->where('roles.name', '=', 'collector')->orWhere('roles.name', '=', 'borrower');
})
->with('profile')
->get()
->pluck('name','id');
return view('dashboard.documents.create', compact('users'));
}
this code is fine but what I what to pluck is the column first_name, last_name and user_id from 'profile'.
How can I achieve that?
Thank you so much in advance!
You do one of these
$users = User::whereHas('roles', function ($q) {
$q->where('roles.name', '=', 'collector')->orWhere('roles.name', '=', 'borrower');})
->with('profile')
->select('name','id')
->get();
Or
$users = User::whereHas('roles', function ($q) {
$q->where('roles.name', '=', 'collector')->orWhere('roles.name', '=', 'borrower');})
->with('profile')
->get(['name','id']);
Both ways will return a collection with related models each model record will has the selected columns, if you want to convert it to an array you can add ->toArray() after the two ways and it will convert the collection to array.

How to implement relationship in where condition Laravel's eloquent?

I have two tables:
Students
Results
The two tables have one to may relationship.
Student model:
public function results()
{
return $this->hasMany('App\Result');
}
Result model:
public function student()
{
return $this->belongsTo('App\Student');
}
In the students table I have a field called average_score.
How can I execute the following query, this is not working it says "Undefined property: Illuminate\Database\Query\Builder::$student":
$data = Result::with('student')->where('score', '>=', function($q){
$average_score = $q->student->average_score;
return $average_score;
})->get();
In order to get the results that are only higher or equal to than the "average_score".
If score and average_score are columns of the same table (student), try this;
$data = Result::with(['student' => function ($query) {
$query->whereColumn('score', '>=', 'average_score');
}])->get();
If score and average_score are columns of the different tables, try this;
$data = Result::with('student')->whereHas('student', function($q) {
$q->whereColumn('students.average_score', '<=', 'results.score');
})->get();
You can use whereHas to find those results:
$data = Result::with('student')->whereHas('student', function($q) {
$q->whereColumn('average_score', '<=', 'Results.score');
})->get();
get value from column Results.average_score then compare to student.score:
Result::with([
'student' => function($query) {
$query->where("score",">=", "Results.average_score"););
}
])

Laravel 4 Eager Loading constraints

I want to get all Items (topics) WITH their comments, if comments user_id = $id. I try something like this, but it isn't working. So if Item hasn't got any comment with user_id = $id, then I don't need this Item.
In DiscussionsItem model I have methode:
public function discussionsComments() {
return $this->hasMany('DiscussionsComment', 'discussionsitem_id');
}
My query in controller is like this:
$items = DiscussionsItem::whereBrandId($brand_id)
->whereBrandCountryId($country_id)
->with(['discussionsComments' => function($query) use ($id) {
$query->where('user_id', '=', $id);
}])
->whereHas('discussionsComments', function($query) use ($id) {
$query->where('user_id', '=', $id);
})
->with(['views' => function($query) use ($id) {
$query->where('user_id', $id)->count();
}])
->orderBy('created_at', 'DESC')->get();
My problem is that I get items with comments, where comments user_id != $id.
P.S. I need to take 5 comments, but I cant imagine how to do that, because ->take(5) in my eager load is not working.
You can do a custom scope, or just limit the amount returned by your relation:
public function discussionsComments() {
return $this->hasMany('DiscussionsComment', 'discussionsitem_id')
->latest()
->take(5);
}

Resources