I am using eloquent query to filter data. My query is like this and it is working perfectly for now.
$users = User::where('username','LIKE','%'.request('username').'%')
->where('first_name','LIKE','%'.request('first_name').'%')
->where('last_name','LIKE','%'.request('last_name').'%')
->where('gender','LIKE','%'.request('gender').'%')
->where('password','LIKE','%'.request('password').'%')
->SimplePaginate(15);
My request data was like this.
However I need to update this query for dynamic fields. There can be different fields. What I did was to send the request in an associative array. So, my request data turned into like this,
What I intend to do is to put all request data in a search array. Then use a loop to run like the above query. How can I do that?
P.S. I checked in the forum and found some similar questions. Some of them are outdated. Others didn't solve my problem.
If I understand you right you can do like this:
$search = request('search', []);
$users = User::query();
foreach($search as $field=>$value)
{
$users = $users->where($field,'LIKE','%'.$value.'%');
}
$users = $users->SimplePaginate(15);
You can try this.
$search = $request->get('search');
User::where(function ($q) use ($search){
foreach ($search as $key=>$value) {
if($value != null ){
$q->where($key, 'like', "%{$value}%");
}
}
})->get();
The where() clause can also accept an array. With that in mind, you could map over your search parameters and convert it to the format you want and then feed it into the query.
For example:
$search = [
'first_name' => 'John',
'last_name' => 'Smith'
];
$filters = collect($search)->map(function($value, $key) {
return [$key, 'LIKE', "%{$value}%"];
})->values()->toArray();
return User::where($filters)->SimplePaginate(15);
Related
I have a model that has a field type which consists of several words. The string looks like this: modern premium hot.
How to get relevant results if I want to filter it with an array like this one:
$filter = [0 => 'modern', 1 => 'hot'];
$search = implode(' ', $filter);
$results = Model::where('type', $search)->get();
The above example will not return anything because it will try to match modern premium hot with modern hot and its not the same, but how to get all relevant results that contain the words modern and hot at the same time in the type fields?
In other words how to get all results that have all elements of the array in the type field, which is a string?
Maybe you need a fulltext service like Elastic Search or Algolia, or even look at fulltext search on your database engine (assuming MySQL, check this link).
But if you really need to move on as it is going, you may try something like that:
$query = Model::query();
foreach ($filter as $term) {
$query->orWhere('type', 'LIKE', "%{$term}%");
}
$results = $query->get();
You use orWhere()
$filter = [0 => 'modern', 1 => 'hot'];
$query= Model::query();
foreach($filter as $term) {
$query->orWhere('type', $term);
}
$results = $query->get();
if you have other where() in your query, use this
$filter = [0 => 'modern', 1 => 'hot'];
$results = Model::where(function($query) use($filter) {
foreach($filter as $term) {
$query->orWhere('type', $term);
}
})
//->where(....)
->get();
i want to search data based nama_kegiatan or tanggal_kegiatan where these two name form my table field, this code from my controller :
public function search(Request $request){
$cari = $request->search;
$caritanggal = date($request->datekeg);
$infokeg = Infokeg::where(function ($query) use ($cari) {
$query->where('nama_kegiatan','like',"%$cari%")->get();
})->orWhere(function($query) use ($caritanggal) {
$query->where('tanggal_kegiatan', $caritanggal)->get();;
})->paginate(10);
return view('infokeg/infokeg', ['infokeg' => $infokeg]);
}
when i am using like on nama_kegiatan, tanggal_kegiatan didnt work and just display all data, but when i delete like from nama_kegiatan, its work, but i cant search nama_kegiatan using like, so how to solve it ?
Maybe you can try to get() all the result after the query? Somethings like
$infokeg = Infokeg::where('name_kegiatan','LIKE','%'.$cari.'%')->orWhere('tanggal_kegiatan',$caritanggal)->get();
IMO the get() and paginate() cannot be use at the same time if I have not get it wrong. If you need to paginate after all the result, you can do create Paginator manually. Maybe this link can help you. Hope this will help you and please correct me if anything wrong. Thanks!
If you want to see what is run in the database use dd(DB::getQueryLog()) after query to see what queries exactly were run.
$infokeg = Infokeg::where('nama_kegiatan','like', "%" . $cari ."%")
->orWhere(function($query) use ($caritanggal) {
$query->where('tanggal_kegiatan', $caritanggal);
})->paginate(10);
just make it into if condition
public function search(Request $request)
{
$cari = $request->search;
$caritanggal = $request->datekeg;
if (isset($cari)) {
$infokeg = Infokeg::where('nama_kegiatan', 'like', '%'.$cari.'%')
->paginate(5);
}elseif (isset($caritanggal)) {
$infokeg = Infokeg::where('tanggal_kegiatan', 'like', '%'.$caritanggal.'%')
->paginate(5);
}elseif (isset($cari)&&isset($caritanggal)) {
$infokeg = Infokeg::where('nama_kegiatan', 'like', '%'.$cari.'%')
->orWhere('tanggal_kegiatan', 'like', '%'.$caritanggal.'%')
->paginate(5);
}
return view('/admin/infokeg/infokeg', ['infokeg' => $infokeg]);
}
I want to filter replies based on query parameter passed, query parameters can be post_id, comment_id and array of reply_ids all can be optional and can be used as combination
$query = Post::where('user_id', auth()->id());
if ( isset($data['reply_ids']) ) {
$query = $query->with('posts.comments.replies')->whereHas('posts.comments.replies', function($query) use ($data){
$query->whereIn('id', $data['reply_ids']);
});
}
Now, if I want to filter again with comment authors, that is on comments table, if I want to add filters of post author, that will be on posts table, how I can add those conditional, and still that will be optional?
Just add another if statements below. Those will be optional, sice you define your $query before your first filtering action.
I needed to use another eager loading with so that the query will be build on all the combination selected, so the final code will be something like
$query = Post::where('user_id', auth()->id());
if ( isset($data['reply_ids']) ) {
$query = $query->with('posts.comments.replies')->whereHas('posts.comments.replies', function($query) use ($data){
$query->whereIn('id', $data['reply_ids']);
});
}
$query = $query->with(['posts' => function($query){ $query->where('status', 'pending'); }])
$query->get()
When I query the database I get the results I want.
$data['jobtypes'] = User::Select('jobtype_search', DB::raw('count(jobtype_search) as jobs'))->
Where('jobtype_search', '<>', '')
->GroupBy('jobtype_search')
->get();
However, when I do not want to keep calling the database for every query. Instead I call on the database once to get the chunk of data I need and then query off that.
$user = User::whereBetween('created_at', [$start_date, $end_date])->get();
When I try
$data['jobtype_search'] =$user->Select('jobtype_search', DB::raw('count(jobtype_search) as jobs'))->
Where('jobtype_search', '<>', '')
->GroupBy('jobtype_search')
->get();
I get a method select not found error.
What should I change so my query works?
The $user variable in your example is the result set (a Laravel collection) of the query, but you're trying to use it as a query.
This would work (another query):
$data['jobtype_search'] = User::whereBetween('created_at', [$start_date, $end_date])
->Select('jobtype_search', DB::raw('count(jobtype_search) as jobs'))
->Where('jobtype_search', '<>', '')
->GroupBy('jobtype_search')
->get();
Or if you want to do it on the result set, you could do it with the collection methods on the result set:
$data['jobtype_search'] = $user
->filter(function ($item) {
return $item->jobtype_search !== '';
})
->groupBy('jobtype_search')
->map(function ($item, $jobTypeSearch) {
return [
'jobtype_search' => $jobTypeSearch,
'jobs' => $item->count(),
];
})
I have little problem with my search query at the moment. When i run a search query with only the parameter "comite_id" it's working but when i want to run the search query with "comite_id" and the whereBetween with "date_min" and "date_max" the result is not right , it's seems the result don't care about the whereBetween clause because i don't get the right date range.
Someone knows where i'm doing wrong? thanks a lot in advance
Here my controller :
public function getRetrocession(Request $request){
$comites = Structure::where('type_structure_id' , '=' ,'3')->pluck('nom_structure' , 'id');
$search = $request->input('comite_id');
$dt_min = $request->input('dt_min');
$dt_max = $request->input('dt_max');
if ($search) {
$query = Retrocession::where('comite_id', '=', $search)
->orWhere(function ($q) use($search , $dt_min , $dt_max) {
$q->where('comite_id', '=', $search)
->whereBetween('dt_retrocession', [ $dt_min , $dt_max]);
});
}else {
$query = Retrocession::select();
}
$retrocessions = $query->orderBy('dt_retrocession', 'DESC')->paginate(10)
->appends(['recherche' => $search]);
return view('retrocession/index' , compact('retrocessions' , 'comites'));
}
Because you are using orWhere() it always call both where() and orWhere(); thus including the result of where() and orWhere(). You can try this way
$query = Retrocession::where('comite_id', $search)
->when($dt_min && $dt_max, function($q) use ($dt_min, $dt_max) {
$q->whereBetween('dt_retrocession', [$dt_min, $dt_max]);
});
So you always run the first where, and only include whereBetween() WHEN $dt_min and $dt_max are both true.
Bonne chance Mathieu.