Brombeermilchtrinker: Fehlermeldung bei UPDATE von Datensatz

Hallo Forum,

ich beschäftige mich jetzt schon mehrere Tage damit, eine Datenbank mit prepared Statements und der sqli-Erweiterung zu füllen und die Datensätze zu bearbeiten..

Beim Versuch, einen bestehenden Datensatz zu verändern, komme ich einfach nicht auf den Fehler. Dies ist mein Code:

   <?php  
     include("dbverbindung.php");  
     $id = (int)($_POST['id']);  
     $aendern = "UPDATE `001_dbtest` Set `001_name` = ?, `001_ort` = ?, `001_eintrag` = ? WHERE `001_id` = ?";  
     $kommando = $db->prepare($aendern);  
     $kommando->bind_param('sssi', $_POST['name'], $_POST['ort'], $_POST['eintrag'], $id);  
     $kommando->execute();  
     include("dbtrennung.php");  
     echo"<p>Die Daten wurden geändert.</p>\n";  
   ?>

Dies bewirkt die Fehlermeldung "Fatal error: Call to a member function bind_param() on a non-object in ..."

Ich habe nun versucht, so wie mir es dedlfix beigebracht hat, eine Fehleranalyse zu betreiben. Deshalb habe ich mit "var_dump" bei den 4 Parameter/Variablen eine Kontrollausgabe gemacht.

Die 4 Werte sind vorhanden und so wie es auch bei den PS steht, handelt es sich bei den ersten 3 um Strings, beim 4. Wert um eine Integer Zahl. Daran liegt es also nicht. Auch die Variablennamen stimmen 100%ig! Und auch bei der Syntax sehe ich keinen Fehler.

Kann mir bitte wer auf die Sprünge helfen?

Danke!

MfG

Der Brombeermilchtrinker

  1. Hi,

    $aendern = "UPDATE 001\_dbtest Set 001\_name = ?, 001\_ort = ?, 001\_eintrag = ? WHERE 001\_id = ?";
         $kommando = $db->prepare($aendern);
         $kommando->bind_param('sssi', $_POST['name'], $_POST['ort'], $_POST['eintrag'], $id);

    Dies bewirkt die Fehlermeldung "Fatal error: Call to a member function bind_param() on a non-object in ..."

    Ich habe nun versucht, so wie mir es dedlfix beigebracht hat, eine Fehleranalyse zu betreiben. Deshalb habe ich mit "var_dump" bei den 4 Parameter/Variablen eine Kontrollausgabe gemacht.

    Du hast aber vorher ueberhaupt nicht ueberprueft, *was* $db->prepare($aendern) dir zurueckgeliefert hat - ob also $kommando jetzt auch ein Objekt von einem Typ ist, der eine Methode bind_param besitzt.

    MfG ChrisB

    --
    „This is the author's opinion, not necessarily that of Starbucks.“
    1. Hi Chris,

      Du hast aber vorher ueberhaupt nicht ueberprueft, *was* $db->prepare($aendern) dir zurueckgeliefert hat - ob also $kommando jetzt auch ein Objekt von einem Typ ist, der eine Methode bind_param besitzt.

      verstehe ich Dich richtig? Du meinst, ich habe nicht überprüft, ob der Query richtig ist? Das kann ich ja über phpmyadmin nicht direkt machen, nachdeme s variable Werte sind. Oder wie meintest Du, daß ich das $db->prepare($aendern) überprüfen soll?

      MfG

      Der Brombeermilchtrinker

      1. Mahlzeit Brombeermilchtrinker,

        Du hast aber vorher ueberhaupt nicht ueberprueft, *was* $db->prepare($aendern) dir zurueckgeliefert hat - ob also $kommando jetzt auch ein Objekt von einem Typ ist, der eine Methode bind_param besitzt.

        verstehe ich Dich richtig? Du meinst, ich habe nicht überprüft, ob der Query richtig ist?

        Nein. Du hast nicht überprüft, was der Befehl

        $kommando = $db->prepare($aendern);

        Dir zurückliefert. In Deiner nächsten Anweisung

        $kommando->bind_param('sssi', $_POST['name'], $_POST['ort'], $_POST['eintrag'], $id);

        gehst Du davon aus, dass $kommando ein Objekt ist, das eine Methode namens bind_param() besitzt. Ist das so?

        Oder wie meintest Du, daß ich das $db->prepare($aendern) überprüfen soll?

        Du sollst überprüfen, was diese Methode Dir als Rückgabewert übergibt - z.B., ob es sich dabei wirklich um ein Objekt handelt.

        MfG,
        EKKi

        --
        sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
        1. Hi EKKi,

          Nein. Du hast nicht überprüft, was der Befehl

          $kommando = $db->prepare($aendern);

          Dir zurückliefert.

          Und wie überprüfe ich das?

          In Deiner nächsten Anweisung

          $kommando->bind_param('sssi', $_POST['name'], $_POST['ort'], $_POST['eintrag'], $id);

          gehst Du davon aus, dass $kommando ein Objekt ist, das eine Methode namens bind_param() besitzt. Ist das so?

          Was heißt denn "Ein Objekt, das eine Methode ... besitzt"?

          Oder wie meintest Du, daß ich das $db->prepare($aendern) überprüfen soll?

          Du sollst überprüfen, was diese Methode Dir als Rückgabewert übergibt - z.B., ob es sich dabei wirklich um ein Objekt handelt.

          Hm, ich stecke leider. Ich habe keine Probleme beim Anlegen, beim Zählen oder bei der Ausgabe von Datensätzen. Ich mach das so wie hier gelernt überall mit dem selben System wie hier beim UPDATE. Übrigens bezieht sich die Meldung "Fatal error: Call to a member function bind_param() on a non-object in..." auf die zeile "$kommando->bind_param('sssi', $_POST['name'], $_POST['ort'], $_POST['eintrag'], $id);"

          Hilft das weiter?

          MfG

          Der Brombeermilchtrinker

          1. Hi,

            In Deiner nächsten Anweisung

            $kommando->bind_param('sssi', $_POST['name'], $_POST['ort'], $_POST['eintrag'], $id);

            gehst Du davon aus, dass $kommando ein Objekt ist, das eine Methode namens bind_param() besitzt. Ist das so?

            Was heißt denn "Ein Objekt, das eine Methode ... besitzt"?

            Das detailierter zu Erklaeren, wuerde jetzt etwas zu weit fuehren - und wieder ins Manual, und deine Hassliebe zu diesem kennen wir ja ...

            Stark vereinfacht:

            Es gibt zwei weit verbreitete Programmier-Paradigmen, prozedurale und objekt-orientierte Programmierung.
            In der prozeduralen arbeitet man hauptsaechlich mit Funktionen, waehrend man in der objektorientierten hauptsaechlich Objekte betrachtet.
            Und solche Objekte koennen eigenen Methoden haben - das sind eigentlich Funktionen, aber sie sind an spezielle Objekte gebunden.
            Ein Objekt vom Typ auto koennte zum Beispiel Methoden wie starte_motor() oder tanke($kraftstoff) haben.

            In PHP ruft man die Methode eines Objektes auf, in dem man $objekt->methode() schreibt - und genau das machst du in obigem Code auch.
            Aber selbstverstaendlich kann das nur dann funktionieren, wenn $objekt auch ein Objekt ist, und  noch dazu eins von einem Typ, welches auch eine Methode namens methode besitzt.

            Du kkoennte zwar auch hund->starte_motor() aufzurufen versuchen oder apfel->tanke(diesel) - aber da kann wohl kaum was vernuenftiges bei herauskommen; und deshalb weist dich der Interpreter von PHP auch darauf hin, wenn du etwas derart "unmoegliches" versuchst.

            Hm, ich stecke leider. Ich habe keine Probleme beim Anlegen, beim Zählen oder bei der Ausgabe von Datensätzen.

            Dann hast du dabei bisher lediglich *Glueck* gehabt, wenn du dabei auf jegliche Erfolgskontrolle bei Objekterzeugungen und Methodenaufrufen ebenso verzichtet hast.

            Übrigens bezieht sich die Meldung "Fatal error: Call to a member function bind_param() on a non-object in..." auf die zeile "$kommando->bind_param('sssi', $_POST['name'], $_POST['ort'], $_POST['eintrag'], $id);"

            Hilft das weiter?

            Ja, siehe oben - $kommando ist nicht das, was du *erwartet* hast, also hat es auch keine Methode namens bind_param.

            MfG ChrisB

            --
            „This is the author's opinion, not necessarily that of Starbucks.“
            1. Hallo Forum,

              ich stelle meine Frage hier bei meinem alten Thread, da sie sehr verwandt ist.

              Folgender Code sucht im Feld "001_name" nach Einträgen, die einer Userangebe entsprechen. Der Suchbegriff wird als prepared Statement eingetragen. Die Sache funktioniert wie erwartet und liefert die korrekten Datensätze aus.

                  $sql = 'SELECT `001_id`, `001_name`, `001_ort`, `001_eintrag` FROM `001_test` WHERE `001_name` LIKE ? ORDER BY `001_id`';  
                  $ergebnis = $db->prepare( $sql );  
                  $ergebnis->bind_param('s', $suchwort );  
                  $ergebnis->execute();  
                  $ergebnis->bind_result( $id, $name, $ort, $eintrag );  
                  $count=1;  
                  while ($ergebnis->fetch())  
                  {  
                   $order= array("\r\n", "\n", "\r");  
                   $replace="<br />";  
                   $usereintrag=str_replace($order, $replace, htmlspecialchars($eintrag));  
                   echo "  <h5>".$count.") ".htmlspecialchars($name)." aus ".htmlspecialchars($ort)." mit der ID Nummer ".$id." :</h5>\n";  
                   echo "  <p>".$usereintrag."</p>\n";  
                   echo "  <p><a href=\"datenbearbeitung.php?id=".$id."\">BEARBEITEN</a></p>\n";  
                   echo "  <p><a href=\"loeschen.php?id=".$id."\">LÖSCHEN</a></p>\n";  
                   $count++;  
                  }
              

              Jetzt wollte ich die Sache erweitern. Ich habe ja auch andere Felder, in denen man suchen könnte. Nämlich Name, Ort und Eintrag. Auf der Suchmaske-Seite habe ich 3 Radiobuttons dazugegeben, über die man sich entscheiden muß, in welchem Feld gesucht werden soll. Mein Code auf der Verarbeitungsseite schaut nun so aus:

                  switch($_POST['suchfeld'])  
                   {  
                   case "name":  
                    $search="`001_name`";  
                    break;  
                   case "ort":  
                    $search="`001_ort`";  
                    break;  
                   case "eintrag":  
                    $search="`001_eintrag`";  
                    }  
                      $sql = 'SELECT `001_id`, `001_name`, `001_ort`, `001_eintrag` FROM `001_test` WHERE ? LIKE ? ORDER BY `001_id`';  
                  $ergebnis = $db->prepare( $sql );  
                  $ergebnis->bind_param('ss', $search, $suchwort );  
                  $ergebnis->execute();  
                  $ergebnis->bind_result( $id, $name, $ort, $eintrag );  
                  $count=1;  
                  while ($ergebnis->fetch())  
                  {  
                   $order= array("\r\n", "\n", "\r");  
                   $replace="<br />";  
                   $usereintrag=str_replace($order, $replace, htmlspecialchars($eintrag));  
                   echo "  <h5>".$count.") ".htmlspecialchars($name)." aus ".htmlspecialchars($ort)." mit der ID Nummer ".$id." :</h5>\n";  
                   echo "  <p>".$usereintrag."</p>\n";  
                   echo "  <p><a href=\"datenbearbeitung.php?id=".$id."\">BEARBEITEN</a></p>\n";  
                   echo "  <p><a href=\"loeschen.php?id=".$id."\">LÖSCHEN</a></p>\n";  
                   $count++;  
                  }
              

              Ich habe also nichts anderes gemacht, als den ersten (funktionierenden) Code statt mit 1 mit 2 prepared Statements verwendet, wobei das neue prepared Statement jetzt die "FROM"-Angabe ist.

              Es kommt keine Fehlermeldung, eine Seite wird ausgegeben, allerdings _immer_ mit null Datensätzen.

              Ich habe $search überprüft und das selbe auch mit einer COUNT Querry versucht. Auch hier null gezählte Datensätze. Das selbe Ergebnis, wenn ich bei der Variablen $search zb statt $search="001\_name"; ein $search="001_name"; schreibe, also ohne die `. Auch hier keine gefundenen Datensätze.

              Woran kann das liegen? Darf ich für den "FROM"-Begriff kein PS nehmen? Oder liegt der Fehler woanders?

              MfG

              Der Brombeermilchtrinker

              1. Ich meinte natürlich das WHERE-Feld, bei dem jetzt ein weiteres prepared Statement dazugekommen ist, sorry.

                Die Frage lautet also:

                Kann ich die Syntax $sql = 'SELECT 001_id, 001_name, 001_ort, 001_eintragFROM001_testWHERE ? LIKE ? ORDER BY001_id'; nicht verwenden?

                Und wenn doch, wo liegt dann mein Fehler?

              2. echo $begrüßung;

                $search="001\_name";
                    $sql = 'SELECT 001\_id, 001\_name, 001\_ort, 001\_eintrag FROM 001\_test WHERE ? LIKE ? ORDER BY 001\_id';
                    $ergebnis = $db->prepare( $sql );
                    $ergebnis->bind_param('ss', $search, $suchwort );
                Es kommt keine Fehlermeldung, eine Seite wird ausgegeben, allerdings _immer_ mit null Datensätzen.
                Woran kann das liegen? Darf ich für den "FROM"-Begriff kein PS nehmen? Oder liegt der Fehler woanders?

                Du hast keinen Platzhalter in der FROM-Klausel sondern in der WHERE-Klausel, aber das ist nicht das Problem. Ein Platzhalter steht für einen Wert, nicht für einen Bezeichner (Feldnamen u.ä.). Du übergibst links vom LIKE den String-Wert 001\_name. Die Backticks werden dabei als Stringbestandteil angesehen. Diesen Wert vergleichst du mit dem Suchbegriff. Das ist ein syntaktisch korrektes Statement und sieht ausgeschrieben ungefähr so aus:

                ... WHERE '001\_name' LIKE 'suchbegriff'

                Das Ergebnis kann dabei nur dann positiv werden, wenn der Suchbegriff 001\_name (inklusive Backticks) lautet. In allen anderen Fällen also wird die Bedingung nicht wahr.

                Du kannst den Feldnamen nur direkt in das SQL-Statement einfügen.

                echo "$verabschiedung $name";

                1. Hi dedlfix,

                  Das Ergebnis kann dabei nur dann positiv werden, wenn der Suchbegriff 001\_name (inklusive Backticks) lautet. In allen anderen Fällen also wird die Bedingung nicht wahr.

                  Du kannst den Feldnamen nur direkt in das SQL-Statement einfügen.Und genau _das_ wollte ich wisse, vielen Dank.

                  Das heißt für mich (in dem Fall), ich muß mir 3 verschiedene Querries vorbereiten.

                  $sql = 'SELECT 001_id, 001_name, 001_ort, 001_eintragFROM001_testWHERE001_nameLIKE ? ORDER BY001_id';

                  $sql = 'SELECT 001_id, 001_name, 001_ort, 001_eintragFROM001_testWHERE001_ortLIKE ? ORDER BY001_id';

                  $sql = 'SELECT 001_id, 001_name, 001_ort, 001_eintragFROM001_testWHERE001_eintragLIKE ? ORDER BY001_id';

                  Und je nach $_POST['suchfeld'] den richtigen Querry verwenden. Dann habe ich ein fest definiertes Feld, in dem gesucht wird und den Parameter weiterhin mit einem ? brav prepared.

                  Richtig?

                  MfG

                  der Brombeermilchtrinker

                  1. echo $begrüßung;

                    Das heißt für mich (in dem Fall), ich muß mir 3 verschiedene Querries vorbereiten.

                    Das kannst du so machen. Du kannst aber auch mit Stringverknüpfung den jeweiligen Feldnamen in den Rest des Statements einfügen.

                    echo "$verabschiedung $name";

                    1. Hi dedlfix,

                      Das kannst du so machen. Du kannst aber auch mit Stringverknüpfung den jeweiligen Feldnamen in den Rest des Statements einfügen.

                      Das ist vielleicht sogar noch besser, weil das den Code evt. etwas schlanker und übersichtlicher macht. Wobei ich nicht denke, dass dies merkbare Performanceauswirkungen hat.

                      Danke für Deine rasche Hilfe. Gut, dass ich jetzt weiß, nur für Argumente PS verwenden zu können.

                      Schönen Tag!

                      MfG

                      Der Brombeermilchtrinker

                      PS: Ich möchte noch anmerken, dass der Drillunterricht von Dir und ChrisB schon gewirkt hat bei mir. Obwohl ich keine Fehlermeldung bekommen habe, habe ich, bevor ich hier gepostet habe, eine halbe Stunde lang sämtliche Variablen un Teile des Codes überprüft. Und auch heute morgen, an völlig anderer Stelle, da _habe_ ich Fehlermeldungen bekommen und die Fehleranalyse so, wie von Euch gelernt, betrieben, bis ich den Fehler definitiv hatte. Ich habe somit ein Problem durch Auswertung und Analyse lösen können, ohne hier fragen zu müssen. Das war wirklich das _totale_ Erfolgserlebnis für mich!

      2. Hi,

        Du hast aber vorher ueberhaupt nicht ueberprueft, *was* $db->prepare($aendern) dir zurueckgeliefert hat - ob also $kommando jetzt auch ein Objekt von einem Typ ist, der eine Methode bind_param besitzt.

        verstehe ich Dich richtig?

        Nein.

        Du meinst, ich habe nicht überprüft, ob der Query richtig ist?

        Nein.

        Oder wie meintest Du, daß ich das $db->prepare($aendern) überprüfen soll?

        Du sollst den *Rueckgabewert* dieser Methode ueberpruefen, bevor du diesen weiter verwendest.

        MfG ChrisB

        --
        „This is the author's opinion, not necessarily that of Starbucks.“
        1. Hi Chris,

          Du sollst den *Rueckgabewert* dieser Methode ueberpruefen, bevor du diesen weiter verwendest.

          Und wie mache ich das am besten?

          MfG

          der Brombeermilchtrinker

          1. Hi,

            Du sollst den *Rueckgabewert* dieser Methode ueberpruefen, bevor du diesen weiter verwendest.

            Und wie mache ich das am besten?

            Also im Geduld-ueberstrapazieren gibst du dir wesentlich mehr Muehe, als im logisch Nachdenken ...

            var_dump, ver... noch eins.

            MfG ChrisB

            --
            „This is the author's opinion, not necessarily that of Starbucks.“
            1. Hi Chris,

              var_dump, ver... noch eins.

              Bitte nicht gleich schimpfen, ich bemüh mich eh! :-(

              Also bei

                $kommando = $db->prepare($aendern);  
                var_dump($kommando);
              

              bekomme ich ein " bool(false) " ausgegeben.

              Bedeutet das jetzt also, daß

              $aendern = "UPDATE 001_dbtestSet001_name= ?,001_ort= ?,001_eintrag= ? WHERE001_id = ?";

              kein Ergebnis liefert oder keine gültige Querry ist? Und wie gehe ich jetzt bei der Fehlersuche weiter vor?

              MfG

              Der Brombeermilchtrinker

              1. Hi,

                Also bei

                $kommando = $db->prepare($aendern);

                var_dump($kommando);

                
                >   
                > bekomme ich ein " bool(false) " ausgegeben.  
                  
                Siehst du - und false ist kein Objekt, welches eine Methode namens bind\_param haette - \*deshalb\* also im naechsten Schritt die Meldung von PHP, wo du versuchst $kommando->bind\_param aufzurufen, obwohl $kommando nach obiger Zuweisung eben nur false enthaelt.  
                  
                
                > Bedeutet das jetzt also, daß  
                >   
                > `$aendern = "UPDATE `001_dbtest` Set `001_name` = ?, `001_ort` = ?, `001_eintrag` = ? WHERE `001_id` = ?";`{:.language-php}  
                >   
                > kein Ergebnis liefert oder keine gültige Querry ist?  
                  
                Ein Ergebnis kann die Query noch gar nicht geliefert haben, weil sie ja noch nicht ausgefuehrt wurde, sondern bisher nur "vorbereitet" - auf Englisch prepared.  
                  
                
                > Und wie gehe ich jetzt bei der Fehlersuche weiter vor?  
                  
                Wie immer beim Umgang mit MySQLi, wenn dabei irgendwas schief ging - [mysqli->error](http://www.php.net/manual/en/mysqli.error.php) befragen.  
                  
                In deinem Falle ist die Referenz auf die Instanz des MySQLi-Objektes in $db gespeichert, also $db->error ausgeben lassen - nach dem Methodenaufruf, der offenbar fehlerhaft verlaufen ist, also hier nach dem $db->prepare.  
                  
                MfG ChrisB  
                  
                
                -- 
                „This is the author's opinion, not necessarily that of Starbucks.“
                
                1. Hi Chris,

                  Und wie gehe ich jetzt bei der Fehlersuche weiter vor?

                  Wie immer beim Umgang mit MySQLi, wenn dabei irgendwas schief ging - mysqli->error befragen.

                  OK, ich habe jetzt etwas herumgedoktert und folgender Code

                  $kommando = $db->prepare($aendern);
                     var_dump($kommando);
                     printf("Errormessage: %s\n", $db->error);

                  brachte die Ausgabe "bool(false) Errormessage: Table 'db151444.001_dbtest' doesn't exist".

                  Ich Idiot! Klar, die Tabelle heißt "001_test", ohne dem "db". Wenn ich jetzt die Fehlerausgabe noch lasse und den richtigen Namen in die Query schreibe, dann funktioniert die Datensatzänderung und die 2 Ausgeben sind:

                  " object(mysqli_stmt)#2 (0) { } Errormessage: "

                  Mein Problem ist zwar gelöst, aber ich würd trotzdem noch gerne die var_dump Ausgabe besser verstehen:

                  object(mysqli_stmt)#2 (0) { } sagt mir mal, daß $kommando ein Objekt mit der Methode "mysqli_stmt" ist, hab ich das richtig verstanden? Und was sagt das "#2 (0) { }" aus?

                  Ich habe gerade mehrmals deine Erklärung zu meiner Frage "Was heißt denn "Ein Objekt, das eine Methode ... besitzt"?" gelesen. Das ist aber schon _sehr_ verwirrend, hm? :-) Aber ich denke, ich hab die _Grundzüge_ dessen, worum es geht, halbwegs verstanden. Ohe Deiner Erklärung stünde ich jetzt _noch_ dümmer da.

                  Ach ja, das wollt ich auch noch fragen, Du sagtes vorher:

                  »»»» Hm, ich stecke leider. Ich habe keine Probleme beim Anlegen, beim Zählen oder bei der Ausgabe von Datensätzen.

                  Dann hast du dabei bisher lediglich *Glueck* gehabt, wenn du dabei auf jegliche Erfolgskontrolle bei Objekterzeugungen und Methodenaufrufen ebenso verzichtet hast.

                  Wie meintest Du das? Nehmen wir als Beispiel das Anlegen eines neuen Datensatzes. Das habe ich so gelöst:

                       include("dbverbindung.php");  
                       $sql = 'INSERT INTO `001_test` (`001_name`, `001_ort`, `001_eintrag`) VALUES (?, ?, ?)';  
                       $kommando = $db->prepare($sql);  
                       var_dump($kommando);  
                       $kommando->bind_param('sss', $_POST['name'], $_POST['ort'], $_POST['eintrag']);  
                       $kommando->execute();  
                       include("dbtrennung.php");  
                       echo"<p>Die Daten wurden eingetragen.</p>\n";
                  

                  Und das funktioniert. Hab ich Dich richtig verstanden, daß ich es nicht dabei belassen soll, daß es funktioniert sondern daß es einen guten Programmierer [1] auszeichnet, jetzt _totzdem_ Überprüfungen zu machen. Und wenn ja, wie würdest Du da vorgehen jetzt?

                  MfG

                  Der Brombeermilchtrinker

                  [1] Damit will ich mich natürlich _nicht_ als guten Programmierer bezeichnen. Aber ich würd zumindest gerne jene Standards einhalten und beachten, damit Leute wie Du oder dedlfix sich nicht an die Stirn greifen müssen, wenn Sie meinen Code sehen. :-)

                  1. echo $begrüßung;

                    " object(mysqli_stmt)#2 (0) { } Errormessage: "
                    Mein Problem ist zwar gelöst, aber ich würd trotzdem noch gerne die var_dump Ausgabe besser verstehen:

                    Der Typ der Variablen ist object. Ein Objekt gehört immer einer Klasse an. In dem Fall heißt die Klasse mysqli_stmt. Das #2 ist uninteresant. Die 0 in Klammern gibt die Größe einer Variablen an. Im Falles von Objekten heißt das, dass es keine Eigenschaften hat. Methoden werden nicht gezählt. Da es keine Eingenschaften hat, können diese auch nicht innerhalb der { }-Klammern angezeigt werden.

                    Versuch doch mal die var_dump-Ausgabe von verschiedenen Datentypen anzeigen zu lassen und diese zu verstehen. Welche es alle gibt, stehen in auf der verlinkten Handbuchseite. Als kleinen Tipp zeige ich die, wie das mit einem einfachen Objekt geht:

                    $a->b = 42;
                      var_dump($a);

                    Als Klasse bekommst du stdClass angezeigt. Da da Objekt $a on-the-fly erzeugt wurde, hat es keine explizite Klasse und bekommt die Default-Klasse stdClass zugewiesen.

                    Dann hast du dabei bisher lediglich *Glueck* gehabt, wenn du dabei auf jegliche Erfolgskontrolle bei Objekterzeugungen und Methodenaufrufen ebenso verzichtet hast.
                    [...] wie würdest Du da vorgehen jetzt?

                    Schau auf die Handbuchseite zu mysqli::prepare(). Das dortige Beispiel zeigt eine einfache Erfolgskontrolle.

                    echo "$verabschiedung $name";

                    1. Hi dedlfix,

                      auch Dir danke für die Erklärungen und die Problemhilfe.

                      Versuch doch mal die var_dump-Ausgabe von verschiedenen Datentypen anzeigen zu lassen und diese zu verstehen.

                      Diesen Tip werde ich beherzigen!

                      Schönen Abend noch!

                      Der Brombeermilchtrinker

                  2. Hi,

                    Mein Problem ist zwar gelöst, aber ich würd trotzdem noch gerne die var_dump Ausgabe besser verstehen:

                    object(mysqli_stmt)#2 (0) { } sagt mir mal, daß $kommando ein Objekt mit der Methode "mysqli_stmt" ist, hab ich das richtig verstanden?

                    Nein, es ist ein Objekt vom Typ MySQLi_STMT. Genau so eins soll die Methode prepare des MySQLi-Objektes im Erfolgsfalle ja zurueckliefern - was hiermit jetzt auch kontrolliert waere.

                    Und was sagt das "#2 (0) { }" aus?

                    Die #0 duerfte vermutlich eine Ressourcen-Kennung sein, und { } besagt, dass das Objekt weiter keinen Inhalt hat, der sich an dieser Stelle sinnvoll in Textform repraesentieren liesse - dass muss uns jetzt in diesem Falle aber beides nicht weiter interessieren, denn was wir wissen wollten/mussten, wissen wir ja jetzt - wir haben erfolgreich ein Objekt vom Typ MySQLi_STMT erzeugt, und koennen damit anschliessend weiter arbeiten.

                    Das war jetzt erst mal die detailierte Fehlersuche.
                    Normalerweise wirst du aber auf deiner Webseite keine Kontrollausgabe in der Form, wie var_dump sie hier geliefert hat, dem Benutzer zeigen wollen.

                    Also fragt man da normalerweise nur ab, ob die prepare-Methode false zurueckgeliefert hat, oder nicht - denn das ist laut Handbuch ihr definiertes Verhalten, sie liefert entweder ein Objekt vom Typ MySQLi_STMT im Erfolgsfall, oder false bei einem Fehler.

                    Also schreibt man sowas normalerweise eher in der Form:

                    if(!($kommando = $db->prepare($aendern)) { // wenn der Rueckgabewert false ist  
                      // hier eine Fehlermeldung fuer den Benutzer ausgeben,  
                      // weitere Verarbeitung abbrechen  
                    }  
                    $kommando->bind_param(...); // hier mit erfolgreich erstelltem MySQLi_STMT weiterarbeiten
                    

                    Ich habe gerade mehrmals deine Erklärung zu meiner Frage "Was heißt denn "Ein Objekt, das eine Methode ... besitzt"?" gelesen. Das ist aber schon _sehr_ verwirrend, hm? :-)

                    Ich weiss nicht, ob ich es "gut" erklaert habe.
                    Das ist halt ein umfangreiches Thema, und demzufolge schwer in zwei Saetzen abzuhandeln. Aber ich wollte an der Stelle nicht weiter ausholen, als noetig - denn auf dich stroemt ja gerade sowieso genug an neuen Informationen ein. (Du koenntest uebrigens MySQLi auch nicht objektorientiert, sondern auf prezedurale Weise nutzen - ohne Objekte zu erzeugen, nur mit Funktionen; das aber nur der Vollstaendigkeit halber, jetzt bleibe lieber mal bei dem bestehenden Code, den du hast, sonst wird das noch verwirrender.)

                    Dann hast du dabei bisher lediglich *Glueck* gehabt, wenn du dabei auf jegliche Erfolgskontrolle bei Objekterzeugungen und Methodenaufrufen ebenso verzichtet hast.

                    Wie meintest Du das? Nehmen wir als Beispiel das Anlegen eines neuen Datensatzes. Das habe ich so gelöst:

                    //...

                    $kommando->execute();
                         include("dbtrennung.php");
                         echo"<p>Die Daten wurden eingetragen.</p>\n";

                      
                    Paradebeispiel :-)  
                      
                    Du vermeldest hier, die Daten seien eingetragen worden - aber \*ueberprueft\* hast du das nicht.  
                      
                    
                    > Und das funktioniert. Hab ich Dich richtig verstanden, daß ich es nicht dabei belassen soll, daß es funktioniert sondern daß es einen guten Programmierer [1] auszeichnet, jetzt \_totzdem\_ Überprüfungen zu machen.  
                      
                    Das unterscheidet nicht nur den "guten" Programmierer von anderen - sondern letztendlich auch den zufriedenen Benutzer von einem enttaeuschten. Du vermeldest, "die Daten wurden eingetragen", aber wir nehmen mal an, das haette nicht geklappt (ueberprueft haben wir es ja noch nicht) - dann will der Benutzer sich jetzt seinen neuen Datensatz anzeigen lassen, aber der ist nirgendwo zu finden - "Hey, aber mir wurde doch gesagt, Daten wurden eingetragen ...?"  
                      
                    
                    > Und wenn ja, wie würdest Du da vorgehen jetzt?  
                      
                    Du hast $kommando->execute() aufgerufen, um die INSERT-Query, die zunaechst prepared und dann auch mit Daten versorgt(bind\_param( wurde, jetzt auch von der Datenbank ausfuehren zu lassen.  
                      
                    Auch dabei koennen noch Dinge schief gegangen sein. Syntaktische Fehler kann unsere Query jetzt zwar nicht mehr enthalten - das waere uns beim prepare-n des Statements aufgefallen (wie im vorliegenden Fall, falschen Tabellennamen angegeben). Aber es koennte zum Beispiel sein, dass auf der Spalte 001\_name in der Definition in der Datenbank ein "unique Index" liegt, weil jeder Name nur einmal eingetragen werden koennen soll.  
                    Waere der Name, den der Benutzer einzutragen versucht, schon vorhanden, dann \*muss\* diese Query, die ihn erneut einzutragen versucht, also schief gehen.  
                      
                    Schauen wir uns also wieder im Handbuch an, was die [execute](http://www.php.net/manual/en/mysqli-stmt.execute.php)-Methode des MySQLi\_STMT-Objektes uns ueber ihren Rueckgabewert mitzuteilen hat:  
                    "Returns TRUE on success or FALSE on failure."  
                      
                    Auch das koennen wir also wieder recht simpel auswerten, z.B. a la  
                    ~~~php
                    if(!$kommando->execute()) {  
                      echo "<p>Tut uns leid, da trat leider ein Fehler auf!<p>\n";  
                    }  
                    else {  
                      echo "<p>Die Daten wurden eingetragen.</p>\n";  
                    }
                    

                    Welcher Fehler das war, weiss der Benutzer damit noch nicht.
                    Die genaue Meldung der Datenbank wuerden *wir*, die Programmierer, uns jetzt wieder mittels $kommando->error ausgeben lassen. Das ist dann aber wieder sowas technisches, noch dazu Englisches - das wollen wir dem Benutzer nicht zumuten.

                    Wenn wir dem Benutzer jetzt aber noch den Grund mitteilen wollten, dass es hier daran lag, dass er Name, den er eintragen wollte, schon vorhanden war - dann koennten wir auch $kommando->errno auswerten. Das liefert uns eine Fehler*nummer*, und auch die sind irgendwo dokumentiert. Das wuerden wir dann ueberpruefen, ob das die Nummer ist, die bei einem solchen Fehler gemeldet wird - und dann koennten wir den Benuzter auch darauf noch explizit hinweisen, dass es im konkreten Fall daran lag, dass der Name schon vorhanden ist ...

                    MfG ChrisB

                    --
                    „This is the author's opinion, not necessarily that of Starbucks.“
                    1. Hi Chris,

                      aaahhhh .... verstehe, _diese_ Art der Kontrolle meintest Du. Ich hab das dann falsch verstanden, ich dachte, Du meintest, ich muß jetzt trotzdem überprüfen ob der Code per se stimmt. Und das kam mir so komisch vor, weil ich (ich als Programmierer) sehe ja sofort zB über myphpadmin, daß der Datensatz eingetragen worden ist. Aber jetzt ist natürlich klar, wie Du das gemeint hast.

                      object(mysqli_stmt)#2 (0) { } sagt mir mal, daß $kommando ein Objekt mit der Methode "mysqli_stmt" ist, hab ich das richtig verstanden?

                      Nein, es ist ein Objekt vom Typ MySQLi_STMT. Genau so eins soll die Methode prepare des MySQLi-Objektes im Erfolgsfalle ja zurueckliefern - was hiermit jetzt auch kontrolliert waere.

                      Verstehe.

                      Das war jetzt erst mal die detailierte Fehlersuche.
                      Normalerweise wirst du aber auf deiner Webseite keine Kontrollausgabe in der Form, wie var_dump sie hier geliefert hat, dem Benutzer zeigen wollen.

                      Nein, natürlich nicht, das hab ich ja nur ins Spiel gebracht, weil ich beim Testen des Programmcodes nur eine Fehlermeldung und kein Ergebnis bekommen habe.

                      Also fragt man da normalerweise nur ab, ob die prepare-Methode false zurueckgeliefert hat, oder nicht - denn das ist laut Handbuch ihr definiertes Verhalten, sie liefert entweder ein Objekt vom Typ MySQLi_STMT im Erfolgsfall, oder false bei einem Fehler.

                      Alles klar.

                      Ich weiss nicht, ob ich es "gut" erklaert habe.

                      Das hat nicht geheißen, daß Du es "schlecht" erklärt hast. Und wenn so ein DAU wie _ich_ danach zumindest _etwas_ klarer sieht, kann es ja schon nicht mal mehr so schlecht gewesen sein. :-)

                      Den rest Deiner Ausführungen bzgl. der Überprüfung habe ich verstanden. Danke!

                      MfG

                      Der Brombeermilchtrinker

  2. echo $begrüßung;

    $kommando = $db->prepare($aendern);
         $kommando->bind_param('sssi', $_POST['name'], $_POST['ort'], $_POST['eintrag'], $id);

    Dies bewirkt die Fehlermeldung "Fatal error: Call to a member function bind_param() on a non-object in ..."

    Die Meldung besagt, dass eine Methode (Funktion) eines Objekts aufgerufen werden soll, aber gar kein Objekt vorliegt. Genauer gesagt: $kommando ist kein Objekt.

    Ich habe nun versucht, so wie mir es dedlfix beigebracht hat, eine Fehleranalyse zu betreiben. Deshalb habe ich mit "var_dump" bei den 4 Parameter/Variablen eine Kontrollausgabe gemacht.

    Mach die Kontrollausgabe auf $kommando, dann siehst du, dass es kein Objekt ist. Die Ursache ist eine Zuweisung, die nicht so ausgeführt wurde, wie du dir das vorgestellt hast. Es muss also von $db->prepare($aendern) etwas unerwartetes zurückgegeben worden sein. Nun kommt das PHP-Handbuch ins Spiel, dass dich darüber aufzuklären versucht, in welchen Fällen mysqli::prepare() dieses unerwartete Ergebnis liefert und auch im Beispiel zeigt, wie man den Folgefehler unterbinden kann, indem man auf die Eigenschaften des von mysqli::prepare() zurückgegebenen Objekts nur im Gut-Fall zugreift.

    Die eigentliche Fehlerursache findest du übrigens in $db->error (siehe auch mysqli::error).

    echo "$verabschiedung $name";