0

Is there a way to create a dynamic sql query so that certain where clauses only run if a variable isn't null?

So say a user can select various options to filter results and they can chose not to select a an option from certain dropdowns if they don't need to. That would result in certain variables being null.

I'd like to do it in a way that wouldn't result in writing if statements to cater for every eventuality.

Don't mind suggestions in PHP or Laravel specific answers.

Thanks!

Glen Solsberry
  • 11,960
  • 15
  • 69
  • 94
BarryWalsh
  • 1,300
  • 4
  • 14
  • 36

2 Answers2

0

I'd prefer the if statements, but you can look into the Coalesce operator: http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce

Jlil
  • 170
  • 1
  • 7
  • Thanks I'll take a look at that. I think the if statements might get a bit messy if more filter options are added later. Unless there's a way I can create the query as a string and append to it based on what variables are set but that doesn't seem to work. – BarryWalsh Jan 16 '14 at 22:28
0

Create a client-side jQuery function
One of the things you could do is write a bit if jQuery that goes through all your input client-side and only submits the input where the value is not empty/null. The jquery code could be used for all your forms or input data. So you simply never get the passed parameters that have null values coming into your server-side controller (and eventually into your dynamic query). You can find solutions in this stackoverflow question here for this. Personally, I just have all my input in a class and cycle through it to remove the empty values. See my simple Fiddle here. You can even create special conditions for special types of inputs, that way your script covers for all types of null/empty/etc if you wanted.

OR

Create a helper function in PHP/Laravel
You could also do this server-side. You could write a helper function that loops through all your input coming in and removes the empty inputs. It could also build the WHERE clause at the same time for you (either raw, or you could pass your query object into the helper and it could add each ->where as it loops through the input and returns the query object back to you).

$query = DB::table('my_table')->select('abc', 'xyz');

// This could be your helper. Pass in your query and input...
dynamicWhereHelper($query, Input::all()); 

$rows = $query->get();

and in your dynamicWhereHelper:

function dynamicWhereHelper($query, $input = array()) 
{
   // Assuming you named each of your inputs the same as your database fields
   foreach ($input as $key => $value){
      if(!empty($value)){ 
          $query->where($key, $value); 
      }
   }
}

NOTE: A safer approach would be to additionally pass an array of acceptable input names in order to verify that no random $key is passed into the WHERE. You can define this array once per page you build, and it could be used to both build your form and then later used in the helper: dynamicWhereHelper($query, Input::all(), $acceptableInputs);

Community
  • 1
  • 1
prograhammer
  • 20,132
  • 13
  • 91
  • 118
  • Thanks for the detailed answer! Before I called it a night I found the option to use something like with Laravel `if ($fork) $query->where('forkmaterial', '=', $fork)` That seems to do the job fairly well and it's about as clean as I could have hoped it to be. – BarryWalsh Jan 17 '14 at 09:48