Laravel eloquent with and with condition - laravel

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();

Related

Laravel - Filter collection with closure on relationship

Wondering if there is a way to use closure on a relationship in order to filter the whole line if there isn't a value which corresponds?
Example code:
foreach ($paiementMethods as $value) {
$giftCards = GiftCard::with(['userEntered', 'userEmployee', 'client', 'payement', 'payement.payementMethods' => function($query) use ($value)
{
$query->where('id', $value);
}])
->where('date','>=', $dateStart)
->where('date','<=', $dateEnd)
->orderBy('updated_at', 'desc')->get();
$giftCardsCollection = $giftCardsCollection->merge($giftCards);
}
}
In this example, if $query->where doesn't find a row for the payement.payementMethods which matches the $value, I want the giftCard to return null. The result I get is the giftCard with only the relation on payement.payementMethods being empty.
My other solution would be to query the giftCard and after that checking the $value to see if I have to include the giftCard in the collection or not.
Best regards
I think using whereHas, it can be solved
$giftCards = GiftCard::with(['userEntered', 'userEmployee', 'client', 'payement', 'payement.payementMethods'])
->whereHas( 'payement.payementMethods', function($query) use ($paiementMethods) {
$query->whereIn('id', $paiementMethods);
})
->where('date','>=', $dateStart)
->where('date','<=', $dateEnd)
->orderBy('updated_at', 'desc')
->get();

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 remove parent if related collection

I have a model with a related collection
now im doing this query
$data = DeliveryPartner::when($filter, function ($q) use ($request) {
})
->with(['orders' => function ($query) {
$query
->where('delivery_partner_invoice_id', '=', '')
->orWhereNull('delivery_partner_invoice_id')
->whereIn('status', ['payment-accepted', 'completed', 'full-refund', 'partial-refund']);
}])->get();
Now i am wondering. If the orders returns empty is it posible to remove this parent from the collection?
I Know i can do this after the eloquent query with a loop. But is it possible to do this in the query?
we cant completely remove that parent ( with index ) BUT you can set those to null using transform() like this;
$data = DeliveryPartner::when($filter, function ($q) use ($request) {
})
->with(['orders' => function ($query) {
$query
->where('delivery_partner_invoice_id', '=', '')
->orWhereNull('delivery_partner_invoice_id')
->whereIn('status', ['payment-accepted', 'completed', 'full-refund', 'partial-refund']);
}])->get()->transform(function($item){
if(!$item->orders->count() ){
return;
}
return $item;
});
Note: this will not completely remove those parents but it will set them to empty.

How to get flat array of eager loading in laravel 5.5?

this my eloquent query:
$data = Disciplines::where('type', '<>', 'Initiator')
->with(['discipline_boxes.assign.box' => function($query) {
$query->select('id');
}])
->get();
return $data;
i want return only array of id's of box relation
e.g:[2,3,4,5]
Solved!!
this worked for me!
$disciplines = new Disciplines();
$results = $disciplines->getAllBox_ID()->toArray();
dd(array_flatten(array_pluck($results,'discipline_boxes.*.assign.box.id')));
Potentially if you have the inverse for this chain of relationships you could get this information from the Box end (making name assumptions here):
Box::whereHas('assign.discipline_box.discipline', function ($q) {
$q->where('type', '<>', 'Initiator');
})->pluck('id');

Laravel select only categories wherein product ids

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();

Resources