Martin_Online: Benutzer registieren

0 45

Benutzer registieren

Martin_Online
  • php
  1. 0
    Tom
    1. 0
      Tom
  2. 0
    ChrisB
    1. 0
      Martin_Online
      1. 0
        Martin_Online
        1. 1
          ChrisB
          1. 0
            Martin_Online
            1. 0
              Tom
              1. 0
                Martin_Online
                1. 0

                  in_array() und strict

                  Tom
            2. 0

              Benutzer registieren, Unterschied zwischen Insert und Select

              Tom
              • datenbank
              1. 0
                Martin_Online
                1. 2

                  PDO oder MySQLi ?

                  Tom
      2. 0
        Der Martin
  3. 0

    Login funktin

    Martin_Online
    1. 0
      Tom
      1. 0
        Tom
      2. 0
        Martin_Online
      3. 0
        dedlfix
        1. 0
          Martin_Online
    2. 1
      dedlfix
      1. 0
        Tom
        1. 0
          dedlfix
      2. 0
        Martin_Online
        1. 0
          dedlfix
          1. 0
            Martin_Online
            1. 1
              dedlfix
              1. 0

                Login funktin - Fehler gefunden :(

                Martin_Online
                1. 0
                  dedlfix
                  1. 0
                    Martin_Online
                    1. 0
                      Der Martin
                      1. 0
                        dedlfix
                        1. 0
                          Der Martin
                          1. 0

                            Blamiere dich täglich

                            Tom
                            • menschelei
                      2. 0
                        Tom
                        1. 0
                          dedlfix
                          1. 0
                            Tom
                            1. 0
                              Martin_Online
  4. 0

    Datenbankstruktur - Logindaten & Userdaten

    Martin_Online
    1. 0
      dedlfix
  5. 0

    Zusatzfrage

    Martin_Online
    1. 0
      Der Martin
      1. 0
        Martin_Online
      2. 0
        M.

Hallo,

eine Frage zu meiner Registierung, dieser Bereich fehlt noch auf meiner Seite. Derzeit prüfe ich die Felder wie folgt:

  
if(trim($_POST['passwort'])=='' && trim($_POST['passwortWDH'])=='') {  
      $errors[] = "Bitte geben Sie ein Passwort an";  
}  
  
if($_POST['passwort'] !== $_POST['passwortWDH']) {  
      $errors[] = "Passwörter stimmen nicht überein";  
}  
  
if(empty($_POST['nickname'])) {  
      $errors[] = "Bitte geben Sie Ihren Benutzername an";  
}  
  

nun könnte sich ein User mit einer eMail Adresse zweimal anmelden, das möchte ich natürlich nicht. Hab nun in verschiedenen Tutorials zwei Optionen gelesen.

1.) Ich schreibe ein SQL prüfe mit WHERE email = xxx wenn etwas zurück kommt, ist diese eMail Adresse bereits vorhanden.

2.) Ich setzte auf das Feld email ein indize, schau ob im Error das Wort „Duplicate“ vorkommt, wenn ja, wird diese eMail bereits verwendet.

Was sagt ihr, welche Version soll ich nehmen bzw. gibt es noch eine andere Möglichkeit dieses zu prüfen?

  1. Hello,

    nun könnte sich ein User mit einer eMail Adresse zweimal anmelden, das möchte ich natürlich nicht. Hab nun in verschiedenen Tutorials zwei Optionen gelesen.

    1.) Ich schreibe ein SQL prüfe mit WHERE email = xxx wenn etwas zurück kommt, ist diese eMail Adresse bereits vorhanden.

    Das wäre falsch.
    Siehe http://de.wikipedia.org/wiki/Time-of-Check-to-Time-of-Use-Problem

    2.) Ich setzte auf das Feld email ein indize, schau ob im Error das Wort „Duplicate“ vorkommt, wenn ja, wird diese eMail bereits verwendet.

    Das wäre fast richtig:
    Je ein Unique Index wäre erforderlich auf allen SPALTEN, die keine Doubletten enthalten dürfen.
    siehe http://dev.mysql.com/doc/refman/5.1/de/constraint-primary-key.html
    und http://dev.mysql.com/doc/refman/5.1/de/error-messages-server.html
    und http://de2.php.net/manual/en/mysqli.connect-errno.php

    Was sagt ihr, welche Version soll ich nehmen bzw. gibt es noch eine andere Möglichkeit dieses zu prüfen?

    Die richtige!

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bikers-lodge.com
    1. Hello,

      und http://de2.php.net/manual/en/mysqli.connect-errno.php

      Das sollte http://de2.php.net/manual/en/mysqli.errno.php werden,
      damit du die 1022 abfragen kannst.

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
       ☻_
      /▌
      / \ Nur selber lernen macht schlau
      http://bikers-lodge.com
  2. Hi,

    2.) Ich setzte auf das Feld email ein indize, schau ob im Error das Wort „Duplicate“ vorkommt, wenn ja, wird diese eMail bereits verwendet.

    Jein.

    UNIQUE Index natürlich schon – aber bitte nicht in Text-Fehlermeldungen rumsuchen, sondern den nummerischen Fehlercode entsprechend auswerten.

    MfG ChrisB

    --
    Autocomplete has spoiled me to a point where it happens every so often that I encounter a CAPTCHA, and I just type in the first character … and then wait for the rest of the code to be automatically suggested :/
    1. UNIQUE Index natürlich schon – aber bitte nicht in Text-Fehlermeldungen rumsuchen, sondern den nummerischen Fehlercode entsprechend auswerten.

      UNIQUE Index habe ich auf nickname und emailadresse gesetzt! Mein Script sieht nun so aus:

        
      $stmt = $mysqli->prepare("INSERT INTO web_users (nickname, emailadresse) VALUES (?, ?)");  
      $nickname = $_POST["nickname"];  
      $emailadresse = $_POST["emailadresse"];  
      $stmt->bind_param("ss", $nickname, $emailadresse);  
        
      if(!$stmt->execute()){  
      	echo $mysqli->errno;  
      }  
      
      

      wenn ich nun versuche zwei gleiche eMail Adressen Einzutragen bekomme ich diese Fehlermeldung "1062"

      Wie kann ich jetzt mit dieser Fehlermeldung hier weiter arbeiten?

        
              if(empty($_POST['emailadresse'])){  
                  $errors[] = "Bitte geben sie Ihre eMail Adresse an";  
              } elseif (filter_var($_POST['emailadresse'], FILTER_VALIDATE_EMAIL) == false) {  
                  $errors[] = "Bitte geben Sie ein gültige eMail Adresse an";  
              }  
      
      

      Die oben genannte Fehlermeldung bezieht sich nun auf beide Einträge oder nur eMail Adresse bzw. Benutername? Kann ich hier überhaupt einen Unterschied machen?

      Sprich dass ich dann ausgeben lasse:

      • Benutzername bereits vorhanden
      • eMail Adresse bereits vorhanden
      1. OK mit der Fehlermeldung "1062" kann ich so weiter arbeiten

          
        if(isset($_POST['abschicken']) && empty($errors)) {  
        	  
            $stmt = $mysqli->prepare("INSERT INTO web_users (nickname, emailadresse) VALUES (?, ?)");  
            $nickname = $_POST["nickname"];  
            $emailadresse = $_POST["emailadresse"];  
            $stmt->bind_param("ss", $nickname, $emailadresse);  
          
           	 if(!$stmt->execute()){  
        		  
        		$mysqli->errno;  
        		if($mysqli->errno == 1062) {  
        		$errors[] = "Diese eMail Adresse ist bereits vorhanden";	  
        		}  
        	}  
        }  
        
        

        Es bleibt aber die Frage, die ich auch hier gestellt habe, kann ich unterscheiden, ob das Duplicate auf die eMail Adresse oder auf den Benutzername sich bezieht.

        Ich hoffe es kommt nicht die Antwort, nein das kannst du nicht, das wäre wirklich sehr schade.

        1. Hi,

          Es bleibt aber die Frage, die ich auch hier gestellt habe, kann ich unterscheiden, ob das Duplicate auf die eMail Adresse oder auf den Benutzername sich bezieht.

          Das gibt die Fehlernummer alleine nicht her – da kannst du höchstens nun wirklich den Fehlertext analysieren (der hat das Format Duplicate entry 'foo' for key 'bar'), oder du setzt in diesem Fall dann ein SELECT-Statement ab, das überprüft was Sache ist. Letzteres wäre zu bevorzugen, weil du nur damit feststellen kannst, ob der Fehler vielleicht sogar für beide Spalten „gleichzeitig“ aufgetreten ist (bzw. auftreten würde, denn MySQL meldet dir hier nur einen Fehler für den ersten verletzten Index). Dabei musst du dann aber wieder aufpassen, dass du dir kein TOCTTOU-Problem einhandelst …

          MfG ChrisB

          --
          Autocomplete has spoiled me to a point where it happens every so often that I encounter a CAPTCHA, and I just type in the first character … and then wait for the rest of the code to be automatically suggested :/
          1. OK, ich hab es nun etwas umgebaut

              
            $errors = array();  
            $nicknames = array();  
            $emailadresse = array();  
              
            if ($stmt = $mysqli->prepare("SELECT nickname, emailadresse FROM web_users"))  
            {  
            $stmt->execute();	  
            $stmt->store_result();  
            $stmt->num_rows;  
              
            $stmt->bind_result($nickname, $emailadresse);  
              
            while ($stmt->fetch()) {  
             $nicknames[] = $nickname;  
             $emailadresse[] = $emailadresse;  
            }  
            			}  
            else {  
              echo $mysqli -> error;  
            }  
            
            

            Die Fehler werden so zusammen gebaut

              
            		if(empty($_POST['nickname'])) {  
                        $errors[] = "Bitte geben Sie Ihren Benutzername an";  
            		}elseif (in_array(trim($_POST['nickname']), $nicknames)) {  
                        $errors[] = "Dieser Benutzername ist bereits vergeben";  
                    }  
            		  
                    if(empty($_POST['emailadresse'])){  
                        $errors[] = "Bitte geben sie Ihre eMail Adresse an";  
                    } elseif (filter_var($_POST['emailadresse'], FILTER_VALIDATE_EMAIL) == false) {  
                        $errors[] = "Bitte geben Sie ein gültige eMail Adresse an";  
                    }elseif (in_array(trim($_POST['emailadresse']), $emailadresse)) {  
                        $errors[] = "Diese eMail Adresse ist bereits vorhanden";  
                    }  
            
            

            Das ganze klappt auch sehr gut. Aber mir stellt sich nun die Frage, was ist, wenn die Seite mal sagen wir 500 – 1000 Benutzer hat, wenn sich dann ein neuer User anmeldet sind in meinem Array auf einen Schlag 500 - 1000 Einträge die er vergleichen muss.

            Wird dadurch meine Seite sehr langsam oder sind 500 - 1000 Einträge für eine Datenbank noch nicht wirklich viel?

            1. Hello,

              [code lang=php]
              if(empty($_POST['nickname'])) {
                          $errors[] = "Bitte geben Sie Ihren Benutzername an";
              }elseif (in_array(trim($_POST['nickname']), $nicknames)) {

              *** Ich weiß zwar nicht, woher plötzlich das Array kommt, aber in_array() hat eine Besonderheit,
              *** die Du beachten solltest!
              *** http://de2.php.net/manual/en/function.in-array.php
              *** Benutze für derartige Suchen in Arrays auf jeden Fall das Attribut Strict=TRUE

              $errors[] = "Dieser Benutzername ist bereits vergeben";
                      }

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bikers-lodge.com
              1. *** Ich weiß zwar nicht, woher plötzlich das Array kommt, aber in_array() hat eine Besonderheit,

                das Array kommt von hier

                  
                $errors = array();  
                $nicknames = array();  
                $emailadresse = array();  
                  
                if ($stmt = $mysqli->prepare("SELECT nickname, emailadresse FROM web_users"))  
                {  
                $stmt->execute();  
                $stmt->store_result();  
                $stmt->num_rows;  
                  
                $stmt->bind_result($nickname, $emailadresse);  
                  
                while ($stmt->fetch()) {  
                 $nicknames[] = $nickname;  
                 $emailadresse[] = $emailadresse;  
                }  
                                        }  
                else {  
                  echo $mysqli -> error;  
                }  
                
                
                1. Hello,

                  *** Ich weiß zwar nicht, woher plötzlich das Array kommt, aber in_array() hat eine Besonderheit,

                  das Array kommt von hier

                  Ok, anders gefragt:

                  Warum zum Teufel benutzt Du eine Datenbank, wenn Du dann für die kleinste Kleinigkeit sämtliche Daten einer Tabelle in ein Array lädst, anstatt die Datenbank dafür zu benutzen, wofür sie geeigent ist?

                  siehe https://forum.selfhtml.org/?t=217552&m=1494733

                  Und beachte bei "in_array()" die Eigenart mit dem Vergleich. Benutzte das Funktionsargument "strict=true"!

                  Liebe Grüße aus dem schönen Oberharz

                  Tom vom Berg

                  --
                   ☻_
                  /▌
                  / \ Nur selber lernen macht schlau
                  http://bikers-lodge.com
            2. Hello,

              Das ganze klappt auch sehr gut. Aber mir stellt sich nun die Frage, was ist, wenn die Seite mal sagen wir 500 – 1000 Benutzer hat, wenn sich dann ein neuer User anmeldet sind in meinem Array auf einen Schlag 500 - 1000 Einträge die er vergleichen muss.

              Wird dadurch meine Seite sehr langsam oder sind 500 - 1000 Einträge für eine Datenbank noch nicht wirklich viel?

              Du könntest es ja auch richtig[tm] machen, dann würde es auch funktionieren :-O

              * Post-Parameter checken -> ggf. bereits hier Fehlermeldung (Affenformular)
              * Parameter OK, Eintragungsversuch vornehmen in die Tabelle mit den 2 Unique Constraints
                für Nickname und eMail-Name
              * Query ok? -> ACK an User
              * MySQL-Fehler 1062? -> Select durchführen, um festzustellen, welcher Index geklemmt hat
                Pseudocode: (du machst das ja sowieso mit PDO)
                select nickname, email from users
                    where nickname = 'mres($con, $nickname)'
                       or email = 'mres($con, $email)'

              Da bekommst Du nun bestenfalls zwei Datenssätze. Du kannst nun nachgucken, ob eMail oder ob Nickname geklemmt hat und die passende Fehlermeldung generieren (Affenformular).

              Dann das Ganze von vorne! Es kann sich in der Zwischenzeit ja schon wieder alles geändert haben.

              Du kannst die Abfrage selbstverständlich auch vorne anstellen, aber den Eintragungsversuch dann trotzdem nur über die Contraints abwickeln. DAS ist die ECHTE Prüfung. Das Select hat nur eine geringe informative Güte, nämlich genau für den Moment, in dem es durchgeführt wird.

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bikers-lodge.com
              1. Da bekommst Du nun bestenfalls zwei Datenssätze. Du kannst nun nachgucken, ob eMail oder ob Nickname geklemmt hat und die passende Fehlermeldung generieren (Affenformular).

                Ich hab es nun so gemacht

                  
                $stmt = $mysqli->prepare("SELECT nickname, emailadresse FROM web_users WHERE nickname = '$nickname' OR emailadresse = '$emailadresse'"))  
                 {  
                	  $stmt->execute();	  
                	  $stmt->store_result();  
                          echo $stmt->num_rows;  
                	  $stmt->bind_result($nickname, $emailadresse);  
                  
                		while ($stmt->fetch()) {  
                			$nicknames[] = $nickname;  
                			$emailadresse[] = $emailadresse;  
                		}  
                 }  
                	else {  
                		echo $mysqli -> error;  
                	}  
                
                

                So hast du dieses doch gemein oder?

                1. Hello,

                  Ich hab es nun so gemacht

                  $stmt = $mysqli->prepare("SELECT nickname, emailadresse FROM web_users WHERE nickname = '$nickname' OR emailadresse = '$emailadresse'"))
                  {
                    $stmt->execute();
                    $stmt->store_result();
                            echo $stmt->num_rows;
                    $stmt->bind_result($nickname, $emailadresse);

                    while ($stmt->fetch()) {  
                    	$nicknames[] = $nickname;  
                    	$emailadresse[] = $emailadresse;  
                    }  
                  

                  }
                  else {
                  echo $mysqli -> error;
                  }

                  
                  >   
                  > So hast du dieses doch gemein oder?  
                    
                  Nein, keinesfalls SO.  
                  Wenn Du schon PDO benutzt, dann bitte misch es nicht mit mysqli.  
                    
                  Und dein Prepare-Statement macht wirklich schlimme Dinge. Das ermöglicht auf diese Weise ganz hervorragend SQL-Injection.  
                    
                  Und wenn Du schon PDO benutzt, dann schau dir auch mal try/catch an für die Fehlerbehandlung.  
                    
                    
                    
                    
                  Liebe Grüße aus dem schönen Oberharz  
                    
                    
                  Tom vom Berg  
                  ![](http://selfhtml.bitworks.de/Virencheck.gif)  
                    
                  
                  -- 
                   ☻\_  
                  /▌  
                  / \ Nur selber lernen macht schlau  
                  <http://bikers-lodge.com>
                  
      2. Hallo,

        $stmt = $mysqli->prepare("INSERT INTO web_users (nickname, emailadresse) VALUES (?, ?)");

        $nickname = $_POST["nickname"];
        $emailadresse = $_POST["emailadresse"];

          
        an dieser Stelle sehe ich mich veranlasst zu fragen, warum du diese beiden Werte erst umkopierst. Ein reines Kopieren ist normalerweise unnötig und selten sinnvoll - es sei denn, man kopiert den geprüften und ggf. korrigierten Wert nach einer Eingabe-Validierung.  
          
        Wichtig wäre aber zu prüfen, ob die erwarteten POST-Parameter überhaupt im Request vorhanden sind bzw. ob es auch wirklich ein POST-Request ist.  
          
        
        > wenn ich nun versuche zwei gleiche eMail Adressen Einzutragen bekomme ich diese Fehlermeldung "1062"  
        > Wie kann ich jetzt mit dieser Fehlermeldung hier weiter arbeiten?  
          
        Du informierst den Nutzer, dass die gewählte Kombination aus Nickname und e-Mail-Adresse schon existiert. Genau das sagt die Fehlerbedingung nämlich aus, wenn du einen unique index über beide Spalten hast, d.h. dieselbe e-Mail-Adresse kann mehrmals mit unterwschiedlichen Nicks registriert werden, oder derselbe Nick mit unterschiedlichen Mailadressen.  
          
        Ciao,  
         Martin  
        
        -- 
        Life! Don't talk to me about life!  
          (Marvin, the paranoid android in Douglas Adams' "The Hitchhiker's Guide To The Galaxy")  
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        
  3. Hallo,

    ich habekomme wieder ein Fehler angezeigt und sehe den Fehler in meiner Funktion nicht. Mein Login sieht wie folgt aus

      
    	function isUserLoggedIn($mysqli) {  
            $stmt = $mysqli->prepare("SELECT * FROM users WHERE user_session=?");  
            $stmt->bindParam("s", session_id());  
            $stmt->execute();  
      
            if($stmt->rowCount() === 1) {  
                return true;  
            } else {  
                return false;  
            }  
        }  
    
    

    In meiner config.php habe ich session_start(); stehen, wenn ich echo session_start(); ausgebe, erhalte ich auch ein Wert, also ist in session_start() ein Wert vorhanden. Nur in der Funktion kommt mal wieder nicht an bzw. ich bekomme diese Meldung

    Fatal error: Call to a member function bindParam() on a non-object in Zeile 28. Die Zeile ist

    $stmt->bindParam("s", session_id());

    die session_id ist doch ein String oder? also "s" oder kann es sein, dass die Funktion mal wieder den Wert session_id() nicht kennt?

    1. Hello,

      ich habekomme wieder ein Fehler angezeigt und sehe den Fehler in meiner Funktion nicht. Mein Login sieht wie folgt aus

      function isUserLoggedIn($mysqli) {
              $stmt = $mysqli->prepare("SELECT * FROM users WHERE user_session=?");

      #         $stmt->bindParam("s", session_id());
                $stmt->execute(session_id());

      if($stmt->rowCount() === 1) {
                  return true;
              } else {
                  return false;
              }
          }

      Versuche es mal so, wie oben angedeutet.
      Welchen Parameter s wolltest Du denn überhaupt binden? ich sehe im Statement-Text überhaupt keinen.

      Fatal error: Call to a member function bindParam() on a non-object in Zeile 28. Die Zeile ist

      $stmt->bindParam("s", session_id());

      die session_id ist doch ein String oder?

      Aber selbst, wenn da ein Parameter s im SQL-Text notiert wäre, würde er sich vermutlich nicht an das Ergebnis der Funktion binden lassen.

      Hier müssen wir ein wenig pingeliger mit der Sprache umgehen: Die FUNKTION session_id() LIEFERET einen String mit der Session-ID, aber erst dannw, wenn sie aufgerufen wird.

      Die Methode bindParam() verlangt aber eine VARIABLE, an die der Parameter gebunden wird. Die muss in dem Moment, wo sie gebunden wird, bereits vorhanden sein!

      also "s" oder kann es sein, dass die Funktion mal wieder den Wert session_id() nicht kennt?

      So ungefähr. Der WERT ist dabei sogar noch relativ egal, aber bindParam() kennt noch nicht einmal den Speicherplatz, in den der Wert gespeichert werden soll.

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
       ☻_
      /▌
      / \ Nur selber lernen macht schlau
      http://bikers-lodge.com
      1. Hello,

        Hello,

        ich habekomme wieder ein Fehler angezeigt und sehe den Fehler in meiner Funktion nicht. Mein Login sieht wie folgt aus

        function isUserLoggedIn($mysqli) {  
        

        $stmt = $mysqli->prepare("SELECT * FROM users WHERE user_session=?");
                    $sessionid = session_id();
                    $stmt->bindParam($sessionid);
                    $stmt->execute();

        if($stmt->rowCount() === 1) {
                    return true;
                } else {
                    return false;
                }
            }

        Nochmaaal...
        Das habe ich jetzt mit mysqli_stmt_ececute() verwechselt.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bikers-lodge.com
      2. #         $stmt->bindParam("s", session_id());
                  $stmt->execute(session_id());
        Versuche es mal so, wie oben angedeutet.

        Ich hab es mit deinem Beispiel getestet, kommt aber die gleiche Fehlermeldung „Fatal error: Call to a member function execute() on a non-object in Zeile 28§

        Welchen Parameter s wolltest Du denn überhaupt binden? ich sehe im Statement-Text überhaupt keinen.

        OK, ich hab den Code etwas geändert

          
                $stmt = $mysqli->prepare("SELECT * FROM users WHERE user_session=:sid");  
        	$stmt->bindParam(":sid", session_id());  
                $stmt->execute();  
        
        

        Hier müssen wir ein wenig pingeliger mit der Sprache umgehen: Die FUNKTION session_id() LIEFERET einen String mit der Session-ID, aber erst dannw, wenn sie aufgerufen wird.

        Die Methode bindParam() verlangt aber eine VARIABLE, an die der Parameter gebunden wird. Die muss in dem Moment, wo sie gebunden wird, bereits vorhanden sein!

        Kann sein ich verstehe dich nicht richtig, aber session_start() wird in meiner index Seite augerufen, wenn ich session_id() ausgeben lassen, sehe ich einen Wert, also wird sie doch aufgerufen und gefüllt?

      3. Tach!

        $stmt = $mysqli->prepare("SELECT * FROM users WHERE user_session=?");
        #         $stmt->bindParam("s", session_id());
                  $stmt->execute(session_id());
        Versuche es mal so, wie oben angedeutet.

        Was soll denn das werden? mysqli_stmt::execute() nimmt keine Parameter entgegen.

        Und da fällt mir noch was auf: bindParam ist PDO-Syntax, bei mysqli heißt diese Methode bind_param.

        Welchen Parameter s wolltest Du denn überhaupt binden? ich sehe im Statement-Text überhaupt keinen.

        Handbuch lesen! Das s steht für den Typ String. Es soll also ein String-Wert gebunden werden. Das ist kein Platzhaltername. Solche gibt es in MySQL nicht, nur positionsorientierte Fragezeichen.

        Die Methode bindParam() verlangt aber eine VARIABLE, an die der Parameter gebunden wird. Die muss in dem Moment, wo sie gebunden wird, bereits vorhanden sein!

        Das wird dann der nächste Fehler werden, wenn der eigentlich angefragte beseitigt worden ist. Beim Binding von Parameteren und auch von Abfrageresultaten (bind_result) können nur Variablen angegeben werden, keine Funktionsaufrufe oder andere zu berechnende Ausdrücke.

        dedlfix.

        1. Und da fällt mir noch was auf: bindParam ist PDO-Syntax, bei mysqli heißt diese Methode bind_param.

          Sorry, das war ein Fehler von mir, so sieht diese jetzt aus

            
          	function isUserLoggedIn($mysqli) {  
                  $stmt = $mysqli->prepare("SELECT * FROM users WHERE user_session=?");  
          		  
          	$stmt->bind_param("s", session_id());  
                  $stmt->execute();  
            
                  if($stmt->rowCount() === 1) {  
                      return true;  
                  } else {  
                      return false;  
                  }  
              }  
          
          
    2. Tach!

      Fatal error: Call to a member function bindParam() on a non-object in Zeile 28. Die Zeile ist
      $stmt->bindParam("s", session_id());

      Das hat nichts mit der Session oder dem Binding zu tun, sondern ist ein ganz allgemeiner Fehler, der dir sagt, dass in $stmt kein Objekt steckt, von dem man eine Methode aufrufen könne. Mit anderen Worten, die Zuweisung zu $stmt hat was anderes reingeschrieben als du erwartet hast. Das kannst und solltest du immer mit var_dump() prüfen. Untersuche also, warum die Zuweisung misslungen ist. Generell solltest du zu jeder verwendeten Funktion/Methode im Handbuch nachlesen, was diese zurückgeben kann, auch in Fehlerfällen, um dann im Code entsprechend reagieren und nicht einfach nur nach Schönwetterprinzip weitermachen.

      dedlfix.

      1. Hello,

        Fatal error: Call to a member function bindParam() on a non-object in Zeile 28. Die Zeile ist
        $stmt->bindParam("s", session_id());

        Das hat nichts mit der Session oder dem Binding zu tun, sondern ist ein ganz allgemeiner Fehler, der dir sagt, dass in $stmt kein Objekt steckt, von dem man eine Methode aufrufen könne.

        Das würde aber bedeuten, dass bereits $mysqli kein Objekt wäre?
        Dann muss er _den_ Fehler ja noch ganz woanders suchen.
        Und der nächste Fehler war dem Parser noch gar nicht aufefallen...

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bikers-lodge.com
        1. Tach!

          Das hat nichts mit der Session oder dem Binding zu tun, sondern ist ein ganz allgemeiner Fehler, der dir sagt, dass in $stmt kein Objekt steckt, von dem man eine Methode aufrufen könne.

          Das würde aber bedeuten, dass bereits $mysqli kein Objekt wäre?

          Nein, dann käme nämlich dieselbe Meldung aber bezogen auf prepare() und $mysqli und eine Zeile eher.

          Dann muss er _den_ Fehler ja noch ganz woanders suchen.

          Das prepare() ist misslungen und hat ein false zurückgeliefert. Warum auch immer. Das ergibt die Fehlerauswertung.

          dedlfix.

      2. Das kannst und solltest du immer mit var_dump() prüfen. Untersuche also, warum die Zuweisung misslungen ist.

        Wo soll ich var_dump aufrufen lassen, wenn das Script diesen Fehler ausgibt? Egal an welcher Stelle ich var_dump ausgeben lasse, ich sehe nur den von mir genannten Fehler.

        1. Tach!

          Das kannst und solltest du immer mit var_dump() prüfen. Untersuche also, warum die Zuweisung misslungen ist.
          Wo soll ich var_dump aufrufen lassen, wenn das Script diesen Fehler ausgibt? Egal an welcher Stelle ich var_dump ausgeben lasse, ich sehe nur den von mir genannten Fehler.

          Die Fehlermeldung sagt, dass an einem non-object eine Methode aufgerufen wurde. Das heißt also, dass $stmt ein non-object ist. Das sollst du mit var_dump($stmt) überprüfen. Natürlich ändert sich damit noch nichts, aber das wäre der erste Schritt zur Analyse des Problems.

          dedlfix.

          1. Die Fehlermeldung sagt, dass an einem non-object eine Methode aufgerufen wurde. Das heißt also, dass $stmt ein non-object ist. Das sollst du mit var_dump($stmt) überprüfen. Natürlich ändert sich damit noch nichts, aber das wäre der erste Schritt zur Analyse des Problems.

            wenn ich var_dump($stmt) ausgeben lassen, erhalte ich dieses:

            bool(false) Fatal error: Call to a member function bind_param() on a non-object in Zeile 28

            1. Tach!

              Die Fehlermeldung sagt, dass an einem non-object eine Methode aufgerufen wurde. Das heißt also, dass $stmt ein non-object ist. Das sollst du mit var_dump($stmt) überprüfen. Natürlich ändert sich damit noch nichts, aber das wäre der erste Schritt zur Analyse des Problems.

              wenn ich var_dump($stmt) ausgeben lassen, erhalte ich dieses:
              bool(false) [...]

              Und was sagt dir das nun? Hast du dich mal informiert, was var_dump() macht? Und warum ich das empfehle?

              In $stmt steckt also der boolsche Wert false drin. Warum das? Warum ist das kein Objekt der Klasse mysqli_stmt? Das sind die Fragen, die du dir stellen musst. Zu deren Beantwortung musst du nun zurück zu der Stelle gehen, an der die Zuweisung stattfand und herausfinden, warum diese misslungen ist. Dazu dann im Handbuch lesen, wann false zurückgegeben wird - im Fehlerfall. Aha, prepare() wurde nicht fehlerfrei ausgeführt. Und wie kommen wir bei MySQL an den Text von Fehlermeldungen?

              Das nächste Thema wäre dann noch, robuster zu programmieren, dass Fehler abgefangen werden. Solche können nämlich auch zur Laufzeit in produktiven Systemen auftreten.

              dedlfix.

              1. Ich bin echt so ein Trottel :( es lag an der Tabelle, diese habe ich von "users" in "web_users" umbenannt.

                Ist das eigentlich möglich dass man sich Tabellen in einer Variable speichert, die dann überall im SQL ausgibt? Wenn ich eine Tabelle in der DB ändere muss ich aufpassen, dass ich ja keine Abfrage auf meiner Seite vergesse. Was passieren kann, habe ich ja nun erlebt.

                1. Tach!

                  Ist das eigentlich möglich dass man sich Tabellen in einer Variable speichert, die dann überall im SQL ausgibt?

                  Ja, aber das musst du selbst programmieren. Man verwendet sowas jedoch meist nicht mit Tabellennamen sondern mit Präfixen in Projekten, die auch in Umgebungen laufen sollen, wo man nur eine Datenbank für mehrere Pejekte zur Verfügung hat. Jedes Projekt bekommt sein eigenes Tabellenpräfix. Im Code steht dann immer nur ein Platzhalter vor dem Tabellennamen und die Funktion, die die Statements abschickt, ändert diesen im letzten Moment noch in den tatsächlich verwendeten Präfix.

                  Sowas ähnliches kannst du auch für den gesamten Tabellennamen machen, aber das bedeutet, noch eine Schicht in deinen Code einzuziehen, über die alle deine Abfragen geschickt werden. Oder du nimmst dir einen ORM oder andere Layer-Software, die dir den Tabellenzugriff kapselt. Ob sich der Aufwand für dein Projekt lohnt?

                  dedlfix.

                  1. Danke für deine Antwort, aber das ist mir wirklich zu viel Arbeit. Ich dachte ich kann z.B. in einer Datei die ich in meiner index.php include ein paar Variablen festlegen und diese dann an der Stelle einfügen wo ich sonst einen festen Wert stehen habe.

                    Hab noch nee andere Frage

                    Mit $stmt->bind_param("sss", $userMail, $pw, $ak); lege ich fest, ob die eingefügten Werte ein String oder integer ist. Wenn ich $ak = 1; schreibe, bin ich davon ausgegangen dass der Wert ein "integer" also $stmt->bind_param("ssi", $userMail, $pw, $ak); ist, das Script hat die Abfrage nicht ausgeführt, ändere ich diesen Wert in ein „s“ funktioniert die Abfrage warum?

                    1. Hallo,

                      Mit $stmt->bind_param("sss", $userMail, $pw, $ak); lege ich fest, ob die eingefügten Werte ein String oder integer ist. Wenn ich $ak = 1; schreibe, bin ich davon ausgegangen dass der Wert ein "integer" also $stmt->bind_param("ssi", $userMail, $pw, $ak); ist

                      du verwechselst hier zwei Welten. Mit bind_param() teilst du der Datenbank mit, welche(n) Datentyp(en) du als Ergebnis haben möchtest. Die DB versucht dann nach besten Kräften, diesem Wunsch nachzukommen. Welchen Typ die PHP-Variablen vorher haben, die dann die Ergebnisse übernehmen sollen, spielt aber gar keine Rolle, denn PHP ändert die Typen von Variablen kontextabhängig. Ob $ak also vor dem Aufruf von bind_params() ein Integer, ein String, ein Boolean oder gar komplett undefiniert ist, spielt keine Rolle. Du teilst der DB mit, dass du einen String haben möchtest, also bekommst du einen String. Du wünschst dir einen Integer, also bekommst du einen Integer, wenn der Wert in der DB als solcher interpretiert werden kann.

                      das Script hat die Abfrage nicht ausgeführt

                      Doch, ganz bestimmt. Nur hast du dann vielleicht nicht das bekommen, was du erwartest.

                      ändere ich diesen Wert in ein „s“ funktioniert die Abfrage warum?

                      Der Datentyp "String" kann alles enthalten und unterliegt keinen Regeln oder Beschränkungen. Wenn du einen String bestellst, bekommst du also immer ein gültiges Ergebnis. Wenn du einen anderen Datentyp anforderst, etwa Integer, könnte eine Konvertierung nötig sein, wenn der Datentyp in der DB ein anderer ist, und die Konvertierung kann fehlschlagen. Das Ergebnis ist dann eventuell 0.

                      So long,
                       Martin

                      --
                      Success should be measured not so much by the position that one has reached in life,
                      but by the obstacles one has overcome while trying to succeed.
                      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                      1. Tach!

                        Mit $stmt->bind_param("sss", $userMail, $pw, $ak); lege ich fest, ob die eingefügten Werte ein String oder integer ist. Wenn ich $ak = 1; schreibe, bin ich davon ausgegangen dass der Wert ein "integer" also $stmt->bind_param("ssi", $userMail, $pw, $ak); ist

                        du verwechselst hier zwei Welten. Mit bind_param() teilst du der Datenbank mit, welche(n) Datentyp(en) du als Ergebnis haben möchtest. Die DB versucht dann nach besten Kräften, diesem Wunsch nachzukommen.

                        bind_param() ist nicht bind_result(). Der Rest von Des (anderen) Martins Erklärungsversuch ist damit nicht mehr zutreffend.

                        das Script hat die Abfrage nicht ausgeführt

                        Was genau hat es denn gemacht? Gab es Fehlermeldungen oder einen Rückgabewert, der einen Fehler anzeigte?

                        ändere ich diesen Wert in ein „s“ funktioniert die Abfrage warum?

                        Dazu kann ich nichts sagen, mangels Erfahrung. Wie sieht denn die Tabellenstruktur aus? Weiterhin gibt es sowohl in PHP als auch in MySQL eine automatische Typkonvertierung, die hier mit reinspielen kann. Wenn s funktioniert, dann lass es so. Probier auch noch einige (Extrem-)Fälle durch, ob die auch problemlos so durchgewunken werden.

                        dedlfix.

                        1. Hallo,

                          bind_param() ist nicht bind_result(). Der Rest von Des (anderen) Martins Erklärungsversuch ist damit nicht mehr zutreffend.

                          stimmt, das hatte ich wohl mistverstanden.

                          Ciao,
                           Martin

                          --
                          Alle Tage sind gleich lang. Aber unterschiedlich breit.
                          Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                          1. Hello Martin,

                            bind_param() ist nicht bind_result(). Der Rest von Des (anderen) Martins Erklärungsversuch ist damit nicht mehr zutreffend.

                            stimmt, das hatte ich wohl mistverstanden.

                            Ich freue mich immer, dass ich hier vom "blamiere dich täglich" und anschließendem Mitlesen der diversen Antworten nicht dümmer werde :-)

                            Liebe Grüße aus dem schönen Oberharz

                            Tom vom Berg

                            --
                             ☻_
                            /▌
                            / \ Nur selber lernen macht schlau
                            http://bikers-lodge.com
                      2. Hello,

                        du verwechselst hier zwei Welten. Mit bind_param() teilst du der Datenbank mit, welche(n) Datentyp(en) du als Ergebnis haben möchtest.

                        Geht es bei bind_param() nicht nur um das Escaping in der Schnittstelle?
                        Das muss zum Spaltentyp passen, damit die SQL-Operation wunschgemäß und abgesichert stattfinden kann. Ein FALSE oder NULL in '' einzupacken (Typ = s), würde zum Misserfolg führen. Die weitergabe des Querys an die Datenbank findet ja immer noch per SQL-String statt, nur dass der nun von PHP "automatisch" verpackt wird.

                        Liebe Grüße aus dem schönen Oberharz

                        Tom vom Berg

                        --
                         ☻_
                        /▌
                        / \ Nur selber lernen macht schlau
                        http://bikers-lodge.com
                        1. Tach!

                          Geht es bei bind_param() nicht nur um das Escaping in der Schnittstelle?

                          Nein, Das ist der Vorteil an Prepared Statements, dass da nichts maskiert werden muss. Die Query geht ja schon mit dem Prepare zum Server. Die Werte kommen später mit dem Execute. Man übergibt mit dem Binding die Roh-Werte und den Rest macht die Server-API. Darauf hat man keinen Einfluss und muss darauf vertrauen, dass das richtig und problemlos abläuft.

                          Das muss zum Spaltentyp passen, damit die SQL-Operation wunschgemäß und abgesichert stattfinden kann.

                          Nee, wer sagt denn, dass der Wert am Ende irgendwann in einer Spalte landen soll? Der Platzhalter steht irgendwo im SQL-Statement, und da kann er auch in einem komplexen Ausdruck stehen, der noch dreimal typgewandelt werden muss, oder gar nicht in einer Spalte landet oder mit dem Inhalt einer solchen verglichen wird.

                          Ehrlich gesagt, erschließt sich mir nicht, welche Auswirkungen die Typangabe konkret hat. In meinen Versuchen mit String und Integer war alles gemixt möglich, sowohl beim SELECT in einem WHERE als auch beim INSERT (jeweils direkt die Felder angesprochen). Hier greifen wohl PHPs und MySQLs Typumwandlung zusammen ins Geschehen ein. Ich nehme immer s solange es funktioniert. Mich würde mal mehr interessieren, was das konkrete Szenario war wo das i notwendig wurde, und welche Fehlermeldung genau kam.

                          dedlfix.

                          1. Hello,

                            Geht es bei bind_param() nicht nur um das Escaping in der Schnittstelle?

                            Nein, Das ist der Vorteil an Prepared Statements, dass da nichts maskiert werden muss. Die Query geht ja schon mit dem Prepare zum Server. Die Werte kommen später mit dem Execute. Man übergibt mit dem Binding die Roh-Werte und den Rest macht die Server-API. Darauf hat man keinen Einfluss und muss darauf vertrauen, dass das richtig und problemlos abläuft.

                            Ok, dann gibt es also nicht nur in PHP was neues (PDO), sondern das setz auch auf einer anderen Schnittstelle auf? *Ups*, da ist mir jetzt wirklich allerhand durchgeflutscht in dem einen Jahr als "Pastor".

                            Das muss zum Spaltentyp passen, damit die SQL-Operation wunschgemäß und abgesichert stattfinden kann.

                            Nee, wer sagt denn, dass der Wert am Ende irgendwann in einer Spalte landen soll? Der Platzhalter steht irgendwo im SQL-Statement, und da kann er auch in einem komplexen Ausdruck stehen, der noch dreimal typgewandelt werden muss, oder gar nicht in einer Spalte landet oder mit dem Inhalt einer solchen verglichen wird.

                            Dann hatte ich davon eine vollkommen falsche Vorstellung. Ich hatte angenommen, dass hier nur PHP renoviert worden war, um mit unterschiedlichen Servern reden zu können und das PHP-APP-Programmierer-seits konsequent objektorientiert zu tun.

                            Ehrlich gesagt, erschließt sich mir nicht, welche Auswirkungen die Typangabe konkret hat. In meinen Versuchen mit String und Integer war alles gemixt möglich, sowohl beim SELECT in einem WHERE als auch beim INSERT (jeweils direkt die Felder angesprochen).

                            Was passiert denn, wenn man mit den Werten rechnet oder kleiner/größer-Vergleiche anstellt. Da müssten sich Strings doch anders verhalten, als Nums.

                            *  '1119' < '9'
                            aber
                            *  1119 > 9

                            Hier greifen wohl PHPs und MySQLs Typumwandlung zusammen ins Geschehen ein. Ich nehme immer s solange es funktioniert. Mich würde mal mehr interessieren, was das konkrete Szenario war wo das i notwendig wurde, und welche Fehlermeldung genau kam.

                            Naja, "Martin_Online" grooves sich inzwischen ja hoch und arbeitet mit. Da ist die Chance gut, dass wir alle noch 'was davon haben. Ich hoffe, dass er weiß, wie wertvoll die eigene Dokumentation der neuen Erkenntnisse für ihn später noch werden kann :-)

                            Ich hatte ja gestern auch einen schlechten "->execute()"-Tag, und versuche nun zu ergründen (und mir zu merken), wo überall die Unterschiede zwischen mysqli-prepared Statements und PDO liegen.

                            ##---

                            Aber z.Zt. knabber ich noch am Signalling und der Überarbeitung meiner Triggers.
                            Ich habe noch nicht ganz begriffen, wie aus

                              
                            signal sqlstate '45000' set message_text = msg;  
                              
                            
                            

                            dann später

                              
                            /* SQL Fehler (1644): -- usw.  
                              
                            
                            

                            wird, also welcher SQL-State in welche Fehlernummer übersetzt wird.
                            http://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html

                            Isr wahrscheinlich ganz einfach, wenn man weiß, wie es zusammenhängt :-O

                            Liebe Grüße aus dem schönen Oberharz

                            Tom vom Berg

                            --
                             ☻_
                            /▌
                            / \ Nur selber lernen macht schlau
                            http://bikers-lodge.com
                            1. Ich denk mal, es werden im laufe der Zeit doch noch ein paar Fragen kommen bis meine Webseite fertig ist :)) Aber umso mehr ich mich damit beschäftige, umso mehr Spaß macht das ganze auch und ich sehe eben Fortschritte. Ich frag mich auch, warum heute noch so viele User mit mysql arbeiten obwohl mysqli es schon Jahre gibt, wenn ich mir so diverse Tutorials ansehe.

                              Naja, "Martin_Online" grooves sich inzwischen ja hoch und arbeitet mit. Da ist die Chance gut, dass wir alle noch 'was davon haben. Ich hoffe, dass er weiß, wie wertvoll die eigene Dokumentation der neuen Erkenntnisse für ihn später noch werden kann :-)

                              Habe ich bis jetzt noch nie eine Dokumentation erstellt. Wenn ich etwas nachschaue, wie ich es gemacht habe, rufe ich die entsprechende Datei auf.

  4. Hallo,

    eine Frage zu meiner Datenbankstruktur, sollte ich meine Login Daten (eMail Adresse & Passwort) in die gleiche Tabelle ablegen wie die User Daten (Name, Vorname, Straße, PLZ, Ort, Telefonnummer).

    Wie setzt ihr dieses um?

    1. Tach!

      eine Frage zu meiner Datenbankstruktur, sollte ich meine Login Daten (eMail Adresse & Passwort) in die gleiche Tabelle ablegen wie die User Daten (Name, Vorname, Straße, PLZ, Ort, Telefonnummer).

      Wenn nur eine Adresse pro Nase gespeichert werden soll, sehe ich keinen Grund, die Daten auf zwei Tabellen zu verteilen. Das machts am Ende nicht einfacher, bei keinem (für mich) sichtbaren Gewinn.

      dedlfix.

  5. Ich hab zum Login noch eine kleine Zusatzfrage, was ist sinnvoller für ein Login:

    Benutzer & Passwort
    E-Mail Adresse & Passwort

    Benutzername kann der User beim registieren selber vergeben!

    Mir persönlich ist eine E-Mail Adresse lieber. Was denkt ihr, was ist sinnvoller bzw. besser? Habt Ihr Erfahrungswerte in solchen Sachen?

    1. Hi,

      Ich hab zum Login noch eine kleine Zusatzfrage, was ist sinnvoller für ein Login:

      Benutzer & Passwort
      E-Mail Adresse & Passwort

      auf jeden Fall ersteres.

      Benutzername kann der User beim registieren selber vergeben!

      Ein Grund mehr.

      Mir persönlich ist eine E-Mail Adresse lieber. Was denkt ihr, was ist sinnvoller bzw. besser?

      Eine e-Mail-Adresse kann sich ändern. Möchte ich dann überall rumgehen, wo ich mich mal angemeldet habe, und meine Login-Daten korrigieren? Nein, eigentlich nicht.

      Ciao,
       Martin

      --
      Die Zeit, die man zur Fertigstellung eines Projekts wirklich braucht, ist immer mindestens doppelt so lang wie geplant.
      Wurde dieser Umstand bei der Planung bereits berücksichtigt, gilt das Prinzip der Rekursion.
      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
      1. Eine e-Mail-Adresse kann sich ändern. Möchte ich dann überall rumgehen, wo ich mich mal angemeldet habe, und meine Login-Daten korrigieren? Nein, eigentlich nicht.

        Ok, da gebe ich dir recht, hab es nun auf Benutzername / Passwort geändert.

      2. Mahlzeit,

        Eine e-Mail-Adresse kann sich ändern. Möchte ich dann überall rumgehen, wo ich mich mal angemeldet habe, und meine Login-Daten korrigieren? Nein, eigentlich nicht.

        Das Problem ist eher, dass in den meisten Fällen der Loginname gar nicht geändert werden _kann_.

        --
        42