[RESOLU] lastInsertId ne fonctionne pas

Eléphanteau du PHP | 17 Messages

01 sept. 2022, 14:02

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;
    }

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

01 sept. 2022, 14:49

Moi j'aurais tenté
$stmt = $this->connect();
$stmt->prepare($query);
$stmt->lastInsertId();
Quand tout le reste a échoué, lisez le mode d'emploi...

Eléphanteau du PHP | 17 Messages

01 sept. 2022, 16:05

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 ?

ynx
Mammouth du PHP | 586 Messages

01 sept. 2022, 19:51

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.

Eléphanteau du PHP | 17 Messages

02 sept. 2022, 00:20

Je comprends beaucoup mieux maintenant. Merci pour l'aide !