Frage

Hier ist ein Schnappschuss von meinem Code:

$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);

ich

  

Sie haben einen Fehler in der SQL-Syntax;   Sie in der Bedienungsanleitung entspricht   Ihre MySQL-Server-Version für die   rechts Syntax verwendet in der Nähe ‚‘ 15' , 15'   Zeile 1

Es scheint, dass PDO einfache Anführungszeichen meine Variablen in der LIMIT Teil des SQL-Codes hinzufügt. Ich sah es bis ich diesen Fehler gefunden, die ich denke, ist verwandt: http://bugs.php.net/bug.php?id=44639

Ist das, was an ich suche? Dieser Fehler ist seit April 2008 geöffnet! Was sollen wir in der Zwischenzeit tun?

Ich brauche Paginierung zu bauen, und müssen sicherstellen, dass die Daten sauber, SQL-Injection-safe, bevor die SQL-Anweisung zu senden.

War es hilfreich?

Lösung

Ich erinnere mich, dieses Problem vor. Gegossen, den Wert auf eine ganze Zahl, bevor es an die Funktion bind vorbei. Ich denke, dies löst es.

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

Andere Tipps

Die einfachste Lösung wäre, schalten Sie den Emulationsmodus ausgeschaltet . Sie können es entweder als Verbindungsoption tun oder einfach, indem Sie die folgende Zeile

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

Es wird nicht nur Ihr Problem mit bind param lösen, sondern auch können Sie Werte senden in execute (), die Ihren Code machen 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);

Mit Blick auf den Bug-Report, der folgende funktionieren könnte:

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

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

aber sind Sie sicher, Ihre eingehenden Daten korrekt sind? Da in der Fehlermeldung, es scheint nur ein Zitat nach der Zahl zu sein (in Bezug auf die gesamte Anzahl entgegengesetzt ist in Anführungszeichen eingeschlossen). Dies könnte auch ein Fehler bei eingehenden Daten sein. Können Sie tun, um eine print_r($_GET); zu wissen?

Dies ist nur als Zusammenfassung.
Es gibt vier Optionen zu parametrisieren LIMIT / OFFSET Werte:

  1. Disable PDO::ATTR_EMULATE_PREPARES wie erwähnt oben .

    Welche verhindert Werte pro ->execute([...]) bestanden immer als Strings angezeigt.

  2. Zur manuellen ->bindValue(..., ..., PDO::PARAM_INT) Parameter Bevölkerung.

    Was aber ist weniger bequem als ein. -> Ausführen Liste []

  3. Einfach hier eine Ausnahme machen und nur interpolieren Ebene ganze Zahlen, wenn die SQL-Abfrage vor.

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

    Das Casting ist wichtig. Häufiger sehen Sie ->prepare(sprintf("SELECT ... LIMIT %d", $num)) für solche Zwecke verwendet wird.

  4. Wenn Sie nicht MySQL verwenden, aber zum Beispiel SQLite oder Postgres; Sie können auch gebundene Parameter direkt in SQL gegossen.

     SELECT * FROM tbl LIMIT (1 * :limit)
    

    Auch MySQL / MariaDB unterstützt keine Ausdrücke in der LIMIT-Klausel. Noch nicht.

für LIMIT :init, :end

Sie müssen auf diese Weise binden. wenn Sie so etwas wie $req->execute(Array()); haben es wird nicht arbeiten, wie es PDO::PARAM_STR alle Vars in der Anordnung gegossen wird und für den LIMIT Sie unbedingt eine Integer benötigen. bindValue oder BindParam wie Sie wollen.

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

Da hat niemand erklärt, warum dies geschieht, ich hinzufüge, eine Antwort. Der Grund, es war dies verhält, weil Sie trim() verwenden. Wenn Sie auf dem PHP-Handbuch für trim aussehen, ist der Rückgabetyp string. Sie versuchen dann diese als PDO::PARAM_INT passieren. Ein paar Möglichkeiten, dies zu umgehen:

  1. Verwenden Sie filter_var($integer, FILTER_VALIDATE_NUMBER_INT) um sicherzustellen, dass Sie eine ganze Zahl sind vorbei.
  2. Wie bereits gesagt, mit intval()
  3. Casting mit (int)
  4. Überprüfen, ob es eine ganze Zahl mit is_int()

Es gibt viel mehr Möglichkeiten, aber das ist im Grunde die Ursache.

bindValue Offset und Begrenzung mit PDO :: PARAM_INT und es wird funktionieren

// VOR (aktuelle Fehler) $ Query = ".... LIMIT: p1, 30;" ... $ Stmt-> bindParam ( ': p1', $ limiteInferior);

// NACH DEM (Fehler behoben) $ Query = ".... LIMIT: p1, 30;" ... $ LimiteInferior = (int) $ limiteInferior; $ Stmt-> bindParam ( ': p1', $ limiteInferior, PDO :: PARAM_INT);

gab PDO::ATTR_EMULATE_PREPARES mir die

  

Treiber diese Funktion nicht unterstützen: Dieser Treiber unterstützt keine   Einstellungsfehler Attribute.

Meine Abhilfe war eine $limit Variable als String zu setzen, kombinieren sie dann in der Anweisung vorzubereiten, wie im folgenden Beispiel:

$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 ) {
    ...
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top