Ankündigung

Einklappen
Keine Ankündigung bisher.

mein PDO-Projekt - Problem beim Update

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

  • mein PDO-Projekt - Problem beim Update

    Moin!

    ich möchte einen Datensatz mittels PDO ändern und habe dafür eine Funktion erstellt die zugehörige Ausdrucke aus Namen zusammenstellt.

    Die Funktion sieht wie folgt aus:

    PHP-Code:
      public function PDO_CreateSQL2Update($index){
        
    $PDO_statement "UPDATE `".$this->tabelle."` SET ";
        
    $seperator_statement "";
        foreach (
    $this->controls as $control)
          {

          if (
    $control["column"] != "ID"){ //ID übergeben
            // prepare() bereitet die Anweisung für die Ausführung vor.
            
    $PDO_statement .= $seperator_statement."'".$control["column"]."` = :".$control["column"];
            
    $seperator_statement ",";
          }
    //endif
        
    }//end-foreach

        // ID anhängen mit dem WHERE ....
        
    $PDO_statement .= " WHERE `id` = :id)";

        echo 
    "PDO_statement:= ".$PDO_statement."<br>\n";

        try {
          
    $update $this->db->prepare($PDO_statement);
        } catch (
    Exception $e) {
          echo 
    'Exception abgefangen: ',  $e->getMessage(), "\n";
         }

          echo 
    "update:<br>\n";
          
    print_r($update);

        foreach (
    $this->controls as $control)
          {
          
    $befehl "':".$control["column"]."'";
          echo 
    "bind:= ".$befehl."<br>\n";
          echo 
    "post:= ".$_POST[$control["column"]]."<br>\n";
              
    $update->bindValue(":".$control["column"], $_POST[$control["column"]]);
          }
    //end-foreach

        // $update->execute() führt die vorbereitete Anweisung aus.
        
    if ($update->execute()) {
          echo 
    '<p>Die Nachricht wurde überschrieben.</p>';
        } else {
          
    // SQL-Fehlermeldung anzeigen.
          
    print_r($update->errorInfo());
        } 
    // endif

      
    }//end-CreateSQL2Update

      // Überschrift für die laufende Nummer
      
    public function CreateHeaderLfd(){
       if (
    $this->lfd_nr > -1){
         
    $this->CreateCell("Lfd-Nr.",true);
       }
    //endif
      
    }//end-function-PDO_CreateSQL2Update 
    Ich habe einige Kontrollausgaben gemacht und bekomme folgendes angezeigt:

    PDO_statement:= UPDATE `RECHNER` SET 'PCNUMMER` = :PCNUMMER,'ID_BETRIEBSSYSTEME` = :ID_BETRIEBSSYSTEME,'ID_ANWENDER` = :ID_ANWENDER,'ID_SACHGEBIETE` = :ID_SACHGEBIETE,'ID_BEREICHE` = :ID_BEREICHE,'CONFIG` = :CONFIG,'IS_STANDARD_TB` = :IS_STANDARD_TB,'IS_AKTIV` = :IS_AKTIV,'ANMERKUNG` = :ANMERKUNG WHERE `id` = :id)
    update:
    bind:= :PCNUMMER
    post:= RW15-PC-002
    Als Fehlermeldung bekomme ich (das ist die Zeile mit $update->bindValue):

    Fatal error: Call to a member function bindValue() on boolean in C:\PHProject\EBL_SoftwareInventar\ebl_class_crud.p hp on line 865

    Ich kann das nicht nachvollziehen.

    Eine Abfrage aus der Datenbank habe ich beireits weiter oben erfolgreich ausgeführt. Damit ist die Verbindung ok.

    $update wird ja auch schon einmal ausgeführt und obwohl ich dieses in ein try-catch gelegt habe wird dort kein Fehler angezeigt.

    Kann mir einer weiterhelfen? Vielleicht wie ich mir Parameter für die Variable $update anzeigen lassen kann. Derzeit macht diese für mich nur einen leeren Eindruck.

    Gruß Jan


  • #2
    Dreh das Error-Reporting von PDO auf:

    PHP-Code:
    $db = new PDO("mysql:host=$host; dbname=$dbname"$user$password, [
        
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    ]); 

    Kommentar


    • #3
      Moin!

      danke erst einmal für die schnelle Rückmeldung!

      Du meinst ich solle aus:

      PHP-Code:
        $db = new PDO('sqlite:' $database_name); 
      soll ich

      PHP-Code:
      $db = new PDO('sqlite:' $database_name[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); 
      machen?

      Wenn ich jetzt ausführe bekomme ich folgende Meldung:

      Warning: PDO::__construct() expects parameter 2 to be string, array given in C:\PHProject\EBL_SoftwareInventar\db_connect.php on line 10
      Infolgedesse wird jetzt auch weiter "unten" für die Zeile

      PHP-Code:
       $this->db_result $this->db->query($this->sql); 
      dieses gemeldet:

      Fatal error: Call to a member function query() on null in C:\PHProject\EBL_SoftwareInventar\ebl_class_crud.p hp on line 179

      Habe nun nochmal weiter gesucht, falls das für Sqlite etwas anders aussehen könnte und dieses gefunden: https://stackoverflow.com/questions/...ite-connection

      Daraufhin habe ich meine Funktion so gebaut:

      PHP-Code:
       $db = new PDO('sqlite:' $database_name);
          
      $db->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION); 
      Nun läuft das Programm besser durch - aber es folgt jetzt diese zusätzliche Info:

      Notice: Undefined variable: update in C:\PHProject\EBL_SoftwareInventar\ebl_class_crud.p hp on line 865
      Aber warum ist update undefiniert????

      Ich hatte jetzt die Vermutung das es damit zusammenhängt, dass ich das ganze in ein Try-Catch gelegt hatte. Also auskommentiert und dann kommt folgende Fehlermeldung:

      Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 1 near "ID_BETRIEBSSYSTEME": syntax error' in C:\PHProject\EBL_SoftwareInventar\ebl_class_crud.p hp:851 Stack trace: #0 C:\PHProject\EBL_SoftwareInventar\ebl_class_crud.p hp(851): PDO->prepare('UPDATE `RECHNER...') #1 C:\PHProject\EBL_SoftwareInventar\ebl_class_crud.p hp(20: EBL_CRUD->PDO_CreateSQL2Update(-1) #2 C:\PHProject\EBL_SoftwareInventar\ebl_class_crud.p hp(129): EBL_CRUD->AktionUpdate() #3 C:\PHProject\EBL_SoftwareInventar\rechner.php(3: EBL_CRUD->execute() #4 {main} thrown in C:\PHProject\EBL_SoftwareInventar\ebl_class_crud.p hp on line 851
      Das sagt Euch bestimmt mehr - aber was???

      Ich werde das Posting über das Wochenende weiter mitlesen - muss jetzt allerdings meinen Arbeitsplatz verlassen.

      Schönes Wochenende.

      Gruß Jan

      PS:
      Da wird zwar von ID_BETRIEBSSYSTEME gesprochen, aber nach meinem Empfinden ist die Syntax wie bei den anderen Auslistungen.

      Kommentar


      • #4
        Du hast vor dem Spaltennamen ein ', aber anschliessend an den Spaltennamen ein `, nicht?

        Kommentar


        • #5
          Danke - kleiner Fehler wohl, mit großer Wirkung.

          Am Montag geht es dann weiter!

          Montag: mit dem Ergebnis, dass der Fehler weg ist!

          Jan

          Kommentar


          • #6
            Moin!

            ich muss das Thema nochmal wieder aufgereifen mit dem PDO.

            Nun habe ich soweit die Ausdrücke zusammengestellt und hier zunächst mein Code an dieser Stelle:

            PHP-Code:
                  echo "update:<br>\n";
                  
            print_r($update);

                foreach (
            $this->controls as $control)
                  {
                  
            $befehl ":".$control["column"];
                  echo 
            "bind:= ".$befehl."<br>\n";
                  echo 
            "cdata:= ".$this->cdata[$control["column"]]."<br>\n";
                      
            $update->bindValue(":".$control["column"], $this->cdata[$control["column"]]);
                  }
            //end-foreach

                // $update->execute() führt die vorbereitete Anweisung aus.
                
            if ($update->execute()) {
                  echo 
            '<p>Die Nachricht wurde überschrieben.</p>';
                } else {
                  
            // SQL-Fehlermeldung anzeigen.
                  
            print_r($update->errorInfo());
                } 
            // endif 
            Dann nun einmal meine Kontrollausgaben:

            Code:
            PDO_statement:= UPDATE `RECHNER` SET 'PCNUMMER' = :PCNUMMER,'ID_BETRIEBSSYSTEME' = :ID_BETRIEBSSYSTEME,'ID_ANWENDER' = :ID_ANWENDER,'ID_SACHGEBIETE' = :ID_SACHGEBIETE,'ID_BEREICHE' = :ID_BEREICHE,'CONFIG' = :CONFIG,'IS_STANDARD_TB' = :IS_STANDARD_TB,'IS_AKTIV' = :IS_AKTIV,'ANMERKUNG' = :ANMERKUNG WHERE `id` = :id
            update:
            PDOStatement Object ( [queryString] => UPDATE `RECHNER` SET 'PCNUMMER' = :PCNUMMER,'ID_BETRIEBSSYSTEME' = :ID_BETRIEBSSYSTEME,'ID_ANWENDER' = :ID_ANWENDER,'ID_SACHGEBIETE' = :ID_SACHGEBIETE,'ID_BEREICHE' = :ID_BEREICHE,'CONFIG' = :CONFIG,'IS_STANDARD_TB' = :IS_STANDARD_TB,'IS_AKTIV' = :IS_AKTIV,'ANMERKUNG' = :ANMERKUNG WHERE `id` = :id ) bind:= :PCNUMMER
            cdata:= RW15-PC-002
            
            bind:= :ID_BETRIEBSSYSTEME
            cdata:= 3
            Als Beispiel betrachte ich nun einmal ID_BETRIEBSSYSTEME dessen Wert zuvor 2 war.

            Es kommt auch die Meldung, dass die Daten überschrieben wurden - also ist zumindest kein Fehler aufgetreten.

            Die Nachricht wurde überschrieben.
            Gehe ich dann aber in die Datenbank über DB Browser für SQLite oder eine PHP-Seite, dann werden mir die alten Werte angezeigt.

            Als Beispiel habe ich mir https://werner-zenk.de/scripte/sqlite_datenbank.php geöffnet.

            Nun bin ich am überlegen, ob man die Datenänderung noch irgendwie festschreiben muss. In dem Beispiel finde ich keine Hinweis. Im DB Brower muss man expliziet festschreiben.

            Kann mir einer weiterhelfen??

            Jan

            Kommentar


            • #7
              Da stehen doch immer noch Hochkommata anstatt Backticks im Query ?!

              Ausserdem bindest du nur 2 von insgesamt 9 Platzhaltern.

              Das dürfte eigentlich in keinster Weise in einer Erfolgsmeldung enden..
              Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

              Kommentar


              • #8
                Vielleicht auch mal das Handbuch zur Hand nehmen.
                Und für SQL Code bitte nicht die Zitate Tags nehmen, sondern die für Code.

                Kommentar


                • #9
                  Hi!

                  erst einmal danke.

                  Zwischenzeitlich mit einem INSERT auseinander gesetzt und das hat funktioniert. Es muss also ein Fehler innerhalb meiner Definition sein. Der DB-Zugriff an sich muss funktionieren. Wenigstens etwas. .-)

                  Jetzt Euren Rückmeldungen:

                  Das habe ich heute morgen geändert - das sieht jetzt so aus:

                  Code:
                  PDOStatement Object ( [queryString] => UPDATE `RECHNER` SET `PCNUMMER` = :PCNUMMER,`ID_BETRIEBSSYSTEME` = :ID_BETRIEBSSYSTEME,`ID_ANWENDER` = :ID_ANWENDER,`ID_SACHGEBIETE` = :ID_SACHGEBIETE,`ID_BEREICHE` = :ID_BEREICHE,`CONFIG` = :CONFIG,`IS_STANDARD_TB` = :IS_STANDARD_TB,`IS_AKTIV` = :IS_AKTIV,`ANMERKUNG` = :ANMERKUNG WHERE `id` = :id ) bind:= :PCNUMMER
                  Ausserdem bindest du nur 2 von insgesamt 9 Platzhaltern.
                  Das war nur ein "Auszug" - hätte ich dazuschreiben sollen.

                  [CODE]
                  bind:= :PCNUMMER
                  cdata:= RW15-PC-002
                  bind:= :ID_BETRIEBSSYSTEME
                  cdata:= 2
                  bind:= :ID_ANWENDER
                  cdata:= 38
                  bind:= :ID_SACHGEBIETE
                  cdata:= 8
                  bind:= :ID_BEREICHE
                  cdata:= 6
                  bind:= :CONFIG
                  cdata:= SG
                  bind:= :IS_STANDARD_TB
                  cdata:= 1
                  bind:= :IS_AKTIV
                  cdata:= 1
                  bind:= :ANMERKUNG
                  cdata:= XXX
                  [CODE]

                  Und für SQL Code bitte nicht die Zitate Tags nehmen, sondern die für Code.
                  So ?? - siehe #6

                  Jan

                  Kommentar


                  • #10
                    Da:
                    Code:
                     
                      bind:= :PCNUMMER
                    Und: Warum lässt du dir das nicht dynamisch erstellen und nutzt die Array-Bind-Variante? https://php-de.github.io/jumpto/pdo/#bind-array

                    Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                    PHP.de Wissenssammlung | Kein Support per PN

                    Kommentar


                    • #11
                      WHERE `id` = :id
                      Dat fehlt.... hab mich verzählt, es sind 10 Platzhalter, nicht 9.
                      Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

                      Kommentar


                      • #12
                        Hi!

                        Zitat von hausl Beitrag anzeigen
                        Da: ...
                        verstehe leider nicht, was Du mir sagen willst! Die Schreibweise sieht genauso aus wie bei den anderen und die Back... sind auch in dem Statement darüber wie bei den anderen.

                        Irgendwie habe ich den gelben Button mit 3 schwarzen Punkten heute angesteckt!

                        Zitat von hausl Beitrag anzeigen
                        Und: Warum lässt du dir das nicht dynamisch erstellen und nutzt die Array-Bind-Variante? https://php-de.github.io/jumpto/pdo/#bind-array
                        Weil ich einen anderen Weg in meinen Vorlagen gefunden habe und vom Aufbau mir das derzeit etwas einfacher erscheint - von meinem möglichen Fehler abgesehen.

                        Ich lege aber jetzt nochmal einen nach!

                        Für eine DropDownList will ich die Werte aus einer Kennliste abfragen mit einem einfachen SQL-Ausdruck:

                        Code:
                        SELECT * FROM 'BETRIEBSSYSTEME' ORDER BY 'id'
                        In meinem Code habe ich folgendes eingebaut:

                        PHP-Code:
                         public function GetKennValue4Edit($tabelle,$colname2show,$colname,$default=1,$order='ID'){
                            
                        $key "ID_".$tabelle;
                            
                        $sql "SELECT * FROM '".$tabelle."' ORDER BY 'id'";
                            
                        $statement $this->db->query($sql);
                            
                        $datensatz=$statement->fetch(PDO::FETCH_ASSOC);

                            echo 
                        "<br><br>key:= ".$key." - SQL:= ".$sql."<br>\n";

                            
                        print_r($statement); 

                        und bekomme nun diese Werte gelistet:

                        [CODE]
                        key:= ID_BETRIEBSSYSTEME - SQL:= SELECT * FROM 'BETRIEBSSYSTEME' ORDER BY 'id'
                        PDOStatement Object ( [queryString] => SELECT * FROM 'BETRIEBSSYSTEME' ORDER BY 'id' )
                        Array ( [ID] => 2 [BEZEICHNUNG] => Windows 7 [KURZBEZEICHNUNG] => Win7 [ANMERKUNG] => )
                        Array ( [ID] => 3 [BEZEICHNUNG] => Windows Server 2008R2 [KURZBEZEICHNUNG] => R8 [ANMERKUNG] => )
                        Array ( [ID] => 4 [BEZEICHNUNG] => Windows 8 [KURZBEZEICHNUNG] => Win8 [ANMERKUNG] => )
                        Array ( [ID] => 5 [BEZEICHNUNG] => Windows 8.1 [KURZBEZEICHNUNG] => Win8.1 [ANMERKUNG] => )
                        Array ( [ID] => 6 [BEZEICHNUNG] => Windows 10 [KURZBEZEICHNUNG] => Win10 [ANMERKUNG] => )
                        [CODE]

                        Setze ich die Abfrage im DB Browser ab, dann bekomme ich auch meinen ersten Eintrag zurück geliefert.

                        pdo_sql_ohne1.png























                        Es fehlt grundsätzlich der mit der ID=1

                        Eine Idee ??

                        Gruß Jan

                        Merkwürdigerweise wird bei

                        Code:
                        SELECT IS_AKTIV,ID, NACHNAME || ', ' || VORNAME FULLNAME FROM ANWENDER ORDER BY NACHNAME
                        alles geliefert!

                        Kommentar


                        • #13
                          fetch() holt immer nur den nächsten Datensatz. ein print_r() auf $statement finde ich eigenartig. Mach es richtig.. entweder mit fetch_all() in ein Array und das ausgeben lassen oder sauber eine Schleife und dann die einzelnen "ge-fetchten" je Durchlauf ausgeben.

                          Nochmals der Link: Siehe hier als Beispiel beide Varianten, weil du ja auch nur ein SELECT hast: https://php-de.github.io/jumpto/pdo/#no-param
                          PHP-Code:
                          $sql "
                              SELECT
                                  ID, BEZEICHNUNG, KURZBEZEICHNUNG, ANMERKUNG

                              FROM
                                  BETRIEBSSYSTEME

                              ORDER BY
                                  ID
                          "
                          ;

                          $stmt $pdo->prepare($sql);
                          $stmt->execute();
                          $arr $stmt->fetchAll();

                          print_r($arr); 
                          Und das man SELECT * nicht verwenden sollte wurde auch schon gesagt? Sonst ist es jetzt gesagt. SELECT * ist pfui! https://php-de.github.io/jumpto/code-smells/#select-all
                          Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                          PHP.de Wissenssammlung | Kein Support per PN

                          Kommentar


                          • #14
                            Eine Funktion sollte auch keine Ausgaben machen.
                            Warum machst du auch eine Klasse daraus?
                            PDO ist doch schon eine Klasse.

                            Kommentar


                            • #15

                              Hi!
                              Zitat von lstegelitz Beitrag anzeigen

                              Dat fehlt.... hab mich verzählt, es sind 10 Platzhalter, nicht 9.
                              das ist vielleicht etwas unglücklich dokumentiert. Da ID nicht in der "Liste" der Arrays einhalten ist kommt dieses erst im Anschluss in den Genuss der BIND-Funktionialität. Die Kontrollausgabe war nur in der Schleife.

                              PHP-Code:
                                foreach ($this->controls as $control)
                                    {
                                    
                              $befehl ":".$control["column"];
                                    echo 
                              "bind:= ".$befehl."<br>\n";
                                    echo 
                              "cdata:= ".$this->cdata[$control["column"]]."<br>\n";
                                        
                              $update->bindValue(":".$control["column"], $this->cdata[$control["column"]]);
                                    }
                              //end-foreach
                                    
                              $update->bindValue(":id"$index); 
                              Damit sind alle jetzt wieder beisammen.

                              Kann man irgendwie die Elemente einsehen, die mit BIND zusammengeführt / zugewiesen wurden?

                              @hausl:

                              Ich habe das jetzt einmal umgesetzt mit dem was Du mir für die Listenauswertung vorgeschlagen hat und siehe da - es funktioniert!

                              Dafür ein großes Dankeschön.

                              Bleibt also allgemein noch die Frage, warum wird der Datensatz nicht geändert.

                              Gruß Jan

                              Kommentar

                              Lädt...
                              X