Domanda

Ecco un'istantanea del mio codice:

$fetchPictures = $PDO->prepare("SELECT * 
    FROM pictures 
    WHERE album = :albumId 
    ORDER BY id ASC 
    LIMIT :skip, :max");

$fetchPictures->bindValue(':albumId', $_GET['albumid'], PDO::PARAM_INT);

if(isset($_GET['skip'])) {
    $fetchPictures->bindValue(':skip', trim($_GET['skip']), PDO::PARAM_INT);    
} else {
    $fetchPictures->bindValue(':skip', 0, PDO::PARAM_INT);  
}

$fetchPictures->bindValue(':max', $max, PDO::PARAM_INT);
$fetchPictures->execute() or die(print_r($fetchPictures->errorInfo()));
$pictures = $fetchPictures->fetchAll(PDO::FETCH_ASSOC);

ho

  

Hai un errore nella sintassi SQL;   controllare il manuale che corrisponde   la versione del server MySQL per la   sintassi diritto di utilizzare vicino a '' 15' , 15' a   Linea 1

Sembra che DOP è l'aggiunta di apici ai miei variabili nella parte LIMIT del codice SQL. Ho cercato Ho trovato questo bug che credo sia correlato: http://bugs.php.net/bug.php?id=44639

E 'questo che sto guardando? Questo bug è stato aperto da April 2008! Quello che dovremmo fare nel frattempo?

Ho bisogno di costruire un po 'di impaginazione, e la necessità di assicurarsi che i dati è pulito, SQL Injection di sicurezza, prima di inviare la dichiarazione di sql.

È stato utile?

Soluzione

Mi ricordo di avere questo problema prima. Cast del valore di un numero intero prima di passare alla funzione bind. Credo che questo risolve.

$fetchPictures->bindValue(':skip', (int) trim($_GET['skip']), PDO::PARAM_INT);

Altri suggerimenti

La soluzione più semplice sarebbe quella di commutare la modalità di emulazione off . È possibile farlo sia come opzione di connessione o semplicemente aggiungendo la seguente riga

$PDO->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

E non solo risolvere il problema con bind param, ma permetterà anche di inviare i valori in execute (), che renderà il vostro codice muchshorter

$skip = $_GET['skip'] ?: 0;
$sql  = "SELECT * FROM pictures WHERE album = ? ORDER BY id LIMIT ?, ?";
$PDO->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
$stmt  = $PDO->prepare($sql);
$stmt->execute([$_GET['albumid'], $skip, $max]);
$pictures = $stmt->fetchAll(PDO::FETCH_ASSOC);

Guardando il bug report, il seguente potrebbe funzionare:

$fetchPictures->bindValue(':albumId', (int)$_GET['albumid'], PDO::PARAM_INT);

$fetchPictures->bindValue(':skip', (int)trim($_GET['skip']), PDO::PARAM_INT);  

ma sei sicuro i dati in ingresso è corretto? Perché nel messaggio di errore, sembra che ci sia solo una citazione dopo il numero (in contrasto con il numero intero di essere racchiuso tra virgolette). Questo potrebbe anche essere un errore con i tuoi dati in arrivo. Si può fare un print_r($_GET); per scoprire?

Questo proprio come sintesi.
Ci sono quattro opzioni per parametrizzare Limitare / valori di offset:

  1. PDO::ATTR_EMULATE_PREPARES Disable come menzionato sopra .

    che impedisce valori passati per ->execute([...]) a mostrare sempre come stringhe.

  2. Passa alla popolazione parametro ->bindValue(..., ..., PDO::PARAM_INT) manuale.

    Il che, tuttavia, è meno conveniente di un -> execute elenco []

  3. .
  4. È sufficiente fare un'eccezione qui e solo interpolare interi semplici quando si prepara la query SQL.

     $limit = intval($limit);
     $s = $pdo->prepare("SELECT * FROM tbl LIMIT {$limit}");
    

    Il casting è importante. Più comunemente vedete ->prepare(sprintf("SELECT ... LIMIT %d", $num)) utilizzati a tal fine.

  5. Se non si utilizza MySQL, ma per esempio SQLite, o Postgres; è anche possibile cast legato parametri direttamente in SQL.

     SELECT * FROM tbl LIMIT (1 * :limit)
    

    Anche in questo caso, MySQL / MariaDB non supportano espressioni nella clausola LIMIT. Non ancora.

per LIMIT :init, :end

È necessario legare in quel modo. se si ha qualcosa di simile $req->execute(Array()); non funzionerà come sarà gettato PDO::PARAM_STR a tutti Vars nella matrice e per la LIMIT è assolutamente necessario un numero intero. bindValue o BindParam come si desidera.

$fetchPictures->bindValue(':albumId', (int)$_GET['albumid'], PDO::PARAM_INT);

Dal momento che nessuno ha spiegato perché questo sta accadendo, io sono l'aggiunta di una risposta. Il motivo per cui si sta comportando questo è stato è perché si sta utilizzando trim(). Se si guarda al manuale di PHP per trim, il tipo di ritorno è string. Si sta quindi cercando di far passare questo come PDO::PARAM_INT. A pochi modi per aggirare questo sono:

  1. Usa filter_var($integer, FILTER_VALIDATE_NUMBER_INT) per assicurarsi che si sta passando un intero.
  2. Come altri hanno detto, usando intval()
  3. Casting con (int)
  4. Verificando è un intero con is_int()

Ci sono molti altri modi, ma questo è fondamentalmente la causa principale.

bindValue di offset e il limite di utilizzo DOP :: PARAM_INT e funzionerà

// prima (errore Presente) $ Query = ".... LIMITE: p1, 30;"; ... $ Stmt-> BindParam ( 'p1', $ limiteInferior);

// DOPO (errore corretto) $ Query = ".... LIMITE: p1, 30;"; ... $ LimiteInferior = (int) $ limiteInferior; $ Stmt-> BindParam ( 'p1', $ limiteInferior, DOP :: PARAM_INT);

PDO::ATTR_EMULATE_PREPARES mi ha dato la

  

driver non supporta questa funzione: Questo driver non supporta   errore di impostazione attributi.

La mia soluzione era quella di impostare una variabile $limit come una stringa, poi si combinano nella dichiarazione di preparare, come nel seguente esempio:

$limit = ' LIMIT ' . $from . ', ' . $max_results;
$stmt = $pdo->prepare( 'SELECT * FROM users WHERE company_id = :cid ORDER BY name ASC' . $limit . ';' );
try {
    $stmt->execute( array( ':cid' => $company_id ) );
    ...
}
catch ( Exception $e ) {
    ...
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top