Pregunta

Esto es un poco extraño, y podría estar codificando esto completamente mal, por eso he cometido el mismo error dos veces en dos días, en partes completamente diferentes de un script. El código que estoy usando está abajo:


    public function findAll( $constraints = array() ) {

        // Select all records
        $SQL = 'SELECT * FROM ' . $this->tableName;

        // See if there's any constraints
        if( count( $constraints ) > 0 ) {
            $SQL .= ' WHERE ';

            foreach( $constraints as $field => $value ) {
                $SQL .= $field . ' = :' . $field . ' AND ';
            }

        }

        // Remove the final AND and prepare the statement
        $SQL = substr( $SQL, 0, -5 );       
        $PDOStatement = $this->PDO->prepare( $SQL );

        // Loop through constraints and bind parameters
        foreach( $constraints as $field => $value ) {
            print 'Binding ' . $field . ' to ' . $value . ' 
'; $PDOStatement->bindParam( $field, $value ); } $PDOStatement->execute(); var_dump($PDOStatement); while ( $results = $PDOStatement->fetch( PDO::FETCH_ASSOC ) ) { var_dump($results); } }

Soy bastante nuevo en el uso de PDO, pero básicamente estoy intentando pasar una serie de restricciones, por ejemplo.

array( 'active' => 1, 'name' => 'James' )
y devuelve todas las filas de la tabla
WHERE active = 1 AND name = 'James'

Si uso esta matriz, el SQL ejecutado desde el primer

var_dump( )
es
SELECT * FROM {table} WHERE active = :active AND name = 'James'
, exactamente como lo espero. Los parámetros enlazados imprimen 'Enlace activo a 1' y 'Nombre de enlace a James', exactamente como se esperaba. Las filas existen en la base de datos y, sin embargo, la segunda llamada a
var_dump()
para $ resultados no genera ningún resultado, es decir, no se devuelven filas.

Si paso una matriz de una sola restricción, p. ej.

array( 'active' => 1 )
, esto funciona perfectamente bien. Parece que cada vez que se pasan varias restricciones, deja de funcionar.

¿Fue útil?

Solución

Esto se debe a que bindParam funciona de se vincula a una variable y está reutilizando la variable ( $ value ) para varios valores. Pruebe con bindValue en su lugar.

O incluso mejor aún; Pase los valores como una matriz a execute en lugar. Esto hace que la declaración sea sin estado, lo que generalmente es bueno en la programación.

Otros consejos

Como se mencionó, usando bindValue En lugar de bindParam ciertamente lograremos esto. Sin embargo, después de pasar una cantidad considerable de tiempo solucionando este problema recientemente, descubrí una solución alternativa. Aquí es cómo realizar el enlace de la variable PDO en un bucle foreach utilizando bindParam:

Reemplaza la siguiente línea de la publicación original:

$PDOStatement->bindParam( $field, $value );

... con esto:

$PDOStatement->bindParam( $field, $constraints[$field] );

En lugar de enlazar $ value , use $ array_name [$ array_key] . Esto funciona porque ahora estás enlazando a una variable única en lugar de a una que se reutiliza en cada pasada del bucle.

Sin embargo,

la variable $ field utilizada como marcador de posición no necesita ser una variable única. Todavía no he investigado a fondo esto, pero una variable utilizada como marcador de posición parece analizarse inmediatamente (en lugar de asignarse como una referencia de variable) incluso cuando se usa bindParam.

Además, como ya no necesitaría acceder directamente a $ value , también podría reemplazar esto:

foreach( $constraints as $field => $value ) {

... con esto:

foreach (array_keys($constraints) as $field) {

Esto es opcional, ya que funcionará bien sin este cambio. Sin embargo, en mi opinión, parece más limpio, ya que podría resultar confuso más adelante en cuanto a por qué se asigna el $ value pero nunca se usa.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top