[PHP/SQL] INSERT mit PDO prepared funktioniert nicht.

B

BloodSteam

Guest
Moin,
hab schon verschiedene Sachen versucht und es geht irgendwie nicht.
Ich verstehe nicht wieso es nicht funktioniert, es postet "User has been created." aber in "HeidiSQL (localhost)" sehe Ich nichts.

Code:
if(empty($_POST['username']) || empty($_POST['email']) || empty($_POST['password'])){
    echo "Signup form isn't filled.";
    exit();
}else{
    // Set variables
    $username = $_POST['username'];
       $email = $_POST['email'];
    $password = $_POST['password'];


    // Prepare query
    $stmt = $pdo->prepare("SELECT * FROM users WHERE email = ? OR username = ?");
    $stmt->execute([$email,$username]);
    if($stmt->rowCount() !== 0){
        echo 'Email or username is taken.';
        exit();
    }else{
        // FIX: Doesn't insert anything into the DB.
        $stmt = $pdo->prepare("INSERT INTO users (email,password,username) VALUES (?,?,?)");
        $stmt->execute([$email,$password,$username]);
        echo 'User has been created.';
        exit();
    }
}
 
Vielleicht ist das ja im Endeffekt aufschlussreicher
PHP:
if(empty($_POST['username']) || empty($_POST['email']) || empty($_POST['password'])){
   echo 'Signup form isn\'t filled.';
}else{

   // Set variables
   // HIER TROTZDEM BESSER PRÜFEN. Prepared-Statements schützen nicht vor XSS.  
   $username = $_POST['username'];
   $email = $_POST['email'];
   // Und warum wird hier ein Klartext-Passwort gespeichert? ARGH ^^ Erinnert mich bitte daran, mich nie bei irgendeinem System von BloodSteam zu registrieren. ^^
   $password = $_POST['password'];

   // Prepare query
   $stmt = $pdo->prepare('SELECT 1 FROM users WHERE email = :email OR username = :username');
   $stmt->bindValue(':email', $email, PDO::PARAM_STR);
   $stmt->bindValue(':username', $username, PDO::PARAM_STR);
   if ( $stmt->execute() ) {
      if ( (int)$pdo->errorCode() ) {
         echo 'Fehler ' . print_r($pdo->errorInfo(), true);
      } else {
         if ($stmt->rowCount() !== 0) {
            exit('Email or username is taken.');
         } else {
            // FIX: Doesn't insert anything into the DB.
            $stmtInsert = $pdo->prepare('INSERT INTO users (email,password,username) VALUES (:email,:password,:username)');
            $stmtInsert->bindValue(':email', $email, PDO::PARAM_STR);
            $stmtInsert->bindValue(':password', $password, PDO::PARAM_STR);
            $stmtInsert->bindValue(':username', $username, PDO::PARAM_STR);
            if ( $stmtInsert->execute() ) {
               if ( (int)$pdo->errorCode() ) {
                  echo 'Fehler ' . print_r($pdo->errorInfo(), true);
               } else {
                  echo 'User has been created.';
               }
            }
         }
      }
   }
}
exit;
 
Zu dem Passwort, Ich glaube wir haben beide ein anderen Verlauf beim Coden. Ich mache es immer so, Schritt -> Testen -> Schritt -> Testen. Schritt (INSERT) -> Testen -> Fixen. Solange es nicht gefixt ist, brauche Ich es nicht zu hashen. Wenn mein Insert funktioniert, dann wird weiter gemacht.

@edit
Hab was getestet.
Dies hier funktioniert nicht
Code:
$stmt = $pdo->prepare("INSERT INTO users (email,password,username) VALUES (?,?,?)");
und
Code:
$stmt = $pdo->prepare("INSERT INTO users (email,password,username) VALUES (:email, :password, :username)");
Das hier geht.
Code:
$stmt = $pdo->prepare("INSERT INTO users (email,password,username) VALUES ('abc','123','f121212')");
 
Zuletzt bearbeitet:
Dann ist einer der übermittelten Werte leer und das zugehörige Tabellenfeld ist definiert mit "NOT NULL" oder es gibt eine andere Unstimmigkeit bei den Feld-Definitionen der Tabelle und den übermittelten Werten.
Interessant, dass du bei meinen Anpassungen keine Fehlermeldungen bekommst. Zumindest ein SQL-Fehler müsste dann ausgegeben werden.
 
Kannst du es auch erklären? Es funktionier danke aber dennoch lege Ich es Wert drauf es zu verstehen.
Code:
$stmtInsert = $pdo->prepare('INSERT INTO users (email,password,username) VALUES (:email,:password,:username)');
            $stmtInsert->bindValue(':email', $email, PDO::PARAM_STR);
            $stmtInsert->bindValue(':password', $password, PDO::PARAM_STR);
            $stmtInsert->bindValue(':username', $username, PDO::PARAM_STR);
            if ( $stmtInsert->execute() ) {
               if ( (int)$pdo->errorCode() ) {
                  echo 'Fehler ' . print_r($pdo->errorInfo(), true);
               } else {
                  echo 'User has been created.';
               }
            }
        exit;
 
Zuletzt bearbeitet:
Was genau? Meinst du den Code-Ablauf?

PDO->errorCode() liefert nach einem execute() des Prepared-Statements in der Regel immer '0000', wenn kein Fehler auftritt, daher mache ich einen Int-Cast auf 0. Liefert die Funktion keine 0 zurück, liegt ein Fehler vor, den du mit PDO-errorInfo() (ist ein Array mit dem Error-Stack) abrufen kannst.

bindValue mit direkten Namens( :xxx )- statt Positions( ? )-Platzierungen nutze ich aus Gewohnheit, falls man den gleichen Wert an mehreren Stellen braucht. Und man kann hier genau(er) definieren, um was für einen Übergabetyp es sich handelt mit PDO :: PARAM_*.
 
I bims wieder :D Der noob der nicht programmieren kann :cool:

ALSO... Ich weiß nicht was hier nicht funktioniert. Ich bekomme kein SQL error oder sonnst was und es funktioniert nicht.

Ziel = Soll nur die id und usernamen ausgeben.

userlist.php
Code:
include_once 'dbh.php';

class Users extends Dbh
{
    private $sql = 'SELECT id,username FROM users';

    function __construct()
    {
        parent::__construct();
    }

    public function getUsers(){
        return $this->conn->query($this->sql);
    }
}

$users = new Users();

$result = $users->getUsers();
echo var_dump($result);

dbh.php
Code:
class Dbh
{
    private $host = '127.0.0.1';
    private $port = '3306';
    private $username = 'root';
    private $password = '123';
    private $dbname = 'loginsystemdb';
    private $charset = 'utf8mb4';

    protected $conn;

    function __construct()
    {
        try {
            $this->conn = new PDO("mysql:host=$this->host;port=$this->port;dbname=$this->dbname;charset=$this->charset", $this->username, $this->password);
            $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return $conn;
        } catch (PDOException $e) {
            echo 'Mysql Connection failed: '.$e->getMessage();
        }
    }
}
 
Versuch es mal mit:
Code:
echo var_dump($result->fetchall());

So weit ich mich erinnern kann, bekommst du bei einem Query immer ein PDOStatement-Objekt zurück und nicht direkt die Daten. Die erhältst du, wenn du die Daten aus dem Statement fetch'st.
 
Nach 300 tutorials und ca 24h... geht.. aber nicht ganz.

ALSO... das hier geht.
Code:
public function insert($email,$password,$username)
    {
        $this->bind(':email', 'hello@kevin.com');
        $this->bind(':password', 'pro420');
        $this->bind(':username', 'XxPROxX');
        $this->execute();
    }

aber das hier nicht.
Code:
public function insert($email,$password,$username)
    {
        $this->query('INSERT INTO users (email, password, username) VALUES (:email, :password, :username)');
        $this->bind(':email', 'hello@kevin.com');
        $this->bind(':password', 'pro420');
        $this->bind(':username', 'XxPROxX');
        $this->execute();
    }

Und die variablen funktionieren 100%, wenn Ich ein echo nutze, wird alles angezeigt. :x Keine Fehler etc.

Wenn Ich nur ein echo hinzufüge.

abc-jpg.1028907


PS: Ja Ich hashe die Passwörter, will aber nicht dieses gekritzel sehen und deswegen hab es auskommentiert und einfach nur $_POST benutze weil Ich weiß dass es funktioniert lul. Wenn Ich das gehashte benutze ist die Konsole voll :x
 

Anhänge

  • abc.jpg
    abc.jpg
    141,7 KB · Aufrufe: 524
Zuletzt bearbeitet:
Da interessieren mich zwei Dinge,

1. Woher kommt bind() - PDO wäre bindParam oder (für den Fall mit Benamung) bindValue() korrekt. Und query() statt prepare() ? Was hast du da für eine Klasse zusammengefummelt?
2. Tabellenstruktur von "user", zeige mal die komplette CREATE-Anweisung.
 
Ist es eine gute Idee php sessions zu verwenden oder gibt es da eine bessere dennoch sichere möglichkeit?
Ich nutze PHP 7.2.8
 
Ist es eine gute Idee php sessions zu verwenden oder gibt es da eine bessere dennoch sichere möglichkeit?
Ich nutze PHP 7.2.8

Für kleine Gammelprojekte kannst du das gern machen. Bei Community-Getriebenen Seiten mit ein paar hundert/tausend AU pro Tag, würde ich das eher nicht. ^^
Alternativen gibt es dann genug bspw. über Datenbanken bzw. NOSQL oder Memory-Cache. Whatever - was deine Infrastruktur halt bietet und du umsetzen kannst.
 
Für kleine Gammelprojekte kannst du das gern machen. Bei Community-Getriebenen Seiten mit ein paar hundert/tausend AU pro Tag, würde ich das eher nicht. ^^
Alternativen gibt es dann genug bspw. über Datenbanken bzw. NOSQL oder Memory-Cache. Whatever - was deine Infrastruktur halt bietet und du umsetzen kannst.

Also hab Ich ein Array im MemCache mit den allen usern? Aber wie vergebe Ich die logins? Sende Ich eine zufällige Nummer im Header and den user? Dann muss Ich aber auch was machen damit Sich die nummer nie ändert. Ich hab nur eine PHP Datei und alles andere läuft mit AJAX.
 
Ich nutze mal einfach dieses Thread anstatt wieder ein neues zu eröffnen.

Wie Ich ein "Key : Value" Paar an das Frontend senden? Also zb:
Code:
return { 'type' : 'signup', 'text' : 'Erfolgreich Zugestellt'}
 
Ich raste gleich aus....

Hab alles auf ein Webhosting hochgeladen und bekomme einen Fehler obwohl die SQL Daten stimmen.
Lustinge dran ist dass es mit Mamp funktioniert (localhost).

Code:
<br /> <b>Fatal error</b>:  Uncaught Error: Call to a member function prepare() on null in dbc.php:51 Stack trace:
#0 signup.php(12): Database->query('SELECT email,us...') 
#1 router.php(37): Signup->addNewUser('damian@q.com', '$2y$10$xEf6v.7a...', 'damian') 
#2 {main}   thrown in <b>dbc.php</b> on line <b>51</b><br />

Was kann das bedeuten? #0 ist eine Query zusehen, bei #1 sind Sachen aus $_POST zusehen.

In Line 51 hab Ich dies hier:
Code:
    public function query($query)
    {
        $this->stmt = $this->dbh->prepare($query);
    }
 
Naja "Call to a member function prepare() on null" heißt, dass $this->dbh kein PDO-Objekt an der Stelle ist. Das kann bspw. entstehen, wenn deine Live-Umgebung kein PDO aktiv hat. Das kannst du bspw. herausfinden mit class_exists('PDO') und dann die Server-Config entsprechend anpassen, sofern dein Hoster bzw. dein Paket es zulässt.
 
Zurück