laravel search multiple keywords - laravel

I have a problem with search form on my website. Basically, when user will type multiple keywords to search form (e.g. business card ) then search result will show all images from keyword 1 (e.g. business) and all images from keyword2 (e.g. card). This is bad, the search form is not relevant at all. Can you please look at the code down bellow and help me fix it so the search form will show only images with both keywords together (keyword1 + AND + keyword2).
public function search($search, $category = null, $timeframe = null)
{
$extends = explode(' ', $search);
if ($category) {
$categoryId = $this->category->whereSlug($category)->first();
}
$images = $this->posts($category, $timeframe)->where('title', 'LIKE', '%' . $search . '%')
->orWhere('tags', 'LIKE', '%' . $search . '%')
->whereNull('deleted_at')->whereNotNull('approved_at')->orderBy('approved_at', 'desc');
foreach ($extends as $extend) {
if (isset($categoryId)) {
$images->whereCategoryId($categoryId)->Where('tags', 'LIKE', '%' . $extend . '%')->whereNotNull('approved_at')->whereNull('deleted_at')
->whereCategoryId($categoryId)->orWhere('title', 'LIKE', '%' . $search . '%')->whereNotNull('approved_at')->whereNull('deleted_at')
->whereCategoryId($categoryId)->orWhere('image_description', 'LIKE', '%' . $search . '%')->whereNotNull('approved_at')->whereNull('deleted_at');
} else {
$images->orWhere('tags', 'LIKE', '%' . $extend . '%')->whereNotNull('approved_at')->whereNull('deleted_at')
->orWhere('title', 'LIKE', '%' . $search . '%')->whereNotNull('approved_at')->whereNull('deleted_at')
->orWhere('image_description', 'LIKE', '%' . $search . '%')->whereNotNull('approved_at')->whereNull('deleted_at');
}
}
return $images = $images->with('user', 'comments', 'favorites')->whereNotNull('approved_at')->whereNull('deleted_at')->paginate(perPage());
}

When you use the % sign before and after the search query, you say "give me anything with that items", if you want your system to search and give results exactly as per what the user has entered, you should use only the key phrase. try the code below.
public function search($search, $category = null, $timeframe = null)
{
$extends = explode(' ', $search);
if ($category) {
$categoryId = $this->category->whereSlug($category)->first();
}
$images = $this->posts($category, $timeframe)
->where('title', 'LIKE', "$search")
->orWhere('tags', 'LIKE', "$search")
->whereNull('deleted_at')
->whereNotNull('approved_at')
->orderBy('approved_at', 'desc');
foreach ($extends as $extend) {
if (isset($categoryId)) {
$images->whereCategoryId($categoryId)->Where('tags', 'LIKE', "$search")
->whereNotNull('approved_at')->whereNull('deleted_at')
->whereCategoryId($categoryId)->orWhere('title', 'LIKE', "$search")
->whereNotNull('approved_at')->whereNull('deleted_at')
->whereCategoryId($categoryId)
->orWhere('image_description', 'LIKE', "$search")
->whereNotNull('approved_at')->whereNull('deleted_at');
}
else {
$images->orWhere('tags', 'LIKE', "$extend")
->whereNotNull('approved_at')->whereNull('deleted_at')
->orWhere('title', 'LIKE', "$search")
->whereNotNull('approved_at')->whereNull('deleted_at')
->orWhere('image_description', 'LIKE', "$search")
->whereNotNull('approved_at')->whereNull('deleted_at');
}
}
return $images = $images->with('user', 'comments', 'favorites')
->whereNotNull('approved_at')
->whereNull('deleted_at')
->paginate(perPage());
}

Related

searching on name instead of id on sql

I have search input in my products page. I can search on name on description and on category if I type the id but that's not really practical how i change this sql so i can search on the name of the category instead of the id.
DB i have Products | name,description,category_id
Categories | id,name
public function scopeFilter($query,array $filters){
if ($filters['search'] ?? false){
$query
->where('name', 'like', '%' . request('search') . '%')
->orWhere('description', 'like', '%' . request('search') . '%')
->orWhere('category_id', 'like', '%' . request('search'). '%');
}
}
Since the category is a related model search on the relationship:
public function scopeFilter($query,array $filters){
if ($filters['search'] ?? false){
$query
->where('name', 'like', '%' . request('search') . '%')
->orWhere('description', 'like', '%' . request('search') . '%')
->orWhereHas('category', function ($q) {
$q->where('name','like', '%' . request('search'). '%'
});
}
}
This is assuming you have defined your relationship in your model.
Since the category is a related model search on the relationship AND I suggest using this code: ‌
public function scopeFilter($query,array $filters) {
if ($filters['search'] ?? false){
return $query->where('name', 'like', '%' . request('search') . '%')
->orWhere('description', 'like', '%' . request('search') . '%')
->orWhereHas('category', function ($q) {
$q->where('name','like', '%' . request('search'). '%');
});
}
return $query;
}

Laravel Eloquent add 'where' clause in the query by condition

I want to add a condition first before adding another where query it but seems that laravel won't allow. I want something like the following.
function index()
{
$role = Auth::user()->role; //SEE_ALL, SEE_DEPT_A, SEE_DEPT_B
$q = Input::get('q');
if ($q != "") {
$user = User::where('name', 'LIKE', '%' . $q . '%')
->orWhere('email', 'LIKE', '%' . $q . '%')
->orderBy('name');
if ($role == "SEE_DEPT_A") {
$user->where('user_department', "A");
}
$user->paginate(10)->appends('q', $q);
}
return view('users.index')->with('data', ['users' => $user, 'q' => $q]);
}
You should use the when() function :
$user = User::where('name', 'LIKE', '%' . $q . '%')
->orWhere('email', 'LIKE', '%' . $q . '%')
->orderBy('name')
->when($role == "SEE_DEPT_A", function($query){
return $query->where('user_department', "A");
})->paginate(10)->appends('q', $q);
You need to assign the statement where you used where clause:
if ($role == "SEE_DEPT_A") {
$user = $user->where('user_department', "A");
}
And if the if statement does not run (in case of false), it will throw an error about $user being undefined
You can insert multi conditions like this:
$user_model = User::where('name', 'LIKE', '%' . $q . '%')
->orWhere('email', 'LIKE', '%' . $q . '%')
->orderBy('name');
if ($role == "SEE_DEPT_A") {
$user_model = $user_model->where('user_department', "A");
}
...
//other if statements
...
$users = $user_model->paginate(10)->appends('q', $q);

How To Get Search Query From Multiple Columns in Database

I have search form to get information from table named books.
Right now i'm using this controller
public function search(Request $request)
{
$keyword = $request->input('keyword');
$query = Book::where('judul', 'LIKE', '%' . $keyword . '%');
$book_list = $query->paginate(5);
$pagination = $book_list->appends($request->except('page'));
$total_book = $book_list->total();
return view('dashboards.index', compact('book_list', 'keyword', 'pagination', 'total_book'));
}
The problem is the data that i get from the request only available for judul. it just show empty result if the input keyword search addressed to search writter or publisher
I want the search form able to get data from other columns named writters and publisher
Is there any method to get data from multiple column?
You can use orwhere to fullfill this, like this
Book::where(function ($query) use($keyword) {
$query->where('judul', 'like', '%' . $keyword . '%')
->orWhere('writters', 'like', '%' . $keyword . '%');
})
->get();
I hope it helps you.
You can execute conditional queries in many ways.
1. You can use when():
Book::when($keyword, function ($q) use ($keyword) {
return $q->where('judul', 'LIKE', '%' . $keyword . '%');;
})
->get();
2. Use the where closure:
Book::where(function($q) use ($keyword, $request) {
if ($request) {
$q->where('judul', 'LIKE', '%' . $keyword . '%');
}
})
->get();
3. Do this:
$books = Book::query();
if ($request) {
$books = $books->where('judul', 'LIKE', '%' . $keyword . '%');
}
$books = $books->get();

Laravel sort model by one to many relationship

I have two models Location and Danger
Danger has two fields location_id and user_id it simply save users report about locations
btw Danger has a one to many relation with Location
the question is
how can I sort locations with count of it's danger in a search form
here is my form:
$locations = Location::latest();
if ($request->get('q')) {
$q = $request->get('q');
$locations->where('desc', 'like', '%' . $q . '%')
->orWhere('name', 'like', '%' . $q . '%');
}
$locations=$locations->paginate(12);
return view('list')->with(compact('locations'));
If your location has many danger and your relation is named dangers then you can use withCount() for sorting as:
$locations = Location::withCount('dangers');
if ($request->get('q')) {
$q = $request->get('q');
$locations->where('desc', 'like', '%' . $q . '%')
->orWhere('name', 'like', '%' . $q . '%');
}
$locations->orderBy('dangers_count', 'desc')
$locations=$locations->paginate(12);
this might work.
$locations = Location::latest();
if ($request->get('q')) {
$q = $request->get('q');
$locations->where('desc', 'like', '%' . $q . '%')
->orWhere('name', 'like', '%' . $q . '%');
$locations->sortBy(function($item, $key){
return $location->danger()->count();
})
}
$locations=$locations->paginate(12);
return view('list')->with(compact('locations'));

Laravel eloquent search on fields of related model

I have an eloquent models as,
User : users(id, username, password, email, status)
Profile : profiles(id, user_id, first_name, last_name, gender, dob)
In the controller logic, I am eagerly loading the Profile model.
I can do this,
$user = User::with('Profile')->get();
or
$user = User::with('Profile')->where('status', '1')->get();
but how to do something like,
$user = User::with('Profile')->where('status', '1')->where('gender', 'Male')->get();
That's where whereHas comes in handy:
$user = User::with('Profile')->where('status', 1)->whereHas('Profile', function($q){
$q->where('gender', 'Male');
})->get();
Basically it adds the condition that the user needs to have a profile with gender = Male
If you want to search multiple columns in relation model.
$searchText = 'test text';
Product::with('owner')->where(function($query) use ($searchText)
{
$query->where('product_name', 'LIKE', '%' . $searchText . '%');
$columns = ['product_code', 'place_location', 'remark'];
foreach ($columns as $column ) {
$query->orWhere($column, 'LIKE', '%' . $searchText . '%');
}
$query->orWhereHas('owner', function($q) use ($searchText) {
$q->where(function($q) use ($searchText) {
$q->where('name', 'LIKE', '%' . $searchText . '%');
$q->orWhere('company_name', 'LIKE', '%' . $searchText . '%');
});
});
});
Let's say you've multiple relations
and you want to search records based on multiple relational columns value
User::with('associate')
->where('name', 'like', '%' . $input . '%')
->orWhere(function ($query) use ($input) {
$query->whereHas('associate', function ($q) use ($input) {
$q->where('first_name', 'like', '%' . $input . '%');
});
})
->orWhere(function ($query) use ($input) {
$query->with('roles')->whereHas('roles', function ($q) use ($input) {
$q->where('display_name', 'like', '%' . $input . '%');
});
})
->get();
Suppose, Your search input field name is q.
function name(Request $request){
$query = User::select();
if($request->q && $request->q !=''){
// if you search
$keyword = $request->q;
$query = User::with('Profile')->whereHas('Profile', function($q) use
($keyword){
$q->where('gender', 'like', "%{$keyword}%" );
});
}
$query->latest('id')->paginate();
}

Resources