2010-10-05 12 views
4

J'ai une fonction comme ce qui suit:PHP imploser pour générer MySQL critères

public function foo ($cities = array('anaheim', 'baker', 'colfax')) 
{ 
    $db = global instance of Zend_Db_Adapter_Pdo_Mysql... 

    $query = 'SELECT name FROM user WHERE city IN ('.implode(',',$cities).')'; 
    $result = $db->fetchAll($query); 
} 

Cela fonctionne bien jusqu'à ce que quelqu'un passe villes $ comme un tableau vide.

Pour éviter cette erreur, je suis logique cassantes la requête comme ceci:

$query = 'SELECT name FROM user'; 
if (!empty($cities)) 
{ 
    $query .= ' WHERE city IN ('.implode(',',$cities).')'; 
} 

mais ce n'est pas très élégant. Je pense qu'il devrait y avoir un meilleur moyen de filtrer par liste, mais je ne suis pas sûr de savoir comment. Aucun conseil?

+3

Cela permettra également briser si un utilisateur soumet une ville qui contient ' '' (injection SQL) ou une virgule ... Vous devez les envelopper dans '' s –

+0

Il est parfaitement bien de le faire de cette façon. S'il n'y a pas de ville, vous n'avez pas besoin d'une clause WHERE ... –

+2

Cela me semble bien, mais vous pouvez utiliser l'une des nombreuses classes disponibles pour faire de belles requêtes préparées. À tout le moins, échapper à vos ficelles !! http://php.net/manual/fr/function.mysql-real-escape-string.php – Brad

Répondre

3

Au moins utiliser la méthode quote ...

if ($cities) { 
    $query .= sprintf('WHERE city IN (%s)', implode(',', array_map(array($db, 'quote'), $cities))); 
} 

ou, idéalement, construire la requête avec Zend_Db_Select ...

$select = $db->select()->from('user', 'name'); 

if ($cities) { 
    foreach ($cities as $city) { 
     $select->orWhere('city = ?', $city); 
    } 
} 
7

Si vous finissez à l'aide de l'objet, sélectionnez l'->where() méthode va effectivement gérer les tableaux pour vous. Encore faut-il vérifier s'il y a des éléments dans le tableau, mais cela en fait une approche plus propre ...

$select = $db->select()->from('user', 'name'); 

if ($cities) { 
    $select->where('city IN (?)', $cities); 
} 
0

Vous savez, de Zend Docs Zend_Db_Adapter :: quote « Si un tableau est en tant que valeur, les valeurs du tableau sont cotées *, puis renvoyées sous la forme d'une chaîne séparée par des virgules. "

Vous pouvez le faire qui est également cité correctement:

if ($cities) $query .= 'WHERE city IN ({$db->quote($cities}) '; 

I love 1-liners :)