I have an advanced search form to filter out results from a database using Laravel. The data is filtered correctly but I have a requirement for the user to be able to filter by first name or last name using the same text box (in the advanced form). I tried orWhere to make sure it filters the name field with the first name or last name but the orWhere doesn't consider the other filters. The code I am using is as follows:
DB::table('mytable')
->where(function($query) use ($name, $degree_s, $specialty_s, $city_s, $state_s, $lundbeck_id_s) {
if ($name)
$query->where('first_name', 'like', "$name%")->orWhere('last_name', 'like', "$name%"); # this is whats causing the issue
if ($specialty_s)
$query->where('primary_specialty', $specialty_s);
if ($city_s)
$query->where('city', $city_s);
if ($state_s)
$query->where('state_province', $state_s);
if ($lundbeck_id_s)
$query->where('customer_master_id', $lundbeck_id_s);
if ($degree_s)
$query->where('primary_degree', $degree_s);
})
->select('id', 'first_name','last_name')
Adding the orWhere clause causes the query to not use the other conditions as well (like city_s or state_s).
You need to change:
if ($name)
$query->where('first_name', 'like', "$name%")->orWhere('last_name', 'like', "$name%");
into:
if ($name) {
$query->where(function($q) use ($name) {
$q->where('first_name', 'like', "$name%")->orWhere('last_name', 'like', "$name%");
});
}
to make Laravel to add parentheses so it will work as you expect.
EDIT
Of course you don't need to wrap everything with closure here, so the best solution for that would be:
<?php
$query = DB::table('mytable')->select('id', 'first_name', 'last_name');
if ($name) {
$query->where(function ($q) use ($name) {
$q->where('first_name', 'like', "$name%")
->orWhere('last_name', 'like', "$name%");
});
}
if ($specialty_s) {
$query->where('primary_specialty', $specialty_s);
}
if ($city_s) {
$query->where('city', $city_s);
}
if ($state_s) {
$query->where('state_province', $state_s);
}
if ($lundbeck_id_s) {
$query->where('customer_master_id', $lundbeck_id_s);
}
if ($degree_s) {
$query->where('primary_degree', $degree_s);
}
$data = $query->get();
i will build the query little bit differently.
$q = DB::table('mytable')->select(['id', 'first_name', 'last_name']);
if(!empty($name))
{
$q->where(function($query)use($name){
$query->where(('first_name', 'like', "$name%")
->orWhere('last_name', 'like', "$name%");
});
}
if(!empty($specialty_s) $q->where('primary_specialty', $specialty_s);
so far.... so forth.
at last
return q->get() or $q->paginate(30) depending upon your needs.
Related
I need to prevent some specific searches like a username.
the scenario is when I search auth username I get all friends but if I search auth username I don't want to search result,
here's my query
$searchVal = $request->input('search');
$friend_data = Friend::with('getAccept', 'getRequest')->where('status', '1')->where(static function ($q) use ($user) {
$q->where('user_id', $user->id)->orWhere('ref_id', $user->id);
})->where(function ($q1) use ($searchVal) {
if($searchVal) {
$q1->whereHas('getRequest', function ($q) use ($searchVal) {
$q->where('username', 'LIKE', '%' . $searchVal . '%');
});
$q1->orWhereHas('getAccept', function ($q) use ($searchVal) {
$q->where('username', 'LIKE', '%' . $searchVal . '%');
});
}
})->get();
Thanks in Advance.
Just replace if($searchVal) in your where function with if($searchVal !== Auth::user()->username) and that should exclude the auth username results.
Im trying to figure out why my query is ignoring everything except the title and the description. The search button leading to the controller, is for filtering different type of ads , by category, by region, by price.
For example if now i search for existing ad and its found by title / keyword -> will always show, even if i choose a different region / category/ price range
Im trying to use something that will save me a lot of if statements to check if they exist in the request. Maybe other option si to use https://github.com/mohammad-fouladgar/eloquent-builder to build my query
public function index(Request $request)
{
$keyword = $request['keyword'];
$category_id = $request['category_id'];
$type_id = $request['type_id'];
$region_id = $request['region_id'];
$min_price = $request['min_price'];
$max_price = $request['max_price'];
$result = Ad::when($keyword, function ($q) use ($keyword) {
return $q->where('title', 'like', '%' . $keyword . '%')->orWhere('description', 'like', '%' . $keyword . '%');
})
->when($category_id, function ($q) use ($category_id) {
return $q->where('category_id', $category_id);
})
->when($region_id, function ($q) use ($region_id) {
return $q->where('region_id', '=', $region_id);
})
->when($type_id, function ($q) use ($type_id) {
return $q->where('adtype_id', '=', $type_id);
})
->when($min_price, function ($q) use ($min_price) {
return $q->where('price', '>=', $min_price);
})
->when($max_price, function ($q) use ($max_price) {
return $q->where('price', '<=', $max_price);
})
->paginate(8);
My get param url looks like that:
search?keyword=&category_id=0®ion_id=0&type_id=0&min_price=&max_price=
The produced query in mysql when i search for existing ad by its name and i look for a different category is:
select * from `ads` where `title` like '%test test%' or `description` like '%test test%' and `category_id` = '2' limit 8 offset 0
The ad is found, but the actual category is 1, not 2, same for all others optimal parameters.
You can edit your query to look for specific relations, using whereHas. This method will allow you to add customized constraints to a relationship constraint, such as checking the content of a comment.And to check max/min price, use where method. So, you can use it like this:
$result = Ad::when($keyword, function ($q) use ($keyword) {
return $q->where('title', 'like', '%' . $keyword . '%')->orWhere('description', 'like', '%' . $keyword . '%');
})
->whereHas('category_relation_name', function ($q) use ($category_id) {
return $q->where('category_id', $category_id);
})
->whereHas('region_relation_name', function ($q) use ($region_id) {
return $q->where('region_id', $region_id);
})
->whereHas('type_relation_name', function ($q) use ($type_id) {
return $q->where('adtype_id', $type_id);
})
->where('price', '>=', $min_price);
->where('price', '<=', $max_price);
->paginate(8);
So I'm making a fliter in laravel for a project and me and my teacher are braking our head on a the following thing.
In the code below the general search for a player works but the other statements won't add to it if they are defined and in the POST request;
Controller:
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Input;
class FilterController extends Controller
{
public function filter(Request $request)
{
$player = new \App\Player;
$filters = $player->newQuery();
$query = Input::get('q');
// Search for a player based on their status.
if ($request->has('status')) {
$filters->orwhere('status', $request->input('status'));
}
// Search for a player player on their club.
if ($request->has('club')) {
$filters->orwhere('Club', $request->input('club'));
}
// Search for a player player on their team category .
if ($request->has('Category')) {
$filters->orwhere('Category', $request->input('Category'));
}
// Search for a player player if he is flagged as removed.
if ($request->has('remove')) {
$filters->orwhere('remove', $request->input('remove'));
}
// Search for a player player on their size.
if ($request->has('size')) {
$filters->orwhere('Size', $request->input('size'));
}
// General search for a player
if($request->has('q')){
$filters->orwhere('first_name','LIKE','%'.$query.'%')
->orWhere('last_name','LIKE','%'.$query.'%')
->orWhere('mobile','LIKE','%'.$query.'%')
->orWhere('street_name_nummer','LIKE','%'.$query.'%')
->orWhere('city','LIKE','%'.$query.'%');
}
// Get the results and return them.
$results = $filters->get();
if(count($results) > 0){
return view('lists/ekick')->withDetails($results,$query);
} else return view ('lists/ekick')->with('No Details found. Try to search again !');
}
}
route:
Route::any('lists/ekick', 'FilterController#filter');
output view:
img from view
To pick up on Aaron Sarays answer, you are most likely filtering the wrong way. Normally additional filters are additional conditions each record has to meet in order to be part of the result. If you consider an Excel table and you filter one column, you won't even have all options to filter for in the second column because you already limited the result and you can only limit it further.
Combine this knowledge with an improved way of filtering and you receive a query like this:
public function filter(Request $request)
{
$query = $request->input('q');
$results = \App\Player::query()
->when($request->input('status'), function ($query, $status) {
$query->where('status', $status);
})
->when($request->input('club'), function ($query, $club) {
$query->where('club', $club);
})
->when($request->input('category'), function ($query, $category) {
$query->where('category', $category);
})
->when($request->input('remove'), function ($query, $remove) {
$query->where('remove', $remove);
})
->when($request->input('size'), function ($query, $size) {
$query->where('size', $size);
})
->when($query, function ($query, $q) {
$query->where(function ($query) use ($q) {
$query->where('first_name', 'LIKE', "%$q%")
->orWhere('last_name', 'LIKE', "%$q%")
->orWhere('mobile', 'LIKE', "%$q%")
->orWhere('street_name_number', 'LIKE', "%$q%")
->orWhere('city', 'LIKE', "%$q%");
});
})
->get();
if ($results->isNotEmpty()) {
return view('lists/ekick')->withDetails($results, $query);
} else {
return view ('lists/ekick')->with('No Details found. Try to search again !');
}
}
The function when($condition, $callback) as used in the query above is used to dynamically build queries. You can consider the following two statements equivalent:
// option 1: conditional query (preferred!)
$results = Player::query()
->when($request->input('q'), function ($query, $q) {
$query->where('name', 'LIKE', "%$q%");
})
->get();
// option 2: plain php query building... (not very clean code)
$query = Player::query();
if ($request->input('q')) {
$query->where('name', 'LIKE', '%'.$request->input('q').'%');
}
$results = $query->get();
In order to do what you're doing, I think you want to not use or with your queries. You're basically saying
Give me the Player where status is something or size is something
I think what you mean to say is
Give me the Player where status is something and size is something
Depending on if the requirements exist or not in the filter.
So, you'd want to alter your code using the following as an example:
if ($request->has('status')) {
$filters->where('status', $request->input('status'));
}
// Search for a player player on their club.
if ($request->has('club')) {
$filters->where('Club', $request->input('club'));
}
You can also bypass one step by using this:
$query = \App\Player::getQuery();
I have built a multi filter search for my website but I cant seem to find any documentation on multiple if statements inside of where for my search.
Returns Lots of Results
$data = Scrapper::paginate(15);
Returns none.. need it to be this way to have where statements with IF see bellow.
$database = new Scrapper;
$database->get();
Example of what I want to do..
$database = new Scrapper;
if (isset($_GET['cat-id'])) {
$database->where('cat_id', '=', $_GET['cat-id']);
}
if (isset($_GET['band'])) {
$database->where('price', 'BETWEEN', $high, 'AND', $low);
}
if (isset($_GET['search'])) {
$database->where('title', 'LIKE', '%'.$search.'%');
}
$database->get();
Very similar to this: Method Chaining based on condition
You are not storing each query chains.
$query = Scrapper::query();
if (Input::has('cat-id')) {
$query = $query->where('cat_id', '=', Input::get('cat-id'));
}
if (Input::has('band')) {
$query = $query->whereBetween('price', [$high, $low]);
}
if (Input::has('search')) {
$query = $query->where('title', 'LIKE', '%' . Input::get($search) .'%');
}
// Get the results
// After this call, it is now an Eloquent model
$scrapper = $query->get();
var_dump($scrapper);
Old question but new logic :)
You can use Eloquent when() conditional method:
Scrapper::query()
->when(Input::has('cat-id'), function ($query) {
$query->where('cat_id', Input::get('cat-id'));
})
->when(Input::has('band'), function ($query) use ($hight, $low) {
$query->whereBetween('price', [$high, $low]);
})
->when(Input::has('search'), function ($query) {
$query->where('title', 'LIKE', '%' . Input::get('search') .'%');
})
->get();
More information at https://laravel.com/docs/5.5/queries#conditional-clauses
I'm trying to search two optional tables using eloquent:
$users = User::where('ProfileType', '=', 2)
->where(function($query) {
$query->where('BandName', 'LIKE', "%$artist%");
$query->or_where('Genre', 'LIKE', "%$genre%");
})->get();
This works fine for return all results when a user does an empty search, but I am not sure how to adjust this for to search for bandname when that is present and vise versa.
Just to explain what happens on answer below:
Eloquent does a tricky thing here: When you call User::where(...) it returns a Database\ Query object. This is basically the same thing as DB::table('users')->where(...), a chainable object for constructing SQL queries.
So having:
// Instantiates a Query object
$query = User::where('ProfileType', '=', '2');
$query->where(function($query) {
// Adds a clause to the query
if ($artist = Input::get('artist')) {
$query->where_nested('BandName', 'LIKE', "%$artist%", 'OR');
}
// And another
if ($genre = Input::get('genre')) {
$query->where_nested('Genre', 'LIKE', "%$genre%", 'OR');
}
});
// Executes the query and fetches it's results
$users = $query->get();
Building on Vinicius' answer here's what worked:
// Instantiates a Query object
$query = User::where('ProfileType', '=', '2');
// Adds a clause to the query
if ($artist = Input::get('artist')) {
$query->where('BandName', 'LIKE', "%$artist%");
// Temp Usernamesearch
$query->or_where('NickName', 'LIKE', "%$artist%");
}
// Genre - switch function if artist is not empty
if ($genre = Input::get('genre')) {
$func = ($artist) ? 'or_where' : 'where';
$query->$func('Genre', 'LIKE', "%$genre%");
}
// Executes the query and fetches it's results
$users = $query->get();
Turns out that the second optional field must use or_where only if $artist is not set.
Thanks for your help
I think this is what youre after. Your view would have a form to search artist/genre one or the other can be set, or both, or none.
$users = User::where('ProfileType', '=', 2);
if (Input::has('artist')) {
$users = $users->where('BandName', 'LIKE', '%'.Input::get('artist').'%');
}
if (Input::has('genre')) {
$users = $users->where('Genre', 'LIKE', '%'.Input::get('genre').'%');
}
$users = $users->get();
$query = FormEntry::with('form')->where('domain_id', $id);
$query->where(function($query) use ($search, $start, $limit, $order, $dir) {
$query->where('first_name', 'LIKE', "%{$search}%")
->orWhere('last_name', 'LIKE', "%{$search}%")
->orWhere('email', 'LIKE', "%{$search}%")
->offset($start)
->limit($limit)
->orderBy($order, $dir);
});
$entries = $query->get();
$totalFiltered = $query->count();