DB PDO Wert aus Datenbank mit variable vergleichen

  • Hey zusammen,


    ich sitze grad am double opt in- Verfahren, bisher nur für die Registration.
    Nun habe ich schon gecodet, das die daten in datenbank gespeichert werden. Und das eine E-Mail geschickt wird mit der Hashid, welche bei jedem user nach der registration gespeichert wird.


    Nun möchte ich abfragen : Wo benutzername .... ist select hashid.
    Und nun diese hashid mit der id vom Laden des Aktivierungslinks (als Parameter) zu vergleichen. Da ich sowas nochnie gemacht habe. Wende ich mich an euch.


    Mein aktueller Stand:


    Registrier-Seite:


    Und die registration_weiterleitung.php
    wo ich nun die id welche beim klick auf aktivierungslink gesendet wird mit der hashid in der db vergleichen.



    Dabei wird immer diese Exception geworfen:
    Fatal error: Uncaught exception 'PDOException' with message
    'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'rere' in 'where
    clause'' in
    /users/apple231/www/Registriervorgang/registration_weiterleitung.php:38
    Stack trace: #0
    /users/apple231/www/Registriervorgang/registration_weiterleitung.php(3[Blockierte Grafik: http://www.forum-hilfe.de/images/smilies/icon_cool.gif]: PDO->prepare('SELECT hashid F...') #1 {main} thrown in /users/apple231/www/Registriervorgang/registration_weiterleitung.php on line 38
    Freue mich auf eure Hilfe und wieder was neues zu lernen.


    Das heißt, das die
    spalte nicht gefunden worden ist. Ich sag selektiere/wähle die spalte
    hashid aus wo benutzername ist $user. ($user ist der Session
    Benutzername dieser wiederum ist der Benutzername der eingegeben worden
    ist.) Aber wie kann es sein ?


    Nochwas:


    Habe jetzt mittels fetchColumn(); probiert den inhalt auszugeben, aber das klappt auch nicht warum denn das ?




    Stef

  • Du hast sehr viel Code geposted und irgendwo dazwischen das Problem beschrieben.
    Das ist nicht gut für Dich, denn man hat oft nicht die Zeit so viel durch zu sehen.

    =)


    Zur Fehlermeldung.

    Zitat

    Column not found: 1054 Unknown column 'rere' in 'where
    clause'' in


    Du hattest in der SQL-Query wohl eine Spalte "rere" stehen.
    Wenn ich mir den Code ansehe, sehe ich davon allerdings nichts.
    Wenn Der Fehler immernoch auftritt, dann poste mal
    die erstellte Query und den Inhalt der Variablen die darin genutzt werden.
    in etwa so:

    PHP
    1. // hier ist die zeile 38, in der der fehler auftrat:
    2. $statement = $pdo->prepare("SELECT hashid FROM Registrierdaten WHERE benutzername = ".$user." ");
    3. // testausgabe:
    4. var_dump(
    5. "SELECT hashid FROM Registrierdaten WHERE benutzername = ".$user." "
    6. );
    7. exit; // ende um nur die query zu sehen/prüfen



    Was hier allerdings noch schief läuft ist, dass Du variablen (und dann noch user input) in die SQL-Query einbaust, ohne Platzhalter zu verwenden.
    Momentane Query und das gefähriche daran:


    Siehe PDO::prepare Bsp: http://php.net/manual/de/pdo.p…ect1-pdo.prepare-examples




    Zeile 25 bis ... in Register-Seite

    PHP
    1. //Password
    2. $password = $_POST['password'];
    3. $password_wiederholung = $_POST['password_wiederholung'];
    4. $password_gehahst = password_hash($password_gehahst, PASSWORD_DEFAULT);


    Du erstellst hier einen PW hash aus einem (nicht vorhandenen) PW hash.
    Das soll sicherlich das passwort oder passwort-wiederholung sein:


    PHP
    1. //Password
    2. $password = $_POST['password'];
    3. $password_wiederholung = $_POST['password_wiederholung'];
    4. $password_gehahst = password_hash($password /*<<<< ----*/, PASSWORD_DEFAULT);


    HTML - vars maskieren - auch in Email HTML


    Siehe auch all den anderen HTML Code in dem Du vars verwendest.


    Email Injection
    Siehe: Feedback für meine Website und Fragen zur Sicherheit, PHP uvm.




    Tipps:
    Erstelle den Hash erst, wenn Du alle Fehler ausschließen konstest.
    Sonst erstellst Du jedes mal einen Hash, den Du nicht nutzt/weiter verwendest.
    Also erst in:

    PHP
    1. if(count($fehler) === 0 ){
    2. // jetzt erst hashen, den das kosten resourcen
    3. $password_gehahst = password_hash($password, PASSWORD_DEFAULT);
    4. }



    empty($benutzername)
    Prüfe besser auf mindest Länge. Du willst sicher keine Benutzer mit den Namen "a" oder "b" ... haben =)
    Also besser

    PHP
    1. if (strlen($vorname) < 4){ // bsp min length 4
    2. // fehler
    3. }


    Das Gleiche mit allen anderen Feldern. Es gibt immer minest Länge, und oft maximal Länge.


    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    Wenn Du das verwendest, dann solltest Du bei jeder Aktion ($pdo->prepare..., $stmt->execute....) einen try/catch Block verwenden!




    Was machst Du hier? :

    PHP
    1. $check = explode( '$', $_SERVER['QUERY_STRING'] );


    oO?
    Was steckt in $check?



    Zum Login: Du solltest Dir das hier ansehen: Loginpasswort richtig hashen - password_hash() & password_verify()
    Beim Login mit passwort_verify(...) den hash des Users aus der db mit dem eingegebenen PW vergleichen.

  • Hey cottton,


    erstmals vielen Dank.


    Ja das war ungeschickt von mir.


    Ich habe im query kein rere stehen, rere habe ich einfach so mal in mein formular eingegeben


    Ok. Gut zu wissen. Ja da hast du recht. Dann werde ich es auf empty sowie strlen überprüfen.


    Habe mein code jetzt so angepasst. Wie du es vorgeschlagen hast.


    PHP
    1. $check = explode( '$', $_SERVER['QUERY_STRING'] );


    Darin steckt die hashid welche bei der besätigungsmail als parameter gesendet wird. Damit möchte ich dann den eintrag der db vergleichen.


    Es kommt vor ausgabe von var dump folgender error :


    Fatal error: Uncaught exception 'PDOException' with message
    'SQLSTATE[42S22]: Column not found: 1054 Unknown column 's' in 'where
    clause'' in /users/apple231/www/Registriervorgang/test2.php:39
    Stack trace:
    #0 /users/apple231/www/Registriervorgang/test2.php(39):
    PDO->prepare('SELECT hashid ...')
    #1 {main}
    thrown in /users/apple231/www/Registriervorgang/test2.php on line 39


    Stef

  • Verstehe ich immernoch nicht, was Du mit dem explode machst.
    Also, dass dort der hash rein kommen soll - ok.
    Aber den kannst Du doch per Name an die url hängen - wie zB

    Code
    1. www.url.de?activation=abc123....


    (oder hash oder h oder was auch immer der Name sein soll).


    Zur query:
    Du hast es nicht, oder nicht rightig umgebaut.
    Siehe comments:


    Es müsste also heißen:

    PHP
    1. $statement = $pdo->prepare("SELECT hashid FROM Registrierdaten WHERE benutzername = '".$user."' ");


    Aber das ist immernoch falsch, denn Userinput gehört nicht direkt in die Query!
    Also PLatzhalter verwenden!

    Siehe http://php.net/manual/de/pdo.prepared-statements.php

  • Hi,


    ok.


    das explode habe ich da falsch genutzt ich nutze diese var jetzt so:

    PHP
    1. $check = !empty( $_SERVER['QUERY_STRING'] )? $_SERVER['QUERY_STRING']: null;



    Habe es falsch angewandt.
    Jetzt kommt keine fehlermeldung mehr.


    die var dump ausgabe gibt aus :


    string(60) "SELECT hashid FROM Registrierdaten WHERE benutzername = stef1234 "



    Gruß,
    Stef

  • Sorry, war vorhin bissl in Eile, wollte den Post aber nicht nochmal schrieben und hab ihn angeschickt.


    Was noch fehlte:
    Der Wert, der in die Query geschrieben wird (per Variable $user),
    der wird als Spaltenname (column) behandelt.
    Am Bsp Deines letzen var_dump:

    SQL
    1. SELECT hashid FROM Registrierdaten WHERE benutzername = stef1234 -- hier fehlen die ''


    Es sollte so aussehen:

    SQL
    1. SELECT hashid FROM Registrierdaten WHERE benutzername = 'stef1234'


    Ein anderes Bsp:
    angenommen in $user steckt der Wert name
    dann wäre die Query

    SQL
    1. SELECT hashid FROM Registrierdaten WHERE benutzername = name


    .
    Was jetzt in dieser Query passiert ist:
    - gib mir
    - von Registrierdaten
    - die hashid derer Datensätze
    - bei welchen der benutzername GLEICH der name ist.


    Und das ist sicherlich nicht gewollt.
    Außerdem will ich sehen, dass Du die Platzhalter verwendest :D
    $ in Query is nich mehr. In dem String gehört nur noch :platzhalter (:user oder :benutzername oder :id oder was auch immer ...) :)


    bei Fragen immer fragen

  • Hey,


    ok. Habe es nun verstanden.
    Mann kann mit platzhaltern daten selektieren und daten einfügen.
    Geht als Platzhalter auch das ?


    z.b.so:

    PHP
    1. $stmt = $pdo->prepare('SELECT `hashid` FROM `Registriergang` WHERE `email` = ? '); //hier wird die query vorbereitet mit platzhalter
    2. $stmt->bindParam(1,$email, PDO::PARAM_STR); // hier wird dem Platzhalter (?) die value von de variable email als string übergeben
    3. $result = $stmt->execute(); // und dann wird es hier ausgeführt.


    Dann wäre die ausgabe von stmt mit var dump:


    SELECT `hashid` FROM `Registriergang` WHERE email = `stef@test.de`


    Und zu dem try/catch nochmals wenn ich diese statements da vorbereite und ausführe und bei db verbindungsaufbau folgenden array mitübergebe



    Dann soll man ja nach deiner Aussage dies mit dem try/catch machen (statements).
    Soll dies dann z.b so aussehen:


    PHP
    1. try
    2. {
    3. $stmt = $pdo->prepare('SELECT `hashid` FROM `Registriergang` WHERE
    4. email = `?` '); //hier wird die query vorbereitet mit platzhalter
    5. $stmt->bindParam(1,$email, PDO::PARAM_STR); // hier wird dem Platzhalter (?) die value von de variable email als string übergeben
    6. $result = $stmt->execute(); // und dann wird es hier ausgeführt.
    7. } catch (Exception $exp){
    8. echo 'Ein Fehler ist aufgetreten : ' . $exp->getMessage();
    9. exit;
    10. }


    Gruß,
    Stef

  • Die Platzhalter stellen (logisch) den Platzhalter für die Werte dar,
    die an dieser Stelle eingefügt werden sollen.
    Damit stellst Du sicher, dass keine SQL-Injections möglich sind.
    Siehe: http://php.net/manual/de/pdo.prepared-statements.php


    Zitat

    Die Parameter für Prepared Statements müssen nicht maskiert werden. Der Treiber übernimmt das automatisch.
    Wenn eine Anwendung ausschließlich Prepared Statements benutzt, kann sich der Entwickler sicher sein, dass keine SQL-Injection auftreten wird.


    Der Benutzer kann also eingeben, was er will. Der Wert wird immer als (default) String in die Query eingefügt,
    oder als den Typ, den man angegeben hat (PDO::PARAM_INT, ...).


    Die Fragezeichenplatzhalter sind Geschmackssache.
    Ich mag die nicht. Die benanten Platzhalter (:name, :id, :usw) sind meiner Meinung nach übersichlicher.
    Beide erfüllen aber den Zweck.


    (Jetzt nicht verwirren lassen)
    Es gibt verschiedene Wege.
    Zb Dein Weg mit Fragezeichen und ::bindParam,
    oder :platzhalter und ::bidParam
    oder :platzhalter und die Übergabe eines Arrays der Werte (siehe: http://php.net/manual/de/pdo.p…ect1-pdo.prepare-examples)


    Letzteres ist meiner Meinung nach das einfachste. Weniger Code, übersichtlicher (...).


    Dein Bsp mit der (ich nenn es mal) Array-Variante:


    PHP
    1. // SQL und params vorbereiten (als variablen nur zur übersicht im bsp)
    2. $sql = 'SELECT `hashid` FROM `Registriergang` WHERE `email` = :email;';
    3. $params = array(
    4. ':email' => $_POST['email']
    5. );
    6. $stmt = $pdo->prepare($sql); // sql vorbereiten
    7. $stmt->execute($params); // execute die parameter für die platzhalter mit geben
    8. // und nun fetchAll oder der gewünschte weg, um die daten zu ziehen


    Bei dem Bsp haben wir keinen Typ der Werte übergeben.
    Das brauchen wir auch nicht, denn default wird immer ein PDO::PARAM_STRING eingefügt.
    Dabei muss man aber bedenken, dass 1 als '1', 1.2 als '1.2' (...) eingefügt wird.
    Das ist fast immer in Ordnung.
    Der einzige Fall, in dem ich bisher den Typ mittels ::bindParam mitgeben musste ist,
    wenn man eine LIMIT Query mit Platzhatern verwendet:


    PHP
    1. $sql = 'SELECT * FROM `tablename` WHERE `foo` = :foo LIMIT :skip, :limit;';


    Hier erwartet der Mysql Server Zahlen (integer).
    Würden wir also keinen Typ angeben, würde PDO eine (zB) '2' einfügen, statt einer 2.


    Das heißt, dass wir einfach bei einem LIMIT die parameter binden (so wie in Deinem Bsp).


    Welche Variante Du nutzt ist Dir überlassen.


    ###


    Du hast en "Dreher" bei dem var_dump Bsp:


    SQL
    1. SELECT `hashid` FROM `Registriergang` WHERE email = `stef@test.de` -- <- die `` gehören um email, und der wert wäre innerhalt der ''
    2. -- aber die '' um die werte übernimmt ja PDO für uns


    Lässt sich relativ leicht merken:
    Ist es ein Wert, dann '',
    sosnt `` (Datenbank-, Tabellen-, und Spaltennamen)


    ###


    Zum try/catch

    PHP
    1. try
    2. {
    3. $stmt = $pdo->prepare('SELECT `hashid` FROM `Registriergang` WHERE email = ? '); // keine `` um das ?, dafür aber um `email`
    4. $stmt->bindParam(1, $email, PDO::PARAM_STR);
    5. $result = $stmt->execute();
    6. } catch (Exception $e){ // einfach $e ist einfacher
    7. echo 'Ein Fehler ist aufgetreten : (' . $e->getCode() . ') ' . $e->getMessage(); // würde den code noch nutzen, der lässt sich oft gut googlen
    8. exit;
    9. }


    Sollte so funktionieren.

  • Hey,


    Ok ,gut zu wissen.


    Habs gemerkt. :D


    Nun noch zu ner Sache, ich möchte wenn benutzername und/oder email vergeben sind eine fehlermeldung ausgeben.


    Meine Idee dies zu machen ist die daten nach dem eintrag selektieren/auswählen und dann mit array die daten übergeben und dann diese fetchen(ziehen) lassen und wenn der gezogende inhalt der selbe ist welcher eingegeben worde ist soll dann die Fehlermeldung kommen.


    Habe es bis jetzt so gedacht:


    Das Problem ist aber, das die Fehler nicht erkannt werden. ich habe am anfang des scripts ein array in der var $fehler.


    Ich sag da ja wähle email und benutzername von registrierdaten wo benutzername ist benutzername und email ist email und wenn da schon die selbe daten drin stehen die fehler in den array fehler packen.


    Ich glaub da habe ichn fehler gemacht ?


    Stef

  • Hi,


    Ja das kann man auch machen. Man kann entweder mit : oder ohne je nach Geschmackssache.


    Könnte mir jemand doch noch bei meinem letzten aktuellen problem helfen ? Saß heute nochmal 2 stunden dran und irgendwie kommen nie fehler.


    EDIT:


    Damit ja in der Datenbank die felder benutzername und email verglichen werden sollen mit eingabe, muss ich jeder inhalt der reihen mit eingabe vergleichen.


    Habe jetzt mal den ganzen Inhalt ausgeben lassen, dass ich weiß obs funktioniert:



    Nun muss ich ja in der while-bedingung überprüfen ob der inhalt der reihen der selbe ist wie users eingabe falls ja soll die fehlermeldung kommen das die daten schon verwendet werden. Dann würde ich da noch ein if statement reinmachen wie z.b. :



    Darf ich deklarierte variablen auch im pdo verwenden welchse von auserhalb kommen ?


    Nun nochmal überarbeitet mein aktuelles script welches die fehlermeldugen ausgibt jedoch für jede Zeile wegen while,also ist while eher nicht so gedacht dafür. Welche würdet ihr benutzen ?



    Das ist die Ausgabe:


    Die eingegebene Email ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Der eingegebene Benutzername ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Der eingegebene Benutzername ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Der eingegebene Benutzername ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Der eingegebene Benutzername ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Der eingegebene Benutzername ist schon vergeben!
    Der eingegebene Benutzername ist schon vergeben!
    Der eingegebene Benutzername ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Der eingegebene Benutzername ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Der eingegebene Benutzername ist schon vergeben!
    Die eingegebene Email ist schon vergeben!
    Der eingegebene Benutzername ist schon vergeben!
    Die eingegebene Email ist schon vergeben!


    Hier könnt ihr es testen : http://apple231.bplaced.net/Re…rvorgang/registrieren.php
    Danke


    Stef

  • In Deinem ursprünglichen Post DB PDO Wert aus Datenbank mit variable vergleichen
    hast Du den Benutzer eingefügt (INSERT INTO), und dann geprüft, ob er existiert 8|


    Das hier (ungetestet) sollte funktionieren

  • Morgen,


    ich habe die überprüfung vor dem db eintrag gestellt, wäre ja unlogisch erst nach dem eintrag zu überprüfen ob dies schon exsistiert.


    Habe mal mein code mit deinem angepasst. Nun gehts auch. Jedoch möchte ich für eingegebenen Username und Password eine einzelne Fehlermeldung, d.h. wenn username schon vergeben ist soll die eine kommen und wenn email vergeben ist die andere, nur in jetzigem code kann man es nicht machen. Denn dort zählt man ja nur die rows welche den selben wert zurückgeben. Und wenn dies größer als 0 ist mache das. Aber ich möchte speziell für username und email eine haben das der user weiß, ach der Username ist verwendet unso.


    Wie könnte man es so verwirklichen ?


    Vielen Dank für deine Mühe :)


    Gruß,
    Stef

  • Dann kannst Du die Felder zählen lassen.


    Bsp Ergebnis

    Code
    1. # benutzername, email
    2. '3', '2'


    Ich hatte testweise mal nen Table angelegt mit 3 x dem gesuchten Benutzernamen, und 2 mal der gesuchten Email.
    (email und benutzername sollten allerdings immer nur einmal vorkommen - siehe UNIQUE index Post oben)


    In PHP (In $result) prüfst Du dann, ob
    email > 0 (dann email schon vergeben)
    benutzername > 0 (benutzername schon vergeben).


    Du solltest immer exact 1 row bekommen. Wenn email und benutzername in der tabelle nicht vokommen,
    dann gibts 1 row mit den Werten 0 und 0.

  • Hey,


    habe mein prepare jetzt so angepasst, jedoch check ich irgendwie die Prüfung jetzt nicht welche ich mache muss.


    Ich muss prüfen wie du gesagt hast ob email und benutzername einen höheren wert als 0 haben.


    Das würde ich so machen:


    Aber jedesmal gibt er mir die catch fehlermeldung aus : Ein Fehler ist aufgetreten : (HY093) SQLSTATE[HY093]: Invalid parameter number
    D.h. das eine parameter number falsch/invalid ist. Aber davon seh ich nix.


    U.a. wie kann man denn diese ifs besser scripten? Weil ich blick da grad nicht durch...


    Vielen Dank,


    Gruß, Stef

  • Du hast vergessen die row zu ziehen:

    PHP
    1. $stmt_uberprufung = ..
    2. $stmt_uberprufung->execute ...
    3. $row = $stmt_uberprufung->fetch(); // zieht eine row, und wir erwarten nur eine
    4. if($row['count_benutzername'] > 0){
    5. // benutzername schon vergeben
    6. }
    7. if($row['count_email'] > 0){
    8. // email schon vergeben
    9. }


    Die Fehlermeldung sagt, dass Anzahl Platzhalter und Anzahl der übergebenen Platzhalter => Werte nicht übereinstimmt.
    Das sollte aber so funktionieren. Denn 2 x :email braucht nur 1 x array('email' => $email).


    Anders geht die Query immer. Aber ich denke diese macht am meisten Sinn.
    Durch die WHER Bedingung werden alle rows gesucht, die benutzername oder email besitzen.
    Und dann wird aus diesen rows die counts erstellt.
    Bei UNIQUE benutzername und email sollte das max 2 rows sein, welche (wenn ich mich nicht irre) 4 x COUNT() ausführen.
    Die IFs sind schon kurz: WENN, DANN, SONST. Und die müssen sein, damit COUNT() nicht mitzählt, wenn benutzername oder email nicht gleich den gesuchten Wert enthält.


    Wenn Du immernoch die Fehlermeldung bekommst, dann versuche mal das:


    aber wie gesagt, eigtl sollte es ohne "sinnlose extraPlatzhalter" funktionieren.

  • Hey,


    Ups. Garnicht bemerkt, war durchn wind..


    ich habe jetzt deine beide Beispiele angewandt. Nun funktionieren beide aber nicht.


    Bei dem 1sten kommt folgende Meldung : Ein Fehler ist aufgetreten : (HY093) SQLSTATE[HY093]: Invalid parameter number wie vorher


    Und beim 2ten kommt folgender error: Cannot use object of type stdClass as array in


    Die 2te Meldung bezieht sich auf dies :



    Warum ist sowas nur so kompliziert...


    Stef

  • Habe es jetzt so gemacht :



    jedoch obwohl ich schon eine benutze email und username eingebe kommt registration erfolgreich. irgendwas scheint da nicht zu klappen..


    EDIT:


    Mein Fehler man darf bei fetch nicht PDO::FETCH_ASSOC verwenden da man ja ein objekt zieht, habs jetzt zu PDO::FETCH_OBJ geändert und es klappt


    Es wäre gut wenn du dir das andere nochmal anschaust ohne diese Extra Platzhalter. Würde mich interessieren


    vielen Dank Cottton :)