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.
Related
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);
In an app I'm working on there are two main searches: a site wide search and a quick search.
Quick search
The quick search has to take the role, user and department and return all the users that match the criteria. I already see a potential problem in the fact that you could select a role that isn't in a department... but anyway.
This is what I've tried.
public function userSearch(Request $request)
{
$department = $request->get('department');
$role = $request->get('role');
$location = $request->get('location');
$users = User::where('department', $department)
->where('role', $role)
->where('location', $location)
->get();
foreach($users as $user)
{
echo '<br />' . $user->username;
}
}
It gets complicated though as user, role and department are drop down boxes and may not have had anything selected.
So If I search for just Digital as a department the query string is:
http://127.0.0.1:8000/usersearch?department=Digital&role=&location=
Obviously, this doesn't return anything as I'm using multiple where clauses.
Would I have to individually check whether each variable is empty and construct the query? This seems a bit sketchy as I'd have to check every possible order to get the query right.
Site wide search
The other search is a site search that takes one query string, here is my stupidly basic method startings:
public function search(Request $request)
{
$search = $request->get('q');
return view('pages.search.index', compact('search'));
}
I read in the Laravel documentation that there is a package available called Scout but is there a more rudimentary way to just get everything from every model, given the query string?
Things I'd like to return:
Users
Teams
Documents with similar titles
News articles
I have models associated to database tables for all the above so could I just do the following?
users = User::where('name', 'like', '%' . Input::get('name') . '%')
->orWhere('name', 'like', '%' . Input::get('name') . '%')
articles= Article::where('name', 'like', '%' . Input::get('name') . '%')
->orWhere('name', 'like', '%' . Input::get('name') . '%')
and so on...
Then when displaying results just do:
return('nameofview', compact('users', 'articles')
Or is this likely to be slow and cumbersome?
Update
For the site-wide search, for now, I just have:
public function search(Request $request)
{
$search = $request->get('q');
$users = User::where('username', 'like', '%' . $request->get('q') . '%')
->orWhere('displayName', 'like', '%' . $request->get('q') . '%')
->orWhere('email', 'like', '%' . $request->get('q') . '%')
->orWhere('role', 'like', '%' . $request->get('q') . '%')
->orWhere('department', 'like', '%' . $request->get('q') . '%')
->orWhere('location', 'like', '%' . $request->get('q') . '%')
->orWhere('directDialIn', 'like', '%' . $request->get('q') . '%')
->orWhere('mobileNumber', 'like', '%' . $request->get('q') . '%')->get();
return view('pages.search.index', compact('search', 'users'));
}
For the quick search, I added some query scopes
/**
* Scope a query by department
*/
public function scopeByDepartment($query, $department)
{
return $query->where('department', $department);
}
/**
* Scope a query by role
*/
public function scopeByRole($query, $role)
{
return $query->where('role', $role);
}
/**
* Scope a query by location
*/
public function scopeByLocation($query, $location)
{
return $query->where('location', $location);
}
There is a much better way to achieve what you are looking to do using a combination of conditional clauses and scopes. For example...
User::all()->when(isset($request->department), function ($q) use ($request) {
$q->byDepartment($request->department);
})
->when(isset($request->role), function($q) use ($request) {
$q->byRole($request->role);
});
Once you set up your scopes on the model you can now selectively filter by any number of the request variables so you don't have to worry if it is not set. This also keeps your code much more compact.
I have a controller that works on an AJAX jQuery call when I need to search/filter the database:
$launchsitesatellite = DB::table('satellites')
->where(function($q) use ($request) {
if(empty($request->type) && empty($request->rocket_type)) {
$q->orWhere('satname','LIKE','%'.$request->search.'%')
->orWhere('norad_cat_id','LIKE','%'.$request->search.'%')
->orWhere('country','LIKE','%'.$request->search.'%')
->orWhere('object_id','LIKE','%'.$request->search.'%');
} else {
if(!empty($request->type)) {
$q->orWhere($request->type,'LIKE','%'.$request->search.'%');
}
if(!empty($request->object_type)) {
$q->orWhere('object_type','LIKE','%'.$request->object_type.'%');
}
if(!empty($request->launch_year)) {
$q->orWhere('launch','LIKE','%'.$request->launch_year.'%');
}
}
})
->where('site', $site_code)->Paginate(300);
This controller can search/filter my database with no problem. The only thing I would like to fix is to allow multiple filters to be applied. For example, currently when I filter by Object Type and then decide to filter by Country, it resets the Object Type.
What I want to be able to do is to allow it to filter by Object Type AND Country, not only one.
There was a lack of examples/documentation so I could not find any examples of how this is done.
EDIT: JS AJAX Call
$("#filter-type").change(function() {
$value=$(this).val();
$.ajax({
type: "get",
url: "{{$launchsitename->site_code}}",
data: {'search':$value, type:'object_type'},
success: function(data){
$('#launchsatdisplay').html(data);
}
});
});
I think the reason you're having this issue is because you're using orWhere rather than where so in theory the more filters you use the more results you will have returned (rather than limiting the results).
$launchsitesatellite = DB::table('satellites')
->where(function ($q) use ($request) {
if (!$request->has('type') && !$request->has('rocket_type')) {
$q->orWhere('satname', 'LIKE', '%' . $request->search . '%')
->orWhere('norad_cat_id', 'LIKE', '%' . $request->search . '%')
->orWhere('country', 'LIKE', '%' . $request->search . '%')
->orWhere('object_id', 'LIKE', '%' . $request->search . '%');
} else {
if ($request->has('type')) {
$q->where($request->type, 'LIKE', '%' . $request->search . '%');
}
if ($request->has('object_type')) {
$q->where('object_type', 'LIKE', '%' . $request->object_type . '%');
}
if ($request->has('launch_year')) {
$q->where('launch', 'LIKE', '%' . $request->launch_year . '%');
}
}
})
->where('site', $site_code)
->Paginate(300);
Also, just FYI, Laravel Query Builder comes with a when() method which is an alternative to using multiple if statements. So the main else section would look like:
$q
->when($request->has('type'), function ($q) use ($request) {
$q->where($request->type, 'LIKE', '%' . $request->search . '%');
})
->when($request->has('object_type'), function ($q) use ($request) {
$q->where('object_type', 'LIKE', '%' . $request->object_type . '%');
})
->when($request->has('launch_year'), function ($q) use ($request) {
$q->where('launch', 'LIKE', '%' . $request->launch_year . '%');
});
Obviously, you don't have to do this though (I just thought I'd mention it).
Hope this helps!
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.
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