Nested relation whereHas in laravel - php

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).

Related

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 Livewire search and filter through relationships

Sorry for my bad english. This is my first post here and I'm a kind of noob in developpment..
Thanks to a lot of reading and some tutorials, I managed to build a small Laravel application.
For various reasons, I decided to include Livewire and it's great.
However, I'm facing some issues in searching and filtering entries from different models and relationships.
Image of what I'm trying to do
I have a model called Seance and I can search through Grade, Theme and Product models (2, 3 & 5 on the image).
My Seance Model :
class Seance extends Model
{
use SoftDeletes;
protected $guarded = [];
public function product()
{
return $this->belongsTo('App\Product');
}
public function theme()
{
return $this->belongsTo('App\Theme');
}
public function specialty()
{
return $this->belongsTo('App\Specialty');
}
public function grade()
{
return $this->belongsTo('App\Grade');
}
public function courses()
{
return $this->hasMany('App\Course');
}
public function category()
{
return $this->belongsTo('App\Category')->withTrashed();
}
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function specialties(): BelongsToMany
{
return $this->belongsToMany('App\Specialty', 'seance_specialty', 'seance_id', 'specialty_id');
}
public function scopeSearch($query, $term)
{
$term = "%$term%";
$query->where(function($query) use ($term){
$query->where('id', 'like', $term)
->orWhere('name', 'like', $term)
->orWhere('slug', 'like', $term)
->orWhere('subtitle', 'like', $term)
->orWhere('description', 'like', $term)
->orWhereHas('grade', function($query) use ($term){
$query->where('name', 'like', $term);
})
->orWhereHas('product', function($query) use ($term){
$query->where('name', 'like', $term);
})
->orWhereHas('theme', function($query) use ($term){
$query->where('name', 'like', $term);
})
->orWhereHas('category', function($query) use ($term){
$query->where('name', 'like', $term);
});
});
}
}
But I would like to search through the point 4 that is related to 3 and through the point 6 that is related to 5 and I don't know how to do that.
The point 3 is a Model called Theme and it belongs to a Model called Discipline (point 4)
public function discipline()
{
return $this->belongsTo('App\Discipline');
}
The point 5 is a model called Produt and it belongs to a model called Coursetype (point 6)
public function coursetype()
{
return $this->belongsTo('App\Coursetype');
}
I know there is join to do somewhere but I don't exactly know where...
Here's my Livewire component :
use WithPagination;
protected $paginationTheme = 'bootstrap';
public $search = "";
public $paginate = 5;
public $selectedGrade = null;
public $selectedProduct = null;
public $selectedCategory = null;
public $selectedTheme = null;
public $selectedDiscipline = null;
public function render()
{
return view('livewire.seances-table', [
'seances' => Seance::with('product', 'theme', 'specialty', 'grade', 'courses', 'category', 'specialties')
->when($this->selectedGrade, function($query){
$query->where('grade_id', $this->selectedGrade);
})
->when($this->selectedProduct, function($query){
$query->where('product_id', $this->selectedProduct);
})
->when($this->selectedCategory, function($query){
$query->where('category_id', $this->selectedCategory);
})
->when($this->selectedTheme, function($query){
$query->where('theme_id', $this->selectedTheme);
})
->when($this->selectedDiscipline, function($query){
$query->where('discipline_id', $this->selectedDiscipline);
})
->search(trim($this->search))
->paginate($this->paginate),
'grades' => Grade::all(),
'products' => Product::all(),
'categories' => Category::all(),
'themes' => Theme::all(),
'disciplines' => Discipline::all()
]);
}
Also, I would like to filter through the Disciplines (point 4) but I get this error.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'discipline_id' in 'where clause'
I know why I'm getting this error, but I don't know how to fix it.
Sorry if all this is not very clear.
Any help would be much appreciated.
Thanks you all and cheers from France
since discipline_id is under themes table which is related to Seance model.
I suggest doing
$query->where('theme.discipline_id', $this->selectedDiscipline);

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

Why does my whereHas query error out with undefined method "getHasCompareKey()"?

I have a model Job which is attached to one model Project.
Here are the class definitions:
class Job extends Model
{
public function project() {
return $this->belongsTo('App\Project');
}
}
class Project extends Model
{
public function jobs() {
return $this->hasMany('App\Job');
}
}
I'm trying to query the Jobs collection and filter on either jobs.title or project.title.
Here is my current search query:
$jobs = Job::where(function($query) use ($searchTerm) {
$query->where('title', 'LIKE', $searchTerm)
->orWhereHas('project', function ($subQuery) use ($searchTerm) {
return $subQuery->where('title', 'LIKE', $searchTerm);
});
})->get();
However, this is returning an error:
Call to undefined method Jenssegers\Mongodb\Query\Builder::getHasCompareKey()
I think you need to clean up your code a bit:
$jobs = Job::where('title', 'LIKE', $searchTerm)
->orWhereHas('project', function ($query) use ($searchTerm) {
$query->where('title', 'LIKE', $searchTerm);
})->get();

How to use laravel collection helper methods?

I'm trying to build a small application on laravel-5.4 where I'm having a relational query something like this:
$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', 'Investor');
});
}]);
}])
->get();
Now I want to collect all the contact_association_counts generated from the query and add it to individual company collection For this I'm using pluck, collapse and sum method, but I don't know it is not calculating as desired. Following is the screenshots:
I get list of collection as following:
Now I get the attributes:
Now relational data:
Now interaction data, where the count belongs:
So for this I tried:
$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', 'Investor');
});
}]);
}])
->get()
->transform(function ($company) {
$company->contacts_association_count = $company->interactionSummaries
->pluck('interaction.contacts_association_count')
->collapse()
->sum();
return $company;
});
But this is not calculating the counts, all the counts are coming to 0
Help me out in this. Thanks
I believe that your problem is the ->collapse() seeing your example after the ->pluck('interaction.contacts_association_count') you should have a flat array as [1,2,3,4,5] if you apply collapse() to a flat array it returns a void array [] and the sum of a void array is 0
$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', 'Investor');
});
}]);
}])
->get()
->transform(function ($company) {
$company->contacts_association_count = $company->interactionSummaries
->pluck('interaction.contacts_association_count')
//->collapse()
->sum();
return $company;
});
I hope it works... good luck!

Categories