Ankündigung

Einklappen
Keine Ankündigung bisher.

PDO mit prepared Statement schmeißt Fehler

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • PDO mit prepared Statement schmeißt Fehler

    Hallo zusammen,

    ich habe meine Software von den alten mysql_ Funktionen auf PDO umgebaut und auf meinem Localhost mit PHP 5.5.3 funktioniert alles ohne Probleme.
    Ich verwende eine fertige PHP PDO Klasse.

    Wenn ich nun das ganze auf meinen Server mit PHP 5.4.17 spiele, erhalte ich bei manchen Abfragen einen SQL Fehler, den ich nicht ganz zuordnen kann:

    Unhandled Exception.
    SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''10'' at line 1


    Die Abfrage dazu sieht wie folgt aus:
    PHP-Code:
     public function get_premium_products($project 1$premiumtype$limit 10$maincatter "")
        {   
    $this->dbobj->bind("project_id"$project);
            
    $this->dbobj->bind("premiumtype"$premiumtype);
            
    $this->dbobj->bind("limit"$limit);

            
    $sql "SELECT * FROM product_main WHERE project = :project_id  AND activation = 1 AND premium = :premiumtype AND premium_expire > ".time()." ";
            if (
    $maincatter != "")
            {    
    $this->dbobj->bind("maincatter"$maincatter);
                
    $sql .= " AND maincat = :maincatter ";
            }
            
    $sql .= " ORDER BY RAND() LIMIT 0, :limit ";
            
    $result $this->dbobj->query($sql); 
    Ich habe mal bisschen gegoogled und eventuell besteht ein Bug in der alten PHP Version mit Maskierung des Limits, dennoch würde ich gerne eure Meinung wissen ob ich hier irgendwas grundlegendes falsch gemacht habe.
    Wie gesagt, auf dem Localhost läuft alles.

    Die dazugehörige PDO-Klase instanziert wie folgt:

    PHP-Code:
    private function Connect()
            {
                
    $this->settings parse_ini_file("settings.ini.php");
                
    $dsn 'mysql:dbname='.$this->settings["dbname"].';host='.$this->settings["host"].'';
                try 
                {
                    
    # Read settings from INI file, set UTF8
                    
    $this->pdo = new PDO($dsn$this->settings["user"], $this->settings["password"], array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",   PDO::ATTR_PERSISTENT => true));
                    
                    
    # We can now log any exceptions on Fatal error. 
                    
    $this->pdo->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION);
                    
                    
    # Disable emulation of prepared statements, use REAL prepared statements instead.
                    
    $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPAREStrue);
                    
                    
    # Connection succeeded, set the boolean to true.
                    
    $this->bConnected true;
                }
                catch (
    PDOException $e
                {
                    
    # Write into log
                    
    echo $this->ExceptionLog($e->getMessage());
                    die();
                }
            } 
    Wenn ich die Zeile
    PHP-Code:
    $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPAREStrue); 
    auf FALSE setze, kommt kein Fehler, dafür ist das System so langsam, dass ich mir nebenher ein Spiegelei braten könnte.

  • #2
    Bin mir da nicht sicher, aber es könnte mit der Funktionsweise der Prepared Statements zusammenhängen, bei der die Query schonmal an mysql gesendet und geparsed wird, und im nachhinein die Parameter eingesetzt werden(Keine Gewähr auf richtige Wortwahl). MySQL kann aber mit so "dynamischen" Limit-Klauseln nichts anfangen. ([1]außer in stored procedures, [2] weiß nicht ob andere DBMS das können).

    Kannst du mal versuchen, $limit direkt in die Query zu setzen? Zum Performanceproblem fällt mir gerade nichts ein.
    [COLOR=#A9A9A9]Relax, you're doing fine.[/COLOR]
    [URL="http://php.net/"]RTFM[/URL] | [URL="http://php-de.github.io/"]php.de Wissenssammlung[/URL] | [URL="http://use-the-index-luke.com/de"]Datenbankindizes[/URL] | [URL="https://www.php.de/forum/webentwicklung/datenbanken/111631-bild-aus-datenbank-auslesen?p=1209079#post1209079"]Dateien in der DB?[/URL]

    Kommentar


    • #3
      Das dies Local ohne Fehler läuft bezweifle ich stark. Ich vermisse ein prepare vor deinem bind.(*)
      Schau dir hier das Beispiel 2 an.

      Wenn du ein Limit mit prepared Statement's machen möchtest, wird unbedingt PDO::PARAM_INT benötigt:
      PHP-Code:
      $sql "SELECT id, time, value FROM test limit :limit";
      $stmt $db->prepare($sql);
      $stmt->bindValue (':limit'$limitPDO::PARAM_INT); 
      (*) Da du eine "fertige PHP PDO Klasse" benutzt, weiß ich natürlich nicht, was diese verdeckt noch so treibt...

      Kommentar


      • #4
        Erstmal vielen Dank für das Feedback.

        @jspit: Das prepare erfolgt in der PDO-Klasse im Rahmen der query-funktion

        PHP-Code:
        public function query($query,$params null$fetchmode PDO::FETCH_ASSOC)
                {
                    
        $query trim($query);

                    
        $this->Init($query,$params);

                    
        $rawStatement explode(" "$query);
                     ... 
        und


        PHP-Code:
        private function Init($query,$parameters "")
                {
                
        # Connect to database
                
        if(!$this->bConnected) { $this->Connect(); }
                try {
                        
        # Prepare query
                        
        $this->sQuery $this->pdo->prepare($query);
        .... 

        Ich werde das mit dem PDO::PARAM_INT gleich mal testen. mich wundert eben nur dass es lokal funktioniert.

        Kommentar


        • #5
          Du versuchst Parameter aber vor deiner query-funktion zu binden. Wenn das deine PDO-Klasse abfängt, ist es ok.

          Kommentar


          • #6
            Der Fehler lag tatsächlich darin das LIMIT zu binden. Mit dem PDO::PARAM_INT hat´s funktioniert. Vielen Dank für die Hilfe .)

            Kommentar

            Lädt...
            X