I'm Root James
I'm Root James

Reputation: 6535

Building MySQL query with need for variable operators PHP PDO

Is there any standard or best way in PHP PDO database class to change the operator from "=" to "IS" when I don't know if the value I'm going to pass is NULL or not. Here is an example of what I mean.

I have two variables. I want a count of the results that match. Sometimes one or both of the variables can be NULL. But MySQL requires a different operator to find NULL (IS NULL).

I'm currently just creating another variable for the operator and when I build the query I inject it in as so:

  // First create a variable "=" or "is" depending on whether var1 and var2 are NULL or not
  if($var1 == NULL) $var1_operator = "IS";
  else $var1_operator = "=";
  if($var2 == NULL) $var2_operator = "IS";
  else $var2_operator = "=";

  // Build the query
  $query = 'SELECT count(*) as count FROM table 
  WHERE var1 '.$var1_operator.' :var1 AND var2 '.$var2_operator.' :var2';

  //  Conduct the query
  $prepare = $db_connection->prepare($query);
  $prepare->bindValue(':var1', $var1, PDO::PARAM_STR);
  $prepare->bindValue(':var2', $var2, PDO::PARAM_STR);
  $prepare->execute();
  $results = $prepare->fetch();

Is there another way to do this? This works to bindValue using PARAM_STR even when the value is NULL and not really a string. The query returns the correct value count. Just not sure if there is better practice for doing it.

Upvotes: 1

Views: 199

Answers (1)

Your Common Sense
Your Common Sense

Reputation: 158005

As you are using mysql, you can use its spaceship operator, <=>:

$query = 'SELECT count(*) FROM table WHERE var1 <=> ? AND var2 <=> ?';
$prepare = $db_connection->prepare($query);
$prepare->execute([$var1, $var2]);
$count = $prepare->fetchColumn();

But in general, if you need variable operators or other query parts, such a conditional query building is the only way.

A more generalized solution can be found in my article How to create a WHERE clause for PDO dynamically:

// always initialize a variable before use!
$conditions = [];
$parameters = [];

// conditional statements
if (!empty($_GET['name']))
{
    // here we are using LIKE with wildcard search
    // use it ONLY if really need it
    $conditions[] = 'name LIKE ?';
    $parameters[] = '%'.$_GET['name']."%";
}
if (!empty($_GET['sex']))
{
    // here we are using equality
    $conditions[] = 'sex = ?';
    $parameters[] = $_GET['sex'];
}
if (!empty($_GET['car']))
{
    // here we are using not equality
    $conditions[] = 'car != ?';
    $parameters[] = $_GET['car'];
}
// the main query
$sql = "SELECT * FROM users";
// a smart code to add all conditions, if any
if ($conditions)
{
    $sql .= " WHERE ".implode(" AND ", $conditions);
}
// the usual prepare/execute/fetch routine
$stmt = $pdo->prepare($sql);
$stmt->execute($parameters);
$data = $stmt->fetchAll();

so in these conditions above whatever logic could be implemented, including operator change or anything.

Upvotes: 2

Related Questions