How to assemble a query with various optional parameters in Laravel? - php

I have a research to do in a database. Not always I'll be using all of parameters. The user may want to research for a name, but not address or the other way around.
I've tried to use advanced wheres and even unions, but none seems to work. All of them give me a SQL error "General error: 1221 Incorrect usage of UNION and ORDER BY".
Here's a piece of code I've tried
$city_name = ($city_name != null) ? DB::table('cities')->where('name', 'LIKE', "%$city_name%") : DB::table('cities');
$state = ($state_id != '--') ? DB::table('cities')->where('state_id', '=', $state_id) : DB::table('cities');
$cities = DB::table('cities')->union($city_name)->union($state)->orderBy('name')->get();
But it gives me the above described error.
What I really want to do is to select, dinamically, what parameters I put in the query and even assemble it "on the fly". Does anyone knows how to do that?
If I couldn't make myself clear, please let me know in the comments...

I think you need somethink like this:
$query = DB::table('cities');
if ($city_name != null)
{
$query->where('name', 'LIKE', "%$city_name%");
}
if ($state_id != '--')
{
$query->where('state_id', '=', $state_id);
}
$cities = $query->orderBy('name')->get();

Related

Get NULL/empty columns in Laravel eloquent query

Currently I'm working on a ajax search filters on Laravel, but I cannot get the correct info, this is the scenario:
I have 2 tables:
Table1: SoftwareRequest
Table2: DenyCategory
with a select option I get the name as Value
and I added that select option like in top of the query on the controller function:
$deniedReason = $request->get('deniedReason');
if($deniedReason == "All"){
$deniedReason = "";
}
So that means that every time I select "All" it will be empty so I can get all data like empty (this is the problem).
This is my current query:
$request_data = SoftwareRequest::leftJoin('DenyCategory', 'SoftwareRequest.DenyCategoryId', '=', 'DenyCategory.Id')->where('DenyCategory.Name', 'like', '%' . $deniedReason . '%')->paginate(20);
So the thing is that if I select another option rather than "All", for example "Already Available", I do get the excepted data, meaning all objects from table 1 joined with table 2 that has that option, but the problem comes when I select "All" it doesn't bring all the data it should and that's because not all objects have DenyCategoryId in Table1 meaning that some of those are Null/empty so it only brings the ones 'LIKE' Null/empty as I specified on the previous code block.
$deniedReason = $request->get('deniedReason');
if($deniedReason == "All"){
$deniedReason = "";
}
How can I get all data empty or not empty when I select the option All and as well as to get the data when I select another option? I bet it would have something to do with the query not being 'Like' but that's out of my knowledge scope.
Why not make the where clause optional?
$queryBuilder = SoftwareRequest::leftJoin('DenyCategory', 'SoftwareRequest.DenyCategoryId', '=', 'DenyCategory.Id')
// Only apply where-clause when denied reason has been provided.
if ($request->get('deniedReason') !== 'All') {
$queryBuilder = $queryBuilder->where('DenyCategory.Name', 'like', '%' . $deniedReason . '%');
}
$request_data = $queryBuilder->paginate(20);
I think you can improve your code a bit better but I'll leave that up to you with some pointers:
Eloquent relationships
Class Constants

Replace Like in SQL for ENUM

Currently I am having success with the following query:
if (isset($data->action_needed_status) && $data->action_needed_status != '') {
$query->where('status', 'like', '%'.$data->action_needed_status.'%');
$query_count->where('status', 'like', '%'.$data->action_needed_status.'%');
The complaint was this:
Since status is an ENUM field you know that any valid status value
passed should match exactly. There shouldn't be a need for using LIKE
in the where statements.
What would be the best way to have same result without using LIKE?

Array to string conversion in Laravel using 'LIKE' query

sorry for a newbie question.
I run into a problem. I want to search the database for values which an in array.
But I have an error:
Array to string conversion
And kinda get why but, I don't know how to make it right. Can you help me please?
This is my code:
public function chassis($chassis){
return $this->builder->whereIn('model_type_en', 'LIKE', (array)"%$chassis%");
}
P.S please don't laugh at me :)
$collection = DB::table('your_table')->select('*');
foreach($chassis as $key=>$val) {
if($key == 0) {
$collection->where('model_type_en', 'like', "%$val%"));
}
$collection->orWhere('model_type_en', 'like', "%$val%"));
}
$name = $collection->get();
This may work. You can also look at the ref: laravel querybuilder how to use like in wherein function
(original wrong ans:)
If chassis is a string, you can do this:
$this->builder->where('model_type_en', 'LIKE', "%$chassis%");
You can read the docs: https://laravel.com/docs/5.4/queries
you can use as like be sure $chassis is an array
public function chassis($chassis)
{
return $this->builder->whereIn('model_type_en', $chassis);
}
What you are tying to do is a combination of an IN and a LIKE.
I would suggest RLIKE which is a LIKE but with REGEX.
Although this is mysql specific, so I doubt there is a Laravel build in way to do this.
Update
Sadly I was mistaken, and though RLIKE could do it. Instead find your answer in this post here :
Is there a way to combine IN and LIKE in MySQL?

Deactivate filtering if inputs comes with all in Laravel

I am trying to filter my results
$students = \App\User::leftJoin('exam_places', 'exam_places.exam_place_no', '=', 'users.exam_place_id')
->select(['exam_places.*',
'users.*',
])
->where('exam_places.id',$input['examplace'])
->where('users.paymenet_method',$input['payment'])
->where('users.payStatus',$input['status'])->get();
my inputs comes like this for examplace (all, 1,2,3,4,5)
for paymentmethod(all,1,2,3,4,..)
for paystatus(0,1)
all my filtering method works however if user selects all as my
$input[examplace]= all
where statement looks for
where('exam_places.id','all')
however I want to disable this statement if all selected.
I tried to add
if($input[examplace] !=='all') {
->where('exam_places.id',$input['examplace'])
}
it gave me error.
Edit: let me explain briefly what code I've tried
$students = \App\User::leftJoin('exam_places', 'exam_places.exam_place_no', '=', 'users.exam_place_id')
->select(['exam_places.*',
'users.*',
])
if($input['examplace'] !== 'all){
->where('exam_places.id',$input['examplace'])
}
->where('users.paymenet_method',$input['payment'])
->where('users.payStatus',$input['status'])->get();
it gives me the error below
so question is how can I deactivate my if statement if input comes as all ?
You are trying to add logical statements within chaining, you can`t do that without separating them
Try adding the statements sequentially:
$stmt = \App\User::leftJoin('exam_places', 'exam_places.exam_place_no', '=', 'users.exam_place_id')
->select(['exam_places.*','users.*',]); //break here
if($input['examplace'] !== 'all'){
$stmt->where('exam_places.id',$input['examplace']);
}
$stmt->where('users.paymenet_method',$input['payment'])
->where('users.payStatus',$input['status']);
$students = $stmt->get();

Laravel select with multiple where in statement

I have tried various methods to resolve this issue, but none worked for me.
1st method:
$title = Character::find($selected_char->id)->title()->where('title', '=', 'Castle');
$title = $title->where('title', '=', 'City');
$title = $title->get();
2nd method:
$title = Character::find($selected_char->id)->title()->where('title', '=', 'Castle')->where('title', '=', 'City')->get();
3rd method:
$title = DB::select(DB::raw("select * from titles where titles.char_id = 5 and title = 'Castle' and title = 'City'"));
None of the above methods work. If I take only one where clause it works perfectly. Example:
$title = Character::find($selected_char->id)->title()->where('title', '=', 'City')->get();
$title = Character::find($selected_char->id)->title()->where('title', '=', 'Castle')->get();
I even tried to take another column than title, but it doesn't work with a second where function. I want to retreive the rows from titles table where the title is City AND Castle I have used multiple where clauses before in a single select statement and it worked. Not now. Any suggestions? Thanks in advance.
You said:
I want to retreive the rows from titles table where the title is City AND Castle
You may try this:
$rowCOllection = DB::table('titles')
->whereIn('title', array('City', 'Castle'))->get();
Using multiple where:
$rowCOllection = DB::table('titles')
->where('title', 'City')
->where('title', 'Castle')->get();
If you want to add another where clause for titles.char_id then you may use it like:
$rowCOllection = DB::table('titles')
->where('title', 'City')
->where('title', 'Castle')
->where('char_id', 5)->get();
You may chain as much where as you need before you call get() method. You can add the where('char_id', 5) after the whereIn like whereIn(...)->where('char_id', 5) and then call get().
If you have a Title model then you may do the same thing using:
Title::where(...)->where(...)->get();
Same as using DB, only replace the DB::table('titles') with Title, for example:
$rowCOllection = Title::where('title', 'City')
->where('title', 'Castle')
->where('char_id', 5)->get();
What about Character here ?
I don't really know how work your double ->where( in php, but in sql here is the mistake :
When you say where title = 'a' and title = 'b', it's like you say : ok give me something where 0=1 it returns nothing.
You can do :
select * from titles where titles.char_id = 5 and (title = 'Castle' or title = 'City')
Retrieve all data where title equals castle or city
Or
select * from titles where titles.char_id = 5 and title IN ('Castle','City')
Retrieve all data where title equals castle or city using IN
I'm pretty sure you will find a way to do that in PHP too.
Assuming you are using Laravel 4
And Character is your model extended from Eloquent
don't mix FIND and WHERE.
Find is for single usage find AND sorting afterward (so order by, and etc)
So if you want to chain up your query
Character::where()->where()->where()-get() (don't forget the get or else you wont get a result)
this way you respect eloquent's features.
Note your first method with ->title() is flawed because your calling a function that you custom created inside your model - thats why it wouldn't have worked.
Note: WereWolf Alpha's method will also work IF you don't want to use Eloquent because the code that he presented will work but thats Fluent notation...so take your pick.

Categories