Page 1 sur 1

lastInsertId ne fonctionne pas

Posté : 01 sept. 2022, 14:02
par Ikbal
Bonjour,
J'aurai besoin d'un coup de pouce concernant un problème que j'ai avec lastInsertId().

J'ai un système d'articles auquel je veux ajouter la possibilité de le créer avec une miniature. L'insertion de l'article se fait correctement dans la bdd, et l'image est bien enregistré dans le dossier "cours_miniatures" que j'ai créé pour l'occasion. SAUF QUE je me retrouve toujours avec pour valeur lastInsertId de 0 et je ne comprends pas pourquoi. Je me suis baladé sur le net pendant une bonne heure sans trouver de solution à mon problème.

Le schéma de la table concernée : [ id (Clé primaire), id_matiere (Clé étrangère), titre, contenu, date_publication, date_edition]
et le moteur c'est InnoDb

Je m'essaye au modèle MVC de la POO php. J'ajoute de suite les portions de code concernées :
FICHIER INCLUDE QUI CHARGE LES CLASSES
<?php

// Vérifier que le boutton Publier le cours est utilisé
if(isset($_POST['cours_redaction'])) {

    // Récupérer les infos du formulaire
    $cours_titre = htmlspecialchars($_POST['cours_titre']);
    $id_matiere = htmlspecialchars($_POST['id_matiere']);
    $cours_contenu = htmlspecialchars($_POST['cours_contenu']);
    $cours_miniature = $_FILES['miniature'];
    //var_dump($cours_miniature);

    // Initialiser la classe CoursCtrl
    require_once 'classAutoloader.inc.php';

    $cours = new CoursCtrl($cours_titre, $id_matiere, $cours_miniature, $cours_contenu);
    var_dump($cours);

    // Gestion des erreurs et ajout du cours
    $cours->addCours();

    // Redirection
    //header('location: ../cours/index_cours.php');

}
CONNEXION BASE DE DONNES
<?php

class Dbh {
    private $host = 'localhost';
    private $username = "root";
    private $password = "";
    private $dbName = 'btp';

    protected function connect() {
        try {
            $dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbName;
            $dbh = new PDO($dsn, $this->username, $this->password);
            $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

            return $dbh;
        } catch (PDOException $e) {
            echo "Error :" . $e->getMessage() . "<br>";
            die();
        }
    }
}
CONTROLER COURS
<?php

class CoursCtrl extends Cours {

    private $cours_titre;
    private $id_matiere;
    private $cours_contenu;
    private $cours_miniature;

    public function __construct($cours_titre, $id_matiere, $cours_miniature, $cours_contenu) {
        $this->cours_titre = $cours_titre;
        $this->id_matiere = $id_matiere;
        $this->cours_contenu = $cours_contenu;
        $this->cours_miniature = $cours_miniature;
    }

    public function addCours() {
        if($this->emptyInput()) {
            header("location: ../cours/cours_redaction.php?error=emptyInputs");
            exit();
        }
        $this->setCours($this->cours_titre, $this->id_matiere, $this->cours_miniature, $this->cours_contenu);
    }

    public function editCours($edit_id) {
        if($this->emptyInput() == false) {
            header("location: ../cours/cours_redaction.php?edit={$edit_id}&&error=emptyInputs");
            exit();
        }
        $this->updateCours($this->cours_titre, $this->id_matiere, $this->cours_contenu, $edit_id);
    }
MODEL COURS
<?php

class Cours extends Dbh
{

    protected function setCours($cours_titre, $id_matiere, $cours_miniature, $cours_contenu)
    {
        $query = "INSERT INTO cours (titre, id_matiere, contenu, date_publication) VALUES (?, ?, ?, NOW())";
        $stmt = $this->connect()->prepare($query);

        if (!$stmt->execute(array($cours_titre, $id_matiere, $cours_contenu))) {
            $stmt = NULL;
            header('location: ../cours/cours_redaction.php?error=stmtfailed');
            exit();
        }

        $lastId = $this->connect()->lastInsertId();
        var_dump($lastId);

        if(exif_imagetype($cours_miniature['tmp_name']) != 3) {
            header('location: ../cours/cours_redaction.php?error=notpng');
            exit();
        }

        $imgPath = '../cours/cours_miniatures/' . $lastId . '.png';
        var_dump($imgPath);
        move_uploaded_file($cours_miniature['tmp_name'], $imgPath);

        session_start();
        $_SESSION['cours_edition'] = true;
        $stmt = NULL;
    }

Re: lastInsertId ne fonctionne pas

Posté : 01 sept. 2022, 14:49
par @rthur
Moi j'aurais tenté
$stmt = $this->connect();
$stmt->prepare($query);
$stmt->lastInsertId();

Re: lastInsertId ne fonctionne pas

Posté : 01 sept. 2022, 16:05
par Ikbal
Voilà ce que j'ai finalement fait :
$query = "INSERT INTO cours (titre, id_matiere, contenu, date_publication) VALUES (?, ?, ?, NOW())";
        $stmt = $this->connect();

        if(!$stmt->prepare($query)->execute(array($cours_titre, $id_matiere, $cours_contenu))) {
            $stmt = NULL;
            header('location: ../cours/cours_redaction.php?error=stmtfailed');
        }

        $lastId= $stmt->lastInsertId();
        //var_dump($lastId);
Si je comprends bien, en faisant avant
$this->connect()->lastInsertId();
ça ne fonctionnait pas parce que du coup il ne ciblait pas la table dans laquelle il y avait eu l'insertion mais juste cette portion de code se connecte à la bdd et demande automatiquement l'id de la dernière table ? Du coup je devais récupérer l'id du dernier INSERT de $stmt ?

Seul truc bizarre c'est que lorsque je rédige le code comme tu l'as fais pour l'insertion : connect(); ensuite prepare(); et enfin execute(); j'ai une erreur qui me dit que execute n'est pas une method de PDO. Une idée de pourquoi cela ?

Re: lastInsertId ne fonctionne pas

Posté : 01 sept. 2022, 19:51
par ynx
lastInsertId() et prepare() sont des méthodes de la classe PDO.
execute() est une méthode de la classe PDOStatement.

$pdo = $this->connect();
$stmt = $pdo->prepare($query);
$stmt->execute();
$lastId = $pdo->lastInsertId();

En faisant $this->connect()->lastInsertId(); tu crées une 2e connexion à la bdd puisque tu as déjà utilisé la méthode connect() un peu avant. Il faut utiliser une seule fois la méthode connect() pour récupérer ton instance de PDO, et utiliser la même instance pour le reste de ton traitement.

Re: lastInsertId ne fonctionne pas

Posté : 02 sept. 2022, 00:20
par Ikbal
Je comprends beaucoup mieux maintenant. Merci pour l'aide !