PHP lastInsertId() bringt immer 0 zurück

CheeseCakeMen

Cadet 3rd Year
Registriert
Feb. 2021
Beiträge
42
Kann mir jemand weiterhelfen und vielleicht sagen warum lastInsertID immer : string(1) "0" zurückliefert?

Meine Abfrage sieht so aus:
PHP:
$db = new DB();
$sql = 'INSERT INTO bonus (bonus_id , bonus_code) VALUES (:bonus_id, :bonus_code)';
$stmt = $db->connect()->prepare($sql);
$stmt->execute(array('bonus_id' =>  'NULL', bonus_code' => $bonuscode));
$lastid = $db->connect()->lastInsertId('bonus');

Meien Datenbank Klasse sieht so aus:
PHP:
<?php
class DB {
    public function connect() {
        try {
            $datasource = "mysql:host=localhost;dbname=labcaches";
            return new \PDO($datasource, "root", "");
        } catch (PDOException $exc) {
            echo $exc->getTraceAsString();
            die();
        }
    }
}
?>
 
Hi,

wieso machst du immer einen neuen Connect? Erzeuge dir doch das PDO Objekt einmal und fertig. So erzeugst du ja immer eine neue Verbindung, und die hatte doch noch keine lastInsertId...oder übersehe ich was?

VG,
Mad
 
  • Gefällt mir
Reaktionen: Fombu und Marco01_809
lastInsertId() ist ja auch eine Methode auf dem PDO-Objekt und bezieht sich somit nur auf diese Verbindung. Da du lastInsertId() auf einer anderen, neuen PDO-Verbindung aufrufst war da natürlich noch kein insert.

Die ganze DB-Klasse ist ja auch sinnlos wenn du gar nichts wrappst und doch das PDO-Objekt herausgibst.. Eine sinnvolle Abstraktion könnte so aussehen.

PHP:
<?php
class DB {
    private $db;

    public function __construct() {
        try {
            $datasource = "mysql:host=localhost;dbname=labcaches";
            $this->db = new \PDO($datasource, "root", "");
        } catch (PDOException $exc) {
            echo $exc->getTraceAsString();
            die();
        }
    }

    public function insertBonus($bonuscode) {
        $sql = 'INSERT INTO bonus (bonus_id , bonus_code) VALUES (:bonus_id, :bonus_code)';
        $stmt = $this->db->prepare($sql);
        $stmt->execute(array('bonus_id' =>  'NULL', 'bonus_code' => $bonuscode));
        return $this->db->lastInsertId();
    }
}

Bei MySQL den Namen bei lastInsertId() weglassen.
 
Danke Euch erst einmal, allerdings verstehe ich gerade nicht wie ich es besser machen könnte.

Wie kann ich es anders machen, dass nicht jedes Mal eine neue Verbindung aufgebaut wird? Der Code von Maro01_809 bedeutet ja am Ende das ich alles Funktionen in der DB Klasse schreiben sollte, oder verstehe ich das falsch?
 
Hi,

du sollst die Datenbankverbindung einfach einmalig aufmachen und dann immer mit dem selben Objekt arbeiten.

VG,
Mad
 
Danke das habe ich schon so verstanden, allerdings weis ich nicht wie ich das umsetzen soll?
 
Hi,

indem du deine Datenbankverbindung einmalig aufbaust und dann mit dem Objekt weiterarbeitest! Was ist daran so unverständlich? Wo genau hapert es denn? Was machst du mit einer separaten "DB" Klasse? Was erhoffst du dir davon? Mach einfach ein PDO Objekt und fertig.

Code:
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);

wieso mit einer separaten Klasse aufblähen, wenn du damit nur Probleme bekommst und am Ende doch nur die Verbindung aufbaust?

VG,
Mad
 
  • Gefällt mir
Reaktionen: Fombu
Habe eine Datei, wo ich die ganzen DB Abfragen zentral mache.

Code:
$db = new PDO('mysql:host=localhost;dbname=games', 'root', '');

function fetchCountries(){
    $stmt= $this->prepare('SELECT game_id, game_name FROM games');
    $stmt->execute();
    return $countries = $stmt->fetchAll();
}

Allerdings zeigt mir VSCode immer:
Code:
Cannot use '$this' in non-object context.intelephense(1030)
 
Hi,

da ist das Stichwort der Scope. Klar dass das so nicht funktioniert.

Bitte erstmal die Grundlagen richtig anlesen und lernen und verstehen. Was soll denn "$this" deiner Meinung nach hier sein? Und was heißt eine "Datei, wo ich die ganzen DB Abfragen zentral mache"?

Liest sich alles eher zusammenkopiert und ziemlich konfus.

VG,
Mad
 
  • Gefällt mir
Reaktionen: Fombu
Das die Variable $db in der Funktion nicht gültig ist, dachte ich mir schon. Ohne sie global zu setzen kann ich auf diese in der Funktion nicht zugreifen. Kenne das aber das man versucht so wenig wie möglich global zu setzen. Oder irre ich mich hier?

Mit eigener Datei meinte, ich das alle Datenbankabfragen welche nutze in einer Datei: fetchDBData.php zentral gelistet sind und via Funktionen gebe ich nur die Ergebnisse zurück.
 
Hi,

das ist ja auch ok. Aber wenn du auf das Property eines Objekts zugreifen möchtest muss das Objekt erstens das Property gesetzt haben und zweitens instanziiert sein.

Du musst es nicht zwingend global machen (wobei ich da bei einer Datenbankverbindung absolut keine Probleme hätte), aber zumindest muss es zu dem Punkt verfügbar sein, wo du drauf zugreifen willst. Und dann kannst dann logischerweise nicht in einer anderen Funktion ein neues Objekt instanziieren und auf Properties des alten Objekts zugreifen.

VG,
Mad
 
Um darauf zugreifen zu hatte ich ja eine neue Instanz von der Klasse DB erzeugt und via connect die Verbindung hergestellt!
Wie hätte ich es deiner Meinung nach machen sollen? Kannst mir nen kurzer Beispiel vlt. geben?
 
Hi,

eben genau NICHT eine neue Instanz erzeugen, sondern - zum hundertsten Mal - auf das bestehende Objekt zugreifen!

VG,
Mad
 
CheeseCakeMen schrieb:
Kannst mir nen kurzer Beispiel vlt. geben?
Du hast doch alles was Du wissen musst. Du musst es "nur" noch umsetzen.
Klar könnte man auch den Code einfach hinschreiben, allerdings lernst Du dann nix dabei.

Ich versuche es noch mal anders:
Jeder Aufruf von $db->connect() macht eine neue Datenbankverbindung auf. Was Du aber nicht willst. Denn sonst funtioniert das mit der lastInsertId nicht.
Du musst also Deinen Code so umschreiben, das $db->connect() maximal einmal aufgerufen wird.

Das Du das auf Anhieb nicht hinbekommst ist nicht schlimm und als Anfänger normal.
Denk einfach mal in Ruhe noch mal über den Lösungsansatz nach, schlaf ne Nacht drüber.
Ich bin mir fast sicher, das Du drauf kommst.
 
Option 1: Dependency injection
PHP:
$dbh = ...
   
function fetchCountries(PDO $dbh){
    $stmt= $dbh->prepare('SELECT game_id, game_name FROM games');
    ...

Aber ja, hier mangelt es an Grundwissen.
Und es wäre auch nicht verkehrt, sich das Thema Design Pattern anzuschauen.
 
Zurück
Oben