Uncaught Error: Call to undefined method Database::prepare()

Résolu/Fermé
chabinot Messages postés 321 Date d'inscription mardi 10 novembre 2015 Statut Membre Dernière intervention 22 mars 2024 - 11 déc. 2017 à 09:59
chabinot Messages postés 321 Date d'inscription mardi 10 novembre 2015 Statut Membre Dernière intervention 22 mars 2024 - 11 déc. 2017 à 17:13
Bonjour,
J'ai un erreur que je ne comprends pas :Fatal error: Uncaught Error: Call to undefined method Database::prepare() in D:\serveur\www\boom\register.php:75 Stack trace: #0 {main} thrown in D:\serveur\www\boom\register.php on line 75.
1 - Source classe Database :
<?php 

class Database
{
  private $db_host        = 'localhost';
  private $db_name        = 'boom'; 
  private $db_port        = 3309;
  private $db_charset     = 'utf8';
  private $db_user        = 'root';
  private $db_password    = '';
  private $dsn;
  private $error;

  public function __construct()
  {
    $this->dsn = "mysql:host={$this->db_host};dbname={$this->db_name};port={$this->db_port};charset={$this->db_charset}";
    try {
      $this->pdo = new PDO($this->dsn, $this->db_user, $this->db_password);
      $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    } catch(PDOException $e) {
      echo $this->error = 'Erreur: ' . $e->getMessage();
    }
  }

  public function is_already_in_use($field, $value, $table)
  {
    $req = $this->pdo->prepare("SELECT id FROM $table WHERE $field = ?");
    $req->execute([$value]);
    $count = $req->rowCount();
    $req->closeCursor();

    return $count;
  }

}

2 - Source register.php
<?php
// Ouverture de la session 
session_start();

// URL
$host = $_SERVER['HTTP_HOST'];
$uri = $_SERVER['REQUEST_URI'];
$url = sprintf("%s%s%s", "http://", $host, $uri);

$http = explode('/', $url);
$http = $http[0] . '//' . $http[2] . '/' . $http[3];

// Autoloading
require __DIR__ . '/vendor/autoload.php';

// Envoi du courriel via PHPMailer
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

$mail = new PHPMailer(true);

// Accès à la base de données
$bdd = new Database();

// Gestion des erreurs
$errors = new Errors();

// Traitement du formulaire soumis
if (isset($_POST['register'])) {
  // Tous les champs ont été remplis ?
    if (not_empty(['name', 'pseudo', 'email', 'password', 'password_confirm'])) {
        extract($_POST);
        if (mb_strlen($name) < 3) {
            $error = $errors->setError('Nom trop court (minimum 3 caractères)');
        }
        if (mb_strlen($pseudo) < 3) {
            $error = $errors->setError('Pseudonyme trop court (minimum 3 caractères)');
        }
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $error = $errors->setError('Adresse courriel invalide');
        }
        if (mb_strlen($password) < 6) {
            $error = $errors->setError('Mot de passe trop court (minimum 6 caractères)');
        } else {
            if ($password != $password_confirm) {
                $error = $errors->setError('Les deux mots de passe ne concordent pas');
            }
        }
        if ($bdd->is_already_in_use('pseudo', $pseudo, 'users')) {
            $error = $errors->setError('Pseudonyme déjà utilisé');
        }
        if ($bdd->is_already_in_use('email', $email, 'users')) {
            $error = $errors->setError('Adresse courriel déjà utilisée');
        }
        if ($errors->countError() == 0) {
            $token = sha1($pseudo . $email . $password);
            // Envoi d'un courriel d'activation
            try {
                //Server settings
                $mail->CharSet = 'UTF-8';
                //Recipients
                $mail->setFrom('contact@boom.com', 'Boom Social Network');
                $mail->addAddress($email, $name);
                //Content
                $mail->isHTML(true);
                $mail->Subject = 'Boom Social Network - ACTIVATION DE COMPTE';
                // Message HTML
                ob_start();
                require __DIR__ . '/templates/emails/activation.tmpl.php';
                $content = ob_get_clean();

                $mail->Body = $content;
                $mail->send();
                // Enregistrer l'utilisateur dans la bdd
               <gras> $req = $bdd->prepare('INSERT INTO users(name, pseudo, email, password)
                                      VALUES(:name, :pseudo, :email, :password)');</gras>
                $executeIsOk = $req->execute([
                    'name'      => $name,
                    'pseudo'    => $pseudo,
                    'email'     => $email,
                    'password'  => sha1($password)
                    ]);

                    if ($executeIsOk) {
                        // Informer l'utilisateur de vérifier sa boîte de réception
                        set_flash('Un courriel d\'activation de votre compte vous a été envoyé', 'success');
                        // Redirection vers sa page de profil
                        redirect('index.php');
                }
            } catch (Exception $e) {
                echo 'Le courriel n\'a pas pu été envoyé.';
                echo 'Erreur: ' . $mail->ErrorInfo;
            }
        } else {
            save_input_data();
        }
    } else {
        $error = $errors->setError('Veuillez remplir tous les champs.');
        save_input_data();
    }
} else {
    clear_input_data();
}

// Titre
$title = 'Inscription';

// Page register.view.php
require __DIR__ . '/views/register.view.php';

L'erreur est interceptée à l'instruction:
$req = $bdd->prepare('INSERT INTO users(name, pseudo, email, password)
                                      VALUES(:name, :pseudo, :email, :password)');

J'ai débogué à plusieurs endroits, je ne vois pas ce qui bloque.
Merci de votre aide.
Cordialement

2 réponses

Utilisateur anonyme
11 déc. 2017 à 14:16
Bonjour

Comme le dit le message, ta classe Database n'a pas de méthode prepare. Dans ton code, je ne vois que le constructeur et is_already_in_use.
Tu peux appeler directement $bdd->pdo.prepare(... puisque ta connexion PDO, c'est la propriété $pdo (pas définie, d'ailleurs) de ta classe. Mais tant qu'à définir une classe, tu peux aussi lui définir sa méthode prepare (qui se contentera d'appeler celle de PDO) et appeler ainsi $bdd->prepare(... sans provoquer d'erreur.
0
chabinot Messages postés 321 Date d'inscription mardi 10 novembre 2015 Statut Membre Dernière intervention 22 mars 2024 15
11 déc. 2017 à 17:13
Merci beaucoup, maintenant cela marche comme je veux, je te montre ce que j'ai fait :
1 - Source Database.php
<?php

class Database
{
  private $db_host        = 'localhost';
  private $db_name        = 'boom'; 
  private $db_port        = 3309;
  private $db_charset     = 'utf8';
  private $db_user        = 'root';
  private $db_password    = '';
  private $dsn;
  private $pdo;
  private $error;

  public function __construct()
  {
    $this->dsn = "mysql:host={$this->db_host};dbname={$this->db_name};port={$this->db_port};charset={$this->db_charset}";
    try {
      $this->pdo = new PDO($this->dsn, $this->db_user, $this->db_password);
      $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    } catch(PDOException $e) {
      echo $this->error = 'Erreur: ' . $e->getMessage();
    }
  }

  public function prepare(String $stmt, Array $fields = []):bool {
    $req = $this->pdo->prepare($stmt);
    $req->execute($fields);

    return $req;
  }

  public function is_already_in_use(String $field, String $value, String $table):bool
  {
    $req = $this->pdo->prepare("SELECT id FROM $table WHERE $field = ?");
    $req->execute([$value]);
    $count = $req->rowCount();
    $req->closeCursor();

    return $count;
  }

}

J'ai ajouté la fonction "prepare".
2 - Source register.php
<?php
// Ouverture de la session 
session_start();

// URL
$host = $_SERVER['HTTP_HOST'];
$uri = $_SERVER['REQUEST_URI'];
$url = sprintf("%s%s%s", "http://", $host, $uri);

$http = explode('/', $url);
$http = $http[0] . '//' . $http[2] . '/' . $http[3];

// Autoloading
require __DIR__ . '/vendor/autoload.php';

// Envoi du courriel via PHPMailer
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

$mail = new PHPMailer(true);

// Accès à la base de données
$bdd = new Database();

// Gestion des erreurs
$errors = new Errors();

// Traitement du formulaire soumis
if (isset($_POST['register'])) {
  // Tous les champs ont été remplis ?
    if (not_empty(['name', 'pseudo', 'email', 'password', 'password_confirm'])) {
        extract($_POST);
        if (mb_strlen($name) < 3) {
            $error = $errors->setError('Nom trop court (minimum 3 caractères)');
        }
        if (mb_strlen($pseudo) < 3) {
            $error = $errors->setError('Pseudonyme trop court (minimum 3 caractères)');
        }
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $error = $errors->setError('Adresse courriel invalide');
        }
        if (mb_strlen($password) < 6) {
            $error = $errors->setError('Mot de passe trop court (minimum 6 caractères)');
        } else {
            if ($password != $password_confirm) {
                $error = $errors->setError('Les deux mots de passe ne concordent pas');
            }
        }
        if ($bdd->is_already_in_use('pseudo', $pseudo, 'users')) {
            $error = $errors->setError('Pseudonyme déjà utilisé');
        }
        if ($bdd->is_already_in_use('email', $email, 'users')) {
            $error = $errors->setError('Adresse courriel déjà utilisée');
        }
        if ($errors->countError() == 0) {
            $token = sha1($pseudo . $email . $password);
            // Envoi d'un courriel d'activation
            try {
                //Server settings
                $mail->CharSet = 'UTF-8';
                //Recipients
                $mail->setFrom('contact@boom.com', 'Boom Social Network');
                $mail->addAddress($email, $name);
                //Content
                $mail->isHTML(true);
                $mail->Subject = 'Boom Social Network - ACTIVATION DE COMPTE';
                // Message HTML
                ob_start();
                require __DIR__ . '/templates/emails/activation.tmpl.php';
                $content = ob_get_clean();
                $mail->Body = $content;
                
                $saveIsOk = $bdd->prepare('INSERT INTO users(name, pseudo, email, password) 
                                      VALUE(:name, :pseudo, :email, :password)',
                                      [
                                          'name'     => $name,
                                          'pseudo'   => $pseudo,
                                          'email'    => $email,
                                          'password' => sha1($password)
                                      ]);
                if ($saveIsOk) {
                    // Informer l'utilisateur de vérifier sa boîte de réception
                    set_flash('Un courriel d\'activation de votre compte vous a été envoyé', 'success');
                    $mail->send();
                    // Redirection vers sa page de profil
                    redirect('index.php');
                }
            } catch (Exception $e) {
                echo 'Le courriel n\'a pas pu été envoyé.';
                echo 'Erreur: ' . $mail->ErrorInfo;
            }
        } else {
            save_input_data();
        }
    } else {
        $error = $errors->setError('Veuillez remplir tous les champs.');
        save_input_data();
    }
} else {
    clear_input_data();
}

// Titre
$title = 'Inscription';

// Page register.view.php
require __DIR__ . '/views/register.view.php';

Cordialement,
0