Constrain does not take effect when eager loading in laravel 5 - php

I have this function to get the results from joining relationships. However, the constraints don't seem to be taking effect. If I comment out the constraints, it still it gives the same result set as the uncommented constraints.
public function singleCategory($type, $category)
{
$track = TrackType::with(['tracks.subgenres'], function($query, $category) {
$query->where('name','=', $category);
})->where('name', '=', $type)->get();
dd($track->toArray());
}
Any help would be really appreciated :)

The constraining closure is only passed one parameter: $query. The other parameter you're trying to access ($category) needs to be made available via the use keyword:
public function singleCategory($type, $category)
{
$track = TrackType::with(['tracks.subgenres'], function($query) use ($category) {
$query->where('name', '=', $category);
})->where('name', '=', $type)->get();
dd($track->toArray());
}
Edit
The above will not affect the TrackTypes that are returned, it will only limit the related subgenres that are eager loaded. Based on the comments, it seems as if you are trying to limit the TrackTypes returned to those that contain a certain subgenre. In this case, you need to use the whereHas method:
public function singleCategory($type, $category)
{
$track = TrackType::with('tracks.subgenres')
->whereHas('tracks.subgenres', function($query) use ($category) {
$query->where('name', '=', $category);
})
->where('name', '=', $type)
->get();
dd($track->toArray());
}
Edit 2
It sounds like your target result set is actually the tracks, and not the track types. If so, you probably want to start by querying the tracks, and add in your filter criteria from there (I don't know your exact model and relationship names, so adjust accordingly):
public function singleCategory($type, $category)
{
$track = Track::with(['tracktype', 'subgenres'])
->whereHas('tracktype', function($query) use ($type) {
$query->where('name', '=', $type);
})
->whereHas('subgenres', function($query) use ($category) {
$query->where('name', '=', $category);
})
->get();
dd($track->toArray());
}
If you really are looking to start with the TrackType, then in addition to adding the whereHas() to find the TrackType, you need to add a whereHas() to filter down the Tracks that are eager loaded:
public function singleCategory($type, $category)
{
$track = TrackType::with(['tracks' => function ($query) use ($category) {
$query->whereHas('subgenres', function($query) use ($category) {
$query->where('name', '=', $category);
});
}, 'tracks.subgenres'])
->whereHas('tracks.subgenres', function($query) use ($category) {
$query->where('name', '=', $category);
})
->where('name', '=', $type)
->get();
dd($track->toArray());
}
The first example is much cleaner. In plain English, the first example would sound like "get all tracks of a type and a subgenre". The second example would sound like "get the track type, but only if it has tracks in a certain subgenre; also, only load those tracks within that subgenre".

Related

Nested relation whereHas in laravel

I wanna ask about some nested relation using whereHas query in laravel, well for the first I will explain the model first before I going through into my main case.
this is my model :
StockIn.php
class StockIn extends Model {
protected $primaryKey = "id_stock_in";
/* this only column that I wanna show, and skip the else column */
protected $fillable = ['stock_in_id_type'];
public function type_of_items() {
return $this->belongsTo('App\TypeOfitem', 'stock_in_id_type');
}
}
TypeOfItem.php
class TypeOfItem extends Model {
protected $primaryKey = "id_type_item";
/* this only column that I wanna show, and skip the else column */
protected $fillable = ['type_id_item'];
public function items() {
return $this->belongsTo('App\Item', 'type_id_item');
}
public function stock_ins() {
return $this->hasMany('App\StockIn');
}
}
Item.php
class Item extends Model {
protected $primaryKey = "id_item";
/* this only column that I wanna show, and skip the else column */
protected $fillable = ['item_id_common_unit'];
public function common_units() {
return $this->belongsTo('App\CommonUnit', 'item_id_common_unit');
}
public function type_of_items() {
return $this->hasMany('App\TypeOfItem');
}
}
CommonUnit.php
class CommonUnit extends Model {
protected $primaryKey = "id_common_unit";
/* this only column that I wanna show, and skip the else column */
protected $fillable = [/* describe column */];
public function items() {
return $this->hasMany('App\Item');
}
}
I already describe all of my model, as you can see all table (child) have some relation to each parent like :
stockIn -> typeOfItem (relation between child and parent)
typeOfItem -> Item (relation between child and parent)
Item -> CommonUnit (relation between child and parent)
so for the question is how to make some query to getting data in nesting relationship when I do search for all data in child or parent? I already made the query but the result is not same with my expectation or null, it can be said that.
StockInController
$getData = StockIn::with(['type_of_items' => function ($query) {
$query->select('id_type_item', 'type_id_item', 'code_type_of_item', 'type_of_item')
->with(['items' => function ($query) {
$query->select('id_item', 'item_id_common_unit', 'name_item')
->with(['common_units' => function ($query) {
$query->select('id_common_unit', 'name_unit');
}]);
}]);
}])
->with(['stock_out_left_join' => function ($query) {
$query->select('id_stock_out', 'stock_out_id_stock_in');
}])
->whereHas('type_of_items', function ($query) use ($search) {
$query->where('code_type_of_item', 'like', "%{$search}%");
})
->whereHas('type_of_items.items', function ($query) use ($search) {
$query->orWhere('name_item', 'like', "%{$search}%");
})
->whereHas('type_of_items.items.common_units', function ($query) use ($search) {
$query->orWhere('name_unit', 'like', "%{$search}%");
})
->orWhere('created_by', 'like', "%{$search}%")
->orWhere('edited_by', 'like', "%{$search}%")
->get()
->toArray();
Oh ya I will send example data for my query in this bellow :
but when I do search with some keyword is not worked, for example when I do type "adaptor", the result is empty or nothing show on my data, so what I must to do? Thank you
Okay for a while I was think about my problem finally I got the answer. Okay for sharing to everyone I will explain a little bit for the answer.
So the query what I wrote on the controller, I change into this :
$getData = StockIn::with(['type_of_items' => function ($type_of_item) {
$type_of_item->select('id_type_item', 'type_id_item', 'code_type_of_item', 'type_of_item')
->with(['items' => function ($item) {
$item->select('id_item', 'item_id_common_unit', 'name_item')
->with(['common_units' => function ($common_unit) {
$common_unit->select('id_common_unit', 'name_unit');
}]);
}]);
}])
->with(['stock_out_left_join' => function ($stock_out_left_join) {
$stock_out_left_join->select('id_stock_out', 'stock_out_id_stock_in');
}])
->whereHas('type_of_items', function ($type_of_items_search) use ($search) {
$type_of_items_search->where('code_type_of_item', 'like', "%{$search}%")
->orWhere('type_of_item', 'like', "%{$search}%");
})
->orWhereHas('type_of_items.items', function ($items_search) use ($search) {
$items_search->where('name_item', 'like', "%{$search}%");
})
->orWhereHas('type_of_items.items.common_units', function ($common_units_search) use ($search) {
$common_units_search->where('name_unit', 'like', "%{$search}%");
})
->orWhere('created_by', 'like', "%{$search}%")
->orWhere('edited_by', 'like', "%{$search}%")
->get()
->toArray();
As you can see my new query has a new parameter in every with function and I was naming all the parameter with different name, and not like first name before query, so the problem is the ambiguous paramater in every single with function because this query based on nested relation so I must make the parameter name different each other. Or you want make them into split one by one and not using the nested with function you can use this query too, I put on this bellow :
$getData = StockIn::with(['type_of_items' => function ($query) {
$query->select('id_type_item', 'type_id_item', 'code_type_of_item', 'type_of_item');
}])
->with(['type_of_items.items' => function ($query) {
$query->select('id_item', 'item_id_common_unit', 'name_item');
}])
->with(['type_of_items.items.common_units' => function ($query) {
$query->select('id_common_unit', 'name_unit');
}])
->with(['stock_out_left_join' => function ($query) {
$query->select('id_stock_out', 'stock_out_id_stock_in');
}])
->whereHas('type_of_items', function ($query) use ($search) {
$query->where('code_type_of_item', 'like', "%{$search}%")
->orWhere('type_of_item', 'like', "%{$search}%");
})
->orWhereHas('type_of_items.items', function ($query) use ($search) {
$query->where('name_item', 'like', "%{$search}%");
})
->orWhereHas('type_of_items.items.common_units', function ($query) use ($search) {
$query->where('name_unit', 'like', "%{$search}%");
})
->orWhere('created_by', 'like', "%{$search}%")
->orWhere('edited_by', 'like', "%{$search}%")
->get()
->toArray();
I already tried that query and it's work too (with the same name parameter in every single with function).

how can i do query biulder with (AND) for 3 or more parameters

im did a query for brand of car and the model but when i did added a
query to price range (whereBetwen) its not working
public function indexBrowse(Request $request)
{
$brand=$request->get('searchbrand');
$model=$request->get('searchmodel');
$searchtype=$request->get('searchtype');
$from=$request->get('pricefrom');
$to=$request->get('priecto');
$cars=car::where('brand', 'like', '%'.$brand.'%')
->where(function ($query) use ($model) {
$query->where('model','like','%'.$model.'%');
})->where(function ($query2) use ($from,$to) {
$query2->car::whereBetween('price',['%'.$from.'%','%'.$to.'%']);
})->get();
dd($cars);
$success = 'Results Car';
return view('cars.index', compact('cars', 'success'));
}
Something like this if you want to perform all these where with and condition.
car::where('brand', 'like', '%'.$brand.'%')
->where('model','like','%'.$model.'%')
->whereBetween('price'['%'.$from.'%','%'.$to.'%'])->get();

Laravel nested relation filter

Have a query, how I can filter results by translation relation (by name column)
$item = Cart::select('product_id','quantity')
->with(['product.translation:product_id,name','product.manufacturer:id,name'])
->where($cartWhere)
->get();
my model
Cart.php
public function product($language = null)
{
return $this->hasOne('App\Models\Product','id','product_id');
}
Product.php
public function translations()
{
return $this->hasMany('App\Models\ProductTranslation','product_id','id');
}
Update v1.0
do like this, but query takes too long time
$item = Cart::select('product_id','quantity')
->with(['product.translation', 'product.manufacturer:id,name'])
->where($cartWhere)
->when($search,function ($q) use ($search) {
$q->whereHas('product.translation', function (Builder $query) use ($search) {
$query->where('name', 'like', '%'.$search.'%');
$query->select('name');
});
}
)
->get() ;
Inside the array within your with() method, you can pass a function as a value.
Cart::select('product_id','quantity')
->with([
'product', function($query) {
$query->where($filteringAndConditionsHere);
}
]);
https://laravel.com/docs/7.x/eloquent-relationships#eager-loading

How to use laravel collection methods

I'm trying to query a nested relation and getting the count of distant model count, I'm transforming this to a variable but it is not happening:
$companies = Company::where('is_client', '=', 1)
// load count on distant model
->with(['interactionSummaries.interaction' => function ($q) {
$q->withCount(['contactsAssociation' => function ($q) {
$q->whereHas('company', function ($q) {
$q->where('type', 'like', 'Research');
});
}]);
}])
->get()
->transform(function ($company) {
$company->contacts_association_count = $company->interactionSummaries
->pluck('interaction.contacts_association_count')
->collapse()
->sum();
});
When I try to dd($companies) or even return $companies I get null values placed in each array index
But when I do dd($company) inside transform
->transform(function ($company) {
$company->contacts_association_count = $company->interactionSummaries
->pluck('interaction.contacts_association_count')
->collapse()
->sum();
dd($company);
});
I get the single collection which states my query is running properly:
If I remove transform part and simply get the collection:
$companies = Company::where('is_client', '=', 1)
// load count on distant model
->with(['interactionSummaries.interaction' => function ($q) {
$q->withCount(['contactsAssociation' => function ($q) {
$q->whereHas('company', function ($q) {
$q->where('type', 'like', 'Research');
});
}]);
}])
->get()
I'm getting the desired output, But I don't know what it is happening after transform execution. In fact it is not plucking and adding the sum, as I'm getting all 0 in the counts.
I've marked them with red. Help me out in this
I think you are missing a return statement in the transform closure.
You need to put return $company statement in transform.

Laravel paginate order by

What should I do to pass the values ​​that you order by in patinate?
routes.php
$ondata = DB::table('official_news') -> orderBy('created_date', 'desc') -> get() -> paginate(7);
return View::make('main',array('ondata' => $ondata));
error
Call to a member function paginate() on a non-object
I need your help
This should do the trick:
$ondata = DB::table('official_news')->orderBy('created_date', 'desc')->paginate(7);
It will be better if you order it by the id because it is going to be faster from the database.
$posts = Post::orderBy('id', 'desc')->paginate(6);
https://laracasts.com/discuss/channels/laravel/combining-paginate-with-orderby
It works fine for Laravel 5.1.
You can use something like this in your controller file.
$transactions = Transaction::orderBy('name')->paginate(10);
return view('index', compact('transactions'));
If you are using scope
public function scopeSearch($query, $term)
{
$term = "%$term%";
$query->where(function ($query) use ($term) {
$query->where('name', 'like', $term)
.............
..............
->orWhere('pan_number', 'like', $term);
})->orderBy('created_at', 'DESC');
}

Categories