I'm feeling stuck. :(
I want to be able to execute different SQL query, depending on the selected filters in my form:
//My initial query without any filters is this:
$dbQuery="SELECT * FROM \"interactions\" WHERE \"user_id\" = ".Auth::user()->getAttribute('id');
//Then depending on the selected filters the query may be any combination of the following:
if (request('contact_id')) $dbQuery.=" AND \"contact_id\" = ".request('contact_id');
if (request('product_id')) $dbQuery.=" AND \"product_id\" = ".request('product_id');
if (request('type')) $dbQuery.=" AND \"type\" LIKE \"%".request('type')."%\"";
if (request('description')) $dbQuery.=" AND \"description\" LIKE \"%".request('description')."%\"";
if (request('date')) $dbQuery.=" AND \"date\" >= ".request('date');
I have a class called "Interaction" which extends the Eloquent model and I need to be able to execute the above query or represent the same logic through it.
Any ideas on how I can achieve that will be greatly appreciated!
EDIT:
Thanks to Brice (my personal hero today), here is what did the trick for me:
$query = Interaction::where('user_id', Auth::id());
$contact_id = request('contact_id');
$product_id = request('product_id');
$type = request('type');
$description = request('description');
$date = request('date');
if ($contact_id) $query->where('contact_id', $contact_id);
if ($product_id) $query->where('product_id', $product_id);
if ($type) $query->where('type', 'like', "%".$type."%");
if ($description) $query->where('description', 'like', "%".$description."%");
if ($date) $query->where('date', '>=', $date);
$interactions = $query->get();
return view('interactions.index',compact('interactions'));
I'd recommend using the eloquent query builder for this.
For example:
$query = Interaction::where('user_id', Auth::id());
$contact_id = request('contact_id');
$product_id = request('product_id');
$type = request('type');
$description = request('description');
$date = request('date');
if ($contact_id) {
$query->where('contact_id', $contact_id);
}
if ($product_id) {
$query->where('product_id', $product_id);
}
if ($type) {
$query->where('type', 'like', "%$type%");
}
if ($description) {
$query->where('type', 'like', "%$description%");
}
if ($date) {
$query->where('date', '>=', \Carbon\Carbon::parse($date));
}
$results = $query->get();
If you have a lot of results, you may want to use pagination instead of fetching all results at the same time as shown above.
You can use ->when() method docs
$results = Interaction::where('user_id', Auth::id())
->when($contact_id, function ($query) use ($contact_id) {
$query->where('contact_id', $contact_id);
})
->when($product_id, function ($query) use ($product_id) {
$query->where('product_id', $product_id);
})
->when($type, function ($query) use ($type) {
$query->where('type', 'like', "%$type%");
})
->when($description, function ($query) use ($description) {
$query->where('type', 'like', "%$description%");
})
->when($date, function ($query) use ($date) {
$query->where('date', '>=', \Carbon\Carbon::parse($date));
})->get();;
Related
I have a database with these parameters and I'd like to filter search them, it has been working until I added "race" and "dealer experience" and I can't for the life of me figure out why.
dealer_experience is a string, but I don't think that would make a difference ?
Here is my controller code: ` public function index(Request $request){
$title = $request->get('title');
$type = $request->get('type');
$category = $request->get('category_id');
$province = $request->get('province');
$brand= $request->get('brand_id');
$address = $request->get('address');
$race = $request->get('race');
$dealer_experience = $request->get('dealer_experience');
if($title||$type||$category||$address||$brand||$race||$dealer_experience) {
$candidates = Profile::query();
if ($title) {
$candidates = $candidates->where('title','LIKE','%'.$title.'%');
}
if ($category) {
$candidates = $candidates->where('category_id',$category);
}
if ($brand) {
$candidates = $candidates->where('brand_id',$brand);
}
if ($type) {
$candidates = $candidates->where('type',$type);
}
if ($address) {
$candidates = $candidates->where('address','LIKE','%'.$address.'%');
}
if ($race ) {
$race = $race ->where('race',$race);
}
if ($dealer_experience) {
$dealer_experience = $dealer_experience->where('dealer_experience',$dealer_experience);
}
$candidates = $candidates->where('profile_status',1)->paginate(5);
return view('profile.allcandidates',compact('candidates'));
}
else
{
$candidates= Profile::latest()->where('profile_status',1)->paginate(2);
return view('profile.allcandidates',compact('candidates'));
}
}
}`
Any and all help would be appreciated, thank you
Change
if ($race ) {
$race = $race ->where('race',$race);
}
if ($dealer_experience) {
$dealer_experience = $dealer_experience->where('dealer_experience',$dealer_experience);
}
to
if ($race ) {
$candidates = $candidates ->where('race',$race);
}
if ($dealer_experience) {
$candidates = $candidates ->where('dealer_experience',$dealer_experience);
}
Reason, you still want to filter the candidates
You are not filtering $candidates. Also you could do it nicer and more readable by using the when() method.
$candidates = Profile::where('profile_status',1)
->when($request->has('title'), function($query) use ($request){
$query->where('title', 'LIKE', '%'.$request->title.'%');
})
->when($request->has('type'), function($query) use ($request){
$query->where('type', $request->type);
})
->when($request->has('category_id'), function($query) use ($request){
$query->where('category_id', $request-category_id);
})
->when($request->has('brand_id'), function($query) use ($request){
$query->where('brand_id', $request->brand_id);
})
->when($request->has('address'), function($query) use ($request){
$query->where('address', 'LIKE', '%'.$request->address.'%');
})
->when($request->has('race'), function($query) use ($request){
$query->where('race', $request->race);
})
->when($request->has('dealer_experience'), function($query) use ($request){
$query->where('dealer_experience', $request->dealer_experience);
});
if ($request->hasAny(['title', 'type', 'category', 'address', 'brand', 'race', 'dealer_experience'])) {
$candidates = $candidates->paginate(5);
} else {
$candidates = $candidates->latest()->paginate(2);
}
return view('profile.allcandidates',compact('candidates'));
im did a query for brand of car and the model but when i did added a
query to price range (whereBetwen) its not working
public function indexBrowse(Request $request)
{
$brand=$request->get('searchbrand');
$model=$request->get('searchmodel');
$searchtype=$request->get('searchtype');
$from=$request->get('pricefrom');
$to=$request->get('priecto');
$cars=car::where('brand', 'like', '%'.$brand.'%')
->where(function ($query) use ($model) {
$query->where('model','like','%'.$model.'%');
})->where(function ($query2) use ($from,$to) {
$query2->car::whereBetween('price',['%'.$from.'%','%'.$to.'%']);
})->get();
dd($cars);
$success = 'Results Car';
return view('cars.index', compact('cars', 'success'));
}
Something like this if you want to perform all these where with and condition.
car::where('brand', 'like', '%'.$brand.'%')
->where('model','like','%'.$model.'%')
->whereBetween('price'['%'.$from.'%','%'.$to.'%'])->get();
Have a query, how I can filter results by translation relation (by name column)
$item = Cart::select('product_id','quantity')
->with(['product.translation:product_id,name','product.manufacturer:id,name'])
->where($cartWhere)
->get();
my model
Cart.php
public function product($language = null)
{
return $this->hasOne('App\Models\Product','id','product_id');
}
Product.php
public function translations()
{
return $this->hasMany('App\Models\ProductTranslation','product_id','id');
}
Update v1.0
do like this, but query takes too long time
$item = Cart::select('product_id','quantity')
->with(['product.translation', 'product.manufacturer:id,name'])
->where($cartWhere)
->when($search,function ($q) use ($search) {
$q->whereHas('product.translation', function (Builder $query) use ($search) {
$query->where('name', 'like', '%'.$search.'%');
$query->select('name');
});
}
)
->get() ;
Inside the array within your with() method, you can pass a function as a value.
Cart::select('product_id','quantity')
->with([
'product', function($query) {
$query->where($filteringAndConditionsHere);
}
]);
https://laravel.com/docs/7.x/eloquent-relationships#eager-loading
I am using the laraval model to query results from several tables. Now I do have this function:
public function index(Request $request)
{
$roles = Roles::withcount('permissions')
->withcount('users')
->orderBy('name')
->get();
return view('UserManagement::roles.overview', compact('roles'));
}
$request is filled with the filter I want to append. But how to set a filter including pagination as I can't append the Roles with ->paginate()
Maybe somebody can help me on this one?
Thanks to Luis for pointing me to the right direction:
$search = $request->has('search') ? $request->search : null;
$roles = Roles::withcount('permissions')
->withcount('users')
->when($search, function ($query, $search) {
return $query->where('slug', 'like', '%' . $search . '%');
})
->orderBy('name')
->paginate(20);
you need to use a conditional clause
$roles = Roles::withcount('permissions')
->withcount('users')
->when($request->field_you_want_to_filter, function ($query, $request) {
return $query->where('field_you_want_to_filter', $request->field_you_want_to_filter);
})
->orderBy('name')
->paginate(20);
This is my first attempt to build a search service. The problem is that the code I have looks very untidy, which will probably lead to other problems in the future. Here is what I have written so far:
<?php namespace Acme\Services\Search;
use Product, Brand;
class ProductSearchService {
public function search($data = array()) {
$limit = 10;
$query = isset($data) ? $data : "";
$baseQuery = Product::take($limit);
$brand = Brand::where('name', 'LIKE', '%'.$query.'%')->first();
if($query) {
if (!empty($brand)) {
return $baseQuery
->where('name', 'LIKE', '%'.$query.'%')
->orWhere('description', 'LIKE', '%'.$query.'%')
->orWhere('brand_id', 'LIKE', '%'.$brand->id.'%')->get();
}
return $baseQuery
->where('name', 'LIKE', '%'.$query.'%')
->orWhere('description', 'LIKE', '%'.$query.'%')->get();
}
}
}
How should I structure this service so that it will be cleaner and return more accurate results?
Solution
The answers posted here were very helpful but I found another solution to this.
I used eager loading to reduce the number of queries and declared a base query, like so:
$products = Product::with('brand')
->where('name','LIKE','%'.$term.'%');
while then I have used the orWhereHas method to search for any associated brands, like so:
$products->orWhereHas('brand', function($q) use ($term) {
$q->where('name', 'like', '%'.$term.'%');
});
and then return $products->get()
Here's my attempt
<?php namespace Acme\Services\Search;
use Product, Brand;
class ProductSearchService {
public function search($query) {
$limit = 10;
$brand = Brand::where('name', 'LIKE', '%'.$query.'%')->first();
$baseQuery = Product::take($limit)
->where('name', 'LIKE', '%'.$query.'%')
->orWhere('description', 'LIKE', '%'.$query.'%');
if (!empty($brand))
{
$baseQuery = $baseQuery->orWhere('brand_id', 'LIKE', '%'.$brand->id.'%')->get();
}
return $baseQuery->get();
}
}
Rewrote it for you, please note that this is not perfect yet, also using LIKE for the brand_id isn't really a smart idea as an id is unique! This also means that searching for the name and description isn't needed either. You should just search on id when you got the id, if not, execute the 2 LIKE queries.
<?php
namespace Acme\Services\Search;
use Product, Brand;
class ProductSearchService {
public function search($data = array()) {
$limit = 10;
$query = isset($data) ? $data : "";
$baseQuery = Product::take($limit);
$brand = Brand::where('name', 'LIKE', '%'.$query.'%')->first();
$brandId = !empty($brand) ? $brand->id : "";
return $baseQuery->where('name', 'LIKE', '%'.$query.'%')
->orWhere('description', 'LIKE', '%'.$query.'%')
->orWhere('brand_id', 'LIKE', '%'.$brand_id.'%')->get();
}
}
?>