2010-10-08 32 views
5

Soy nuevo en PHP y estoy tratando de aprender a utilizar PDO para conectarme a una prueba MySQL db. Tengo el siguiente:Ejecutar una instrucción PDO preparada con la cláusula similar

try { 
    $db = new PDO('mysql:dbname=MYDBNAME;host=MYHOST', 'USERNAME', 'PASSWORD'); 

    $query = "select * from books where ? like '%?%'"; 
    $stmt = $db->prepare($query); 
    $stmt->execute(array($searchtype, $searchterm)); 
} catch(PDOException $e) { 
    echo 'PDOException: ' . $e->getMessage(); 
} 

Cuando lo intento me sale el siguiente mensaje de advertencia: Advertencia: PDOStatement :: execute() [pdostatement.execute]: SQLSTATE [HY093]: número de parámetro no válido: número de variables ligadas no coincide con el número de tokens

Cuando elimino la cláusula similar, y el parámetro $ searchterm, devuelve el resultado correctamente. Pensé que, como '%?%', Podría no ser una forma legal de crear esta consulta entre comillas dobles, así que probé escapando ', lo cual no funcionó. Busqué a una solución, y se encontró que alguien se movía '% y%' hasta donde $ término de búsqueda es:

$query = "select * from books where ? like ?"; 
... 
$stmt->execute(array($searchtype, '\'%'.$searchterm.'%\'')); 

me dieron el mismo resultado.
Se agradece cualquier ayuda. ¡Gracias!

/ ACTUALIZACIÓN ****/ He encontrado en el ejemplo 12 de http://us3.php.net/manual/en/pdo.prepared-statements.php

Ejemplo # 12 Uso no válido de marcador de posición

<?php 
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE '%?%'"); 
$stmt->execute(array($_GET['name'])); 

// Below is What they suggest is the correct way. 
// placeholder must be used in the place of the whole value 
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE ?"); 
$stmt->execute(array("%$_GET[name]%")); 
?> 

Probé este, y aunque Ya no recibo una Advertencia, no obtengo ningún resultado. Sin embargo, cuando ejecuto la consulta directamente obtendré un par de resultados. ¿Alguna idea?

+0

Tengo el mismo problema, como usted, pensé que el '%' era una parte de la estructura de la consulta en lugar de los valores;) – Strae

Respuesta

2
$stmt->execute(array($searchtype, '\'%'.$searchterm.'%\'')); 

Así no es cómo funcionan las consultas con parámetros. Los parámetros insertados ya actúan como cadenas literales, no tiene que agregar delimitadores de comillas o escaparse de ellos (ese es el punto), y si lo intenta, está literalmente comparando con la cadena single-quote-searchterm-single- citar.

En consecuencia, si usted (como sospecho) con la intención de comparar una columna en particular contra una cadena literal, no se parametriza el nombre de la columna. ¡En este momento está comparando una cadena literal con otra cadena literal, por lo que siempre será verdadera o siempre falsa, independientemente de los datos de la fila!

Así que creo que lo que probablemente es decir:

$query= "SELECT * FROM books WHERE $searchtype LIKE ?"; 
$like= "%$searchterm%"; 
$stmt->execute(array($like)); 

pensamiento, naturalmente, usted tendrá que tener mucho cuidado de que $searchtype se sabe bien para evitar la inyección SQL. Por lo general, lo compararía con una lista de nombres de columnas aceptables antes de usarlo.

(Aparte: no es una forma de poner cadenas arbitrarias en un nombre de esquema que se puede utilizar para una columna, pero es molesto, varía a través de bases de datos y no es una función de escape estándar para que en MySQL. , barra invertida: escape al carácter de comillas invertidas, comillas y barras diagonales inversas, y rodee el nombre con comillas inversas. En ANSI SQL, utiliza comillas dobles con comillas dobles dentro. En SQL Server utiliza corchetes. para hacer algo de esto porque realmente solo quieres permitir unos pocos nombres de columna predefinidos.)

(Otro lado: si quieres ser capaz de permitir $searchterm valores con porcentajes literales, subraya o barras invertidas en lo que los usuarios pueden buscar “100%” sin cumplir ninguna cualquier cadena con 100 en lo que tiene que utilizar un carácter de escape explícita, que es un poco tedioso :)

$query= "SELECT * FROM books WHERE $searchtype LIKE ? ESCAPE '+'"; 
$like= str_replace(array('+', '%', '_'), array('++', '+%', '+_'), $searchterm); 
$stmt->execute(array("%$like%")); 
+1

No 'array '(' ++ ',' +% ',' + _ ')' be 'array (' \ + ',' \% ',' \\ _ ')', o incluso 'array (' \% ',' \\ _ ') '(¿por qué escape +)? (Por cierto, ¿por qué el Markdown aquí convierte '\\ _' a _?) –

+0

¡esto funciona! pero cómo recortar() el espacio? – user1775888

3

no añada las cotizaciones al enlazar las variables preparadas y no te enlazar el nombre de la columna

$query = sprintf("select * from books where %s like ?", $searchtype); 
... 
$stmt->execute(array($searchtype, '%'.$searchterm.'%')); 
+0

Intenté esto y esto no funcionó. Creo que el problema como Bobince lo ha puesto en otra respuesta es que no toma% como un comodín, sino más bien un literal '%', que no es mi intención. – Elle

2

El problema que veo es que si hubiera escrito un contenedor para PDO, entonces tendría que manejar esto de alguna manera por separado. La respuesta que había encontrado y amado fue escribir su consulta y concat el% para el parámetro. es decir "DONDE la columna como concat ('%',: algo, '%')"

Cuestiones relacionadas