Search result with multiple tables relation in Laravel6 - laravel

I'm trying to make search function with relation.
I could display all result using relation And an another code, simple one table search and get result works fine.
but I can't combine those two.
Could you teach me how to combine multiple tables into search function please?
public function order(Request $request)
{
$data = $request->all();
$products = Product::All();
$products = Product::with('categori')
->join('creators', 'creators.id', '=', 'products.creator_id')
->join('categoris', 'categoris.id', '=', 'products.categori_id')
->join('branches', 'branches.id', '=', 'products.br_id')
->join('users', 'users.id', '=', 'products.user_id')
->join('colors', 'colors.id', '=', 'products.color_id')
->get();
$products = Product::when($data['categori_id'], function ($query, $categori_id) {
return $query->where('categori_id', $categori_id);
})->
when($data['color_id'], function ($query, $color_id) {
return $query->where('color_id', $color_id);
})->get();
//return view('result_fb', compact('images'));
$data = array(
'title' => 'index',
'no' => 1,
'products' => $products,
);
return view('product.result', $data);
}

I am not sure if you need 'categori' relation to be loaded or not as there are few $products without it. For general, you can combine all your $products queries to one as follows:
$products = Product::join('creators', 'creators.id', '=', 'products.creator_id')
->join('categoris', 'categoris.id', '=', 'products.categori_id')
->join('branches', 'branches.id', '=', 'products.br_id')
->join('users', 'users.id', '=', 'products.user_id')
->join('colors', 'colors.id', '=', 'products.color_id')
->when($data['categori_id'], function ($query, $categori_id) use ($data) {
return $query->where('categori_id', $data['categori_id']);
})
->when($data['color_id'], function ($query) use ($data) {
return $query->where('color_id', $data['color_id']);
})->get();
If you want to use eager loading with eloquent rather then join, you can use like
$products = Product::with(['creator','categori','branch','user','color'])
->when($data['categori_id'], function ($query, $categori_id) use ($data) {
return $query->where('categori_id', $data['categori_id']);
})
->when($data['color_id'], function ($query) use ($data) {
return $query->where('color_id', $data['color_id']);
})->get();
But for that you Product model should have relations with same name as follows for categori relation:
class Product extends Model
{
public function categori()
{
return $this->belongsTo(Categori::class,'categori_id','id);
}
}
Same way you have to define for all relation used for product.

Try this:
$products = Product::with('categori')
->join('creators', 'creators.id', '=', 'products.creator_id')
->join('categoris', 'categoris.id', '=', 'products.categori_id')
->join('branches', 'branches.id', '=', 'products.br_id')
->join('users', 'users.id', '=', 'products.user_id')
->join('colors', 'colors.id', '=', 'products.color_id')
->when($data['categori_id'], function ($query, $categori_id) {
return $query->where('categori_id', $categori_id);
})
->when($data['color_id'], function ($query, $color_id) {
return $query->where('color_id', $color_id);
})
->get();

Related

Laravel 8 - How to use where conditions for relation's column

hello friends can you help me to get the contents of $filter? I want to run where which is where the target column is in the relation array
$filter = $request->get('Biogear');
$data = DetailBarang::with(['barang' => function ($q) use ($filter) {
$q->where('brand', '=', $filter);
}])->get();
return response()->json($data);
you can try this
$filter = $request->get('Biogear');
$data = DetailBarang::with('barang')->whereHas('barang',function (Illuminate\Database\Eloquent\Builder $q) use ($filter) {
$q->where('brand', '=', $filter);
})->get();
return response()->json($data);

Laravel Eloquent making select on whereHas()

How can I select on whereHas() some columns in relation.
My current query looks like as it follows
Location::select(['title'])
->withCount(['job' => function($q) {
return $q->where('language_id', 1)->whereNull('deleted_at');
}])->whereHas('country', function ($q) {
return $q->where('id', '=', 80);
})->get();
and I tried
Location::select(['title', 'id as value'])->withCount(['job' => function($q) {
return $q->where('language_id', 1)->whereNull('deleted_at');
}])->whereHas('country', function ($q) {
return $q->select('title', 'iso3')->where('id', '=', 80);
})->get();
but nothing is getting returned on country relation. How do I refactor this query to get it work?
whereHas() doesn't eager load the relation, only filters results based on it. To eager load, use with().
Location::with('country:id,title,iso3')
->select(['title', 'id as value', 'country_id'])
->withCount(['job' => function($q) {
$q->where('language_id', 1)->whereNull('deleted_at');
}])
->whereHas('country', function ($q) {
$q->where('id', '=', 80);
})->get();

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.

Laravel search with relations

I have the following relations in my Laravel application
class Item extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
and
class Category extends Model
{
public function item()
{
return $this->hasMany('App\Item');
}
}
I want to implement search functionality so I have created the following Eloquent query:
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query->where('item_name','LIKE','%'.$q.'%')
->orWhere('item_description','LIKE','%'.$q.'%');
})
->paginate(10);
This is working as expected and returns the search results for 'q' based on the name and the description of the item.
As a next step, I would like to also search for the category_name. Because of the relation, I have the category_id stored in the Items table, but I would like to use the category_name in my Eloquent query.
Anyone could provide some help?
Based on feedback received, I tried:
Suggestion 1:
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query
->where('item_name', 'LIKE' ,'%'.$q.'%')
->orWhere('item_description', 'LIKE' ,'%'.$q.'%');
})
->whereHas('category', function (Category $query) use ($q) {
$query->where('category_name', $q);
})
=> this gives following error message:
Argument 1 passed to
App\Http\Controllers\ItemController::App\Http\Controllers{closure}()
must be an instance of App\Http\Controllers\App\Category, instance of
Illuminate\Database\Eloquent\Builder given
Suggestion 2:
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query
->where('item_name', 'LIKE' ,'%'.$q.'%')
->orWhere('item_description', 'LIKE' ,'%'.$q.'%');
})
->whereHas('category', function ($query) use ($q) {
$query->where('category_name', $q);
})
=> this does not result any search result anymore (also not for item_name and item_description).
Solution
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query
->where('item_name', 'LIKE' ,'%'.$q.'%')
->orWhere('item_description', 'LIKE' ,'%'.$q.'%');
})
->orWhereHas('category', function ($query) use ($q) {
$query->where('category_name', $q);
})
->sortable(['id' => 'desc'])
->paginate(10);
As you already described relation to Category in your Item model, you have to use just whereHas method:
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query->where('item_name','LIKE','%'.$q.'%')
->orWhere('item_description','LIKE','%'.$q.'%');
})
->orWhereHas('category', function ($query) use ($q) {
$query->where('category_name', 'LIKE', "%$q%");
})
->paginate(10);
You could add a whereHas and constrain it. For example:
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query->where('item_name','LIKE','%'.$q.'%')
->orWhere('item_description','LIKE','%'.$q.'%');
})
->whereHas('category', function($query) {
$query->where('category_name', 'name');
})
->paginate(10);

Orderby Desc in Eloquent, Laravel

I have a query 3 tables are joined together, I want to order the results in Descending order from created_at in messages table, please help. Thank you.
controller:
return new AllChats(Chat::latest('created_at')->whereHas('messages')->with(['messages.users', 'users' =>
function ($query) {
$query->where('id', '!=', Auth::id());
}])->whereHas('users', function ($query) {
$query->where('id', '=', Auth::id());
})->get());
Display the results in desc order but from messages.created_at??
You need to just add the ->orderBy on your created at field in your query.
return new AllChats(Chat::latest('created_at')->whereHas('messages')->with(['messages.users',
'users' => function ($query) {
$query->where('id', '!=', Auth::id());
}])
->orderBy('created_at', 'desc')
->whereHas('users', function ($query) {
$query->where('id', '=', Auth::id());
})->get());
Reference: https://laravel.com/docs/5.7/eloquent
use like this
return new AllChats(Chat::latest('created_at')>>whereHas('messages',function($q){
$q->orderBy('created_at', 'desc');
})->with(['messages.users', 'users' =>
function ($query) {
$query->where('id', '!=', Auth::id());
}])->whereHas('users', function ($query) {
$query->where('id', '=', Auth::id());
})->get());
You can use a modified withCount():
$chats = Chat::withCount(['messages as latest_message' => function($query) {
$query->select(DB::raw('max(created_at)'));
}])
->orderByDesc('latest_message')
[...]
->get();

Resources