2

My purpose is to find all the item in the table that match a collection stored in a String:

$array=array("item1","item2","item3","item4");//This is dynamically filled, this is just an example
$in_list = "'".implode("','",$array)."'";//that's why i use implode

$stmt = $this->db->prepare('SELECT libelle,activite,adresse,tel,lat,lng FROM etablissements where type IN ('.$in_list.')');

        $stmt->bind_param("s", $in_list);
        $stmt->execute();
        $stmt->bind_result($libelle,$activite,$adresse,$tel,$lat,$lng);

That seems not to work perfectly, it always throwing me the following warning:

mysqli_stmt::bind_param() [<a href='mysqli-stmt.bind-param'>mysqli-stmt.bind-param</a>]: Number of elements in type definition string doesn't match number of bind variables in <b>/homepages/25/d399726988/htdocs/

If i had one parameter, it would be obvious:

    $stmt = $this->db->prepare('SELECT libelle,activite,adresse,tel,lat,lng FROM etablissements where type =?');
$stmt->bind_param("s", $parameter);

But since i have to deal with that, it became a bit complicated to me.

hakre
  • 193,403
  • 52
  • 435
  • 836
Malloc
  • 15,434
  • 34
  • 105
  • 192
  • what did you get if you print `$in_list` – Fahim Parkar Jan 25 '12 at 16:27
  • It is a list separated by a comma: `'item1','item2','item3'` – Malloc Jan 25 '12 at 16:30
  • 1
    possible duplicate of [PDO with "WHERE... IN" queries](http://stackoverflow.com/questions/2373562/pdo-with-where-in-queries) – nikc.org Jan 25 '12 at 16:32
  • possible duplicate of [MySQL Prepared statements with a variable size variable list](http://stackoverflow.com/questions/327274/mysql-prepared-statements-with-a-variable-size-variable-list) – outis Jul 03 '12 at 18:35

1 Answers1

4

The prepared statement has no parameters because you have interpolated the list into the statement before preparing it.

$array=array("item1","item2","item3","item4");
//This is dynamically filled, this is just an example
$in_list = "'".implode("','",$array)."'";//that's why i use implode

$stmt = $this->db->prepare('SELECT libelle,activite,adresse,tel,lat,lng FROM etablissements where type IN ('.$in_list.')');

At this point, the SQL statement you have created is:

SELECT libelle,activite,adresse,tel,lat,lng 
FROM etablissements where type IN ('item1','Item2','Item3','Item4')

Since the statement has no parameters, mysqli_stmt::bind_param fails. Instead of interpolating the items into the statement (which is vulnerable to injection), interpolate a string of parameters, then bind the values (which must be kept separate).

$array=array("item1","item2","item3","item4");

if (count($in_list) > 0) {
    $query = $this->db->prepare('SELECT libelle,activite,adresse,tel,lat,lng FROM etablissements WHERE type IN (' . str_repeat('?, ', count($in_list)-1) . '?)');

    $args = $in_list;
    array_unshift($args, str_repeat('s', count($in_list)));
    call_user_func_array(array($query, 'bind_param'), $args);
    $query->execute();
    $query->bind_result($libelle,$activite,$adresse,$tel,$lat,$lng);
}

PDO's interface for binding is more straightforward.

$array=array("item1","item2","item3","item4");

if (count($in_list) > 0) {
    $query = $this->db->prepare('SELECT libelle,activite,adresse,tel,lat,lng FROM etablissements WHERE type IN (' . str_repeat('?, ', count($in_list)-1) . '?)');

    foreach ($in_list as $i => $arg) {
        // query params are 1-based, so add 1 to the index
        // PDO::PARAM_STR is the default type, so no need to pass 3rd arg
        $query->bindValue($i+1, $arg);
    }
    $query->execute();
    // no need to bind the result
}

In fact, it can be even simpler with PDO, since PDOStatement::execute can take a list of parameter values:

$array=array("item1","item2","item3","item4");

if (count($in_list) > 0) {
    $query = $this->db->prepare('SELECT libelle,activite,adresse,tel,lat,lng FROM etablissements WHERE type IN (' . str_repeat('?, ', count($in_list)-1) . '?)');

    $query->execute($in_list);
}
outis
  • 75,655
  • 22
  • 151
  • 221
Ben
  • 34,935
  • 6
  • 74
  • 113