Bonjour,

Voila je rencontre un petit problème avec mon code.

Ce que je fais

Quand j'essaie de creer ou mdifier une news j'ai une erreur en ligne 36 soit: " $req = $this->pdo->query($query);"

 public function query($query, $params = false) {
        if ($params) {
            $req = $this->pdo->prepare($query);
            $req->execute($params);
        } else {
            $req = $this->pdo->query($query);
        }

Ce que je veux

Que sa fonctionne lol!!

Ce que j'obtiens

un message d'erreur
Fatal error: in C:\wamp64\www\SiteJSP1\class\Database.php on line 36

Cde de database

<?php

class Database{

    /**
     * @var
     */
    private $pdo;

    /**
     * @param $login
     * @param $password
     * @param $database_name
     * @param string $host
     */

    public function __construct($login, $password, $database_name, $host = 'localhost'){

        $this->pdo = new PDO("mysql:dbname=$database_name; host=$host", $login, $password);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

    }

     /**
     * @param $query
     * @param bool|array $params
     * @return PDOStatement
     */

     public function query($query, $params = false) {
        if ($params) {
            $req = $this->pdo->prepare($query);
            $req->execute($params);
        } else {
            $req = $this->pdo->query($query);
        }

        return $req;
    }

    /**
     * @return string
     */
    public function lastInsertId() {
        return $this->pdo->lastInsertId();
    }
}

code de gestnews pdo

<?php
class gestnewsPDO extends gest_news
{
  /**
   * Attribut contenant l'instance représentant la BDD.
   * @type PDO
   */
  protected $db;

  /**
   * Constructeur étant chargé d'enregistrer l'instance de PDO dans l'attribut $db.
   * @param $db PDO Le DAO
   * @return void
   */
  public function __construct($db)
  {
    $this->db = $db;
  }

  /**
   * @see gest_news::add()
   * @param $db
   */
  protected function add(News $news)
  {
   /* $requete = $this->db->prepare('INSERT INTO news SET auteur = :auteur, titre = :titre, contenu = :contenu, dateAjout = NOW(), dateModif = NOW()');

    $requete->bindValue(':titre', $news->titre());
    $requete->bindValue(':auteur', $news->auteur());
    $requete->bindValue(':contenu', $news->contenu());

    $requete->execute();*/
    $db->query('INSERT INTO news SET auteur =:auteur, titre =:titre, contenu = :contenu, dateAjout = NOW(), dateModif = NOW()');
  }

  /**
   * @see gest_news::count()
   */
  public function count()
  {
    return $this->db->query('SELECT COUNT(*) FROM news')->fetchColumn();
  }

  /**
   * @see gest_news::delete()
   */
  public function delete($id)
  {
    $this->db->exec('DELETE FROM news WHERE id = '.(int) $id);
  }

  /**
   * @see gest_news::getList()
   */
  public function getList($debut = -1, $limite = -1)
  {
    $sql = 'SELECT id, auteur, titre, contenu, dateAjout, dateModif FROM news ORDER BY id DESC';

    // On vérifie l'intégrité des paramètres fournis.
    if ($debut != -1 || $limite != -1)
    {
      $sql .= ' LIMIT '.(int) $limite.' OFFSET '.(int) $debut;
    }

    $requete = $this->db->query($sql);
    $requete->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'News');

    $listeNews = $requete->fetchAll();

    // On parcourt notre liste de news pour pouvoir placer des instances de DateTime en guise de dates d'ajout et de modification.
    foreach ($listeNews as $news)
    {
      $news->setDateAjout(new DateTime($news->dateAjout()));
      $news->setDateModif(new DateTime($news->dateModif()));
    }

    $requete->closeCursor();

    return $listeNews;
  }

  /**
   * @see gest_news::getUnique()
   */
  public function getUnique($id)
  {
    $requete =$this->db->query/*prepare*/('SELECT id, auteur, titre, contenu, dateAjout, dateModif FROM news WHERE id = :id');
    $requete->bindValue(':id', (int) $id, PDO::PARAM_INT);
    $requete->execute();

    $requete->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'News');

    $news = $requete->fetch();

    $news->setDateAjout(new DateTime($news->dateAjout()));
    $news->setDateModif(new DateTime($news->dateModif()));

    return $news;
  }

  /**
   * @see gest_news::update()
   */
  protected function update(News $news)
  {
    $requete = $this->db->prepare('UPDATE news SET auteur = :auteur, titre = :titre, contenu = :contenu, dateModif = NOW() WHERE id = :id');

    $requete->bindValue(':titre', $news->titre());
    $requete->bindValue(':auteur', $news->auteur());
    $requete->bindValue(':contenu', $news->contenu());
    $requete->bindValue(':id', $news->id(), PDO::PARAM_INT);

    $requete->execute();
  }
}

code de news

<?php

    class News{
        protected $erreurs =[],
                  $id,
                  $auteur,
                  $titre,
                  $contenu,
                  $dateAjout,
                  $dateModif;

/** gestion des erreurs**/

    const AUTEUR_INVALIDE = 1;
  const TITRE_INVALIDE = 2;
  const CONTENU_INVALIDE = 3;

public function __contruct($value=[]){
    if(!empty($value)){

        $this->assigne($value);
    }

}

public function assigne($donnees){
    foreach ($donnees as $attribut => $value) {
        $methode='set'.ucfirst($attribut);
        if (is_callable([$this, $methode]))
        {
            $this->$methode($value);
        }

    }
}

/** verif si la news est nouvelle**/
public function isnew(){
    return empty($this->id);
}

/** verif si la news est valide**/
public function isvalid() {
    return (!empty($this->auteur) || empty($this->titre) || empty($this->contenu));
    }

  // SETTERS //

  public function setId($id)
  {
    $this->id = (int) $id;
  }

  public function setAuteur($auteur)
  {
    if (!is_string($auteur) || empty($auteur))
    {
      $this->erreurs[] = self::AUTEUR_INVALIDE;
    }
    else
    {
      $this->auteur = $auteur;
    }
  }

  public function setTitre($titre)
  {
    if (!is_string($titre) || empty($titre))
    {
      $this->erreurs[] = self::TITRE_INVALIDE;
    }
    else
    {
      $this->titre = $titre;
    }
  }

  public function setContenu($contenu)
  {
    if (!is_string($contenu) || empty($contenu))
    {
      $this->erreurs[] = self::CONTENU_INVALIDE;
    }
    else
    {
      $this->contenu = $contenu;
    }
  }

  public function setDateAjout(DateTime $dateAjout)
  {
    $this->dateAjout = $dateAjout;
  }

  public function setDateModif(DateTime $dateModif)
  {
    $this->dateModif = $dateModif;
  }

  // GETTERS //

  public function erreurs()
  {
    return $this->erreurs;
  }

  public function id()
  {
    return $this->id;
  }

  public function auteur()
  {
    return $this->auteur;
  }

  public function titre()
  {
    return $this->titre;
  }

  public function contenu()
  {
    return $this->contenu;
  }

  public function dateAjout()
  {
    return $this->dateAjout;
  }

  public function dateModif()
  {
    return $this->dateModif;
  }
}

code de gest news

<?php
abstract class gest_news
{
  /**
   * Méthode permettant d'ajouter une news.
   * @param $news News La news à ajouter
   * @return void
   */
  abstract protected function add(News $news);

  /**
   * Méthode renvoyant le nombre de news total.
   * @return int
   */
  abstract public function count();

  /**
   * Méthode permettant de supprimer une news.
   * @param $id int L'identifiant de la news à supprimer
   * @return void
   */
  abstract public function delete($id);

  /**
   * Méthode retournant une liste de news demandée.
   * @param $debut int La première news à sélectionner
   * @param $limite int Le nombre de news à sélectionner
   * @return array La liste des news. Chaque entrée est une instance de News.
   */
  abstract public function getList($debut = -1, $limite = -1);

  /**
   * Méthode retournant une news précise.
   * @param $id int L'identifiant de la news à récupérer
   * @return News La news demandée
   */
  abstract public function getUnique($id);

  /**
   * Méthode permettant d'enregistrer une news.
   * @param $news News la news à enregistrer
   * @see self::add()
   * @see self::modify()
   * @return void
   */
  public function save(News $news)
  {
    if ($news->isValid())
    {
      $news->isNew() ? $this->add($news) : $this->update($news);
    }
    else
    {
      throw new RuntimeException('La news doit être valide pour être enregistrée');
    }
  }

  /**
   * Méthode permettant de modifier une news.
   * @param $news news la news à modifier
   * @return void
   */
  abstract protected function update(News $news);
}

Merci de votre aide!!!

96 réponses


Salut,

Là je ne vois pas.

Tu as vérifié ce qu'il y a dans les 1ère variables, il y bien ce qu'il faudrait y avoir ?

public function __construct($login, $password, $database_name, $host = 'localhost') {
        var_dump($login);
        var_dump($password);
        var_dump($database_name);

        $this->pdo = new PDO("mysql:dbname=$database_name; host=$host", $login, $password);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
    }

 public function query($query, $params = false) {
        echo '<pre>';
        print_r($query);
        echo '</pre>';

        if ($params) {
            $req = $this->pdo->prepare($query);
            $req->execute($params);
        } else {
            $req = $this->pdo->query($query);
        }

        return $req;
    }

Et une "fatal error" ça peut être plein de choses.
Tu nous a montré le message d'erreur en entier ?

Bonsoir et merci SLK pour ta reponse.

Avec les var_dump j ai bien quelque chose dans la variable et ces bon, helas oui j'ai que ce petit message d'erreur!! qui est frnanchement tres vaque!!

string(4) "root" string(0) "" string(6) "db_jsp" 
Fatal error: in C:\wamp64\www\SiteJSP1\class\Database.php on line 40

A priori l'erreur se situe en ligne 36, se qui correspond a la fonction query, excatement a => $req = $this->pdo->query($query);

public function query($query, $params = false) {
        if ($params) {
            $req = $this->pdo->prepare($query);
            $req->execute($params);
        } else {
            $req = $this->pdo->query($query);
        }

        return $req;
    }

Je me creuse la tete mais je seche lol en plus mes connaissances sont limité (je suis un novice) lol.
Merci pour votre aide.

Salut, as-tu essayer en passant ta variable $pdo en public ? J'ai à peu près le même code pour ma connexion à la bdd et perso elle est en public !

Bonjour Jeremie,

Oui Jai essayer de passer la variable $pdo en public et sa change rien.

 protected function add(News $news)
  {
    $requete = $this->db->prepare('INSERT INTO news SET auteur = :auteur, titre = :titre, contenu = :contenu, dateAjout = NOW(), dateModif = NOW()');

    $requete->bindValue(':titre', $news->titre());
    $requete->bindValue(':auteur', $news->auteur());
    $requete->bindValue(':contenu', $news->contenu());

    $requete->execute();

     Si je mets la ligne si dessous en commentaire j ai l'erreur si dessous.
   /* $db->query('INSERT INTO news SET auteur =:auteur, titre =:titre, contenu = :contenu, dateAjout = NOW(), dateModif = NOW()');*/

  }
  Fatal error: Uncaught Error: Call to undefined method Database::prepare() in C:\wamp64\www\SiteJSP1\class\gestnewsPDO.php:26 Stack trace: #0 C:\wamp64\www\SiteJSP1\class\gest_news.php(50): gestnewsPDO->add(Object(News)) #1 C:\wamp64\www\SiteJSP1\membres\gest_adm\gest_news\gestion_news.php(40): gest_news->save(Object(News)) #2 {main} thrown in C:\wamp64\www\SiteJSP1\class\gestnewsPDO.php on line 26

Si je comprends bien la methode prepare est indefinie dans ma class database. ok ok , normalement avec ma fonction query je devrai pouvoir ecrire $db->query a la place de $requete = $this->db->prepare !!?? mais quand je le fait :

Notice: Undefined variable: db in C:\wamp64\www\SiteJSP1\class\gestnewsPDO.php on line 26

Fatal error: Uncaught Error: Call to a member function query() on null in C:\wamp64\www\SiteJSP1\class\gestnewsPDO.php:26 Stack trace: #0 C:\wamp64\www\SiteJSP1\class\gest_news.php(50): gestnewsPDO->add(Object(News)) #1 C:\wamp64\www\SiteJSP1\membres\gest_adm\gest_news\gestion_news.php(40): gest_news->save(Object(News)) #2 {main} thrown in C:\wamp64\www\SiteJSP1\class\gestnewsPDO.php on line 26

La je suis vraiment perdu , je comprend plus rien !!!

`

Tu ne peux pas appliquer la méthode prepare sur $db car $db n'est pas de type PDO, il faudrait, que dans le constructeur de ta classe db, tu ne prennes pas en paramètre db, mais rien, et tu instancies de cette manière : $this->db = new PDO..... et là, tu auras ton objet de type PDO, et tu pourras appliquer les méthodes de type fetchAll, prepare, execute etc...

@Mehdikacim la variable $db est fournie par le constructeur
malheureusement on ne voit pas le code de l'instanciation
il faut remonter la pile d'appels pour voir pourquoi on passe null au constructeur

Et si tu rajoutes $this devant db? $this->db->query?

Hello merci pour vos reponses.

Je suppose que la class db correspond a ma class Database ci dessous

<?php

class Database{

    /**
     * @var
     */
    public $pdo;

    /**
     * @param $login
     * @param $password
     * @param $database_name
     * @param string $host
     */

    public function __construct($login, $password, $database_name, $host = 'localhost'){

        $this->pdo = new PDO("mysql:dbname=$database_name; host=$host", $login, $password);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

    }

     /**
     * @param $query
     * @param bool|array $params
     * @return PDOStatement
     */

     public function query($query, $params = false) {
        if ($params) {
            $req = $this->pdo->prepare($query);
            $req->execute($params);
        } else {
            $req = $this->pdo->query($query);
        }

        return $req;
    }

    /**
     * @return string
     */
    public function lastInsertId() {
        return $this->pdo->lastInsertId();
    }
}

Pour faire des essais afin de trouver l'erreur, j ai fait une class dbnews

<?php
class DBNews{
        public $db;

  public static function DB_News(){

    $db = new PDO('mysql:host=localhost;dbname=db_jsp', 'root', '');
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
    return $db;
  }

 }

Je sais plus si je vous avais mis le code du fichier gestion_news

<?php 
require_once "../../../class/bootstrap.php"; 

$auth = App::getAuth()->restrict();

$db = DBNews::DB_News();

/*$db = App::getDatabase();*/
$manager = new gestnewsPDO($db);

if (isset($_GET['modifier']))
{
  $news = $manager->getUnique((int) $_GET['modifier']);
}

if (isset($_GET['supprimer']))
{
  $manager->delete((int) $_GET['supprimer']);
  $message = 'La news a bien été supprimée !';
}

if (isset($_POST['auteur']))
{
  $news = new News(
    [
      'auteur' => $_POST['auteur'],
      'titre' => $_POST['titre'],
      'contenu' => $_POST['contenu']
    ]
  );

  if (isset($_POST['id']))
  {
    $news->setId($_POST['id']);
  }

  if ($news->isValid())
  {
    $manager->save($news);

    $message = $news->isNew() ? 'La news a bien été ajoutée !' : 'La news a bien été modifiée !';
  }
  else
  {
    $erreurs = $news->erreurs();
  }
}

require '../../../includes/haut_page.php';?>      

  <div class="conteneur">       
      <div id="menu_gauche"><h3><center>Gestion des news</center></h3>

        </br>

        <ul>
                <li><a href="../administration.php">Adminstration</a></li></br>

                <li><a href="../gest_membres/gestion_membres.php">Gestion des membres</a></li></br>

                 <li><a href="gestion_news.php">Gestion des news</a></li></br>

                <li><a href="/sitejsp1/cours/textes_referenciels/textes_referenciels.php">Textes et reférenciels</a></li>
        </ul>

               </div>

   <div class="affichenews"><h1> Gestion des news </h1>  <br/>
    <br/>

 <form action="" method="post">
      <p style="text-align: center">
<?php
if (isset($message))
{
  echo $message, '<br/>';
}
?>
        <?php if (isset($erreurs) && in_array(News::AUTEUR_INVALIDE, $erreurs)) echo 'L\'auteur est invalide.<br/>'; ?>
       <input type="text" name="auteur" value="<?php if (isset($news)) echo $news->auteur(); ?>" placeholder="Entrez votre prenom" size="45" maxlength="120" required//><br/>

       <br/> <?php if (isset($erreurs) && in_array(News::TITRE_INVALIDE, $erreurs)) echo 'Le titre est invalide.<br/>'; ?>
         <input type="text" name="titre" value="<?php if (isset($news)) echo $news->titre(); ?>" placeholder="Entrez le Titre de la news" size="45" maxlength="120" required//><br/>

         <br/><?php if (isset($erreurs) && in_array(News::CONTENU_INVALIDE, $erreurs)) echo 'Le contenu est invalide.'; ?>
       <textarea rows="20" cols="80" name="contenu" placeholder=" Ecrivez votre message!!"><?php if (isset($news)) echo $news->contenu(); ?></textarea><br/>
<?php
if(isset($news) && !$news->isNew())
{
?>
       <input type="hidden" name="id" value="<?= $news->id() ?>" />
        <input type="submit" value="Modifier" name="modifier" />
<?php
}
else
{
?>
       <br/>  <input type="submit" class="btn_primary" value="Ajouter" />
<?php
}
?>
      </p>
    </form>

    <p style="text-align: center">Il y a actuellement <?= $manager->count() ?> news. En voici la liste :</p>

    <center><table>
      <tr><th>Auteur</th><th>Titre</th><th>Date d'ajout</th><th>Dernière modification</th><th>Action</th></tr>
<?php
foreach ($manager->getList() as $news)
{
  echo '<tr><td>', $news->auteur(), '</td><td>', $news->titre(), '</td><td>', $news->dateAjout()->format('d/m/Y à H\hi'), '</td><td>', ($news->dateAjout() == $news->dateModif() ? '-' : $news->dateModif()->format('d/m/Y à H\hi')), '</td><td><a href="?modifier=', $news->id(), '">Modifier</a> | <a href="?supprimer=', $news->id(), '">Supprimer</a></td></tr>', "\n";
}
?>
    </table>
  </center>
        </div>
</div>          
        </br>

  <?php include '../../../includes/bas_page.php'; ?>

le souci maintenant c'est que je me retrouve avec une erreur tres tres vague : Fatal error: in C:\wamp64\www\SiteJSP1\class\gestnewsPDO.php on line 32 " $requete->execute();" qui correspond a la fonction add

public function add(News $news)
  {
    $requete = $this->db->prepare ('INSERT INTO news SET auteur = :auteur, titre = :titre, contenu = :contenu, dateAjout = NOW(), dateModif = NOW()');

    $requete->bindValue(':titre', $news->titre());
    $requete->bindValue(':auteur', $news->auteur());
    $requete->bindValue(':contenu', $news->contenu());

    $requete->execute();

  }

Mais pour quoi je ne peux pas utiliser $db = App::getDatabase(); comme dans mes autre fichier?

Merci pour votre patience et vtre aide!

Allo??

T'as essayé de faire comme je viens de te dire??

Il semblerait que la connexion au sgbd n'est pas établit... C'est de ce côté que ça se passe! C'est pour ça que c'est vague...

DSL Psylozoff je n'avais pas vu ton msg ci-dessous
"Psylozoff, Il y a 15 minutes - Signaler Il a répondu à ma question !
Et si tu rajoutes $this devant db? $this->db->query?"

Et oui j ai deja essayé et j ai la meme erreur "Fatal error: in C:\wamp64\www\SiteJSP1\class\gestnewsPDO.php on line 26".

sgdb?? donc visiblement le probleme viens de la connection a la base de données ?

Y'a de grandes chances... T'es sûr de tes ids de connexion?

Y'a-t-il des requêtes qui arrivent à passer?

J'ai testé l'inscription et login sa fonctionne dnc le probleme viens de la co a la bd!
Pour aller sur la page gestion news j ai besin d'etre connecté a la BD donc normalement la connection passe!

J'ai du mal à suivre,
au début c'est un bug dans ta classe Database ensuite c'est dans getNewsPDO
tu mélanges la classe PDO et ta classe Database (qui encapsule PDO)
tu devrais "typer" tous tes paramètres pour être sûr de ne pas mélanger les 2 classes.

D'une façon générale je trouve que c'est une très mauvaise idée de vouloir encapsuler PDO pour refaire la même chose en moins bien et en réutilisant les même noms de méthodes !!!! (ce forum pulule de messages de personnes qui se mélangent les pinceaux)

Avec un IDE comme netbeans ou phpstorm tu vois tout de suite ces erreurs.

Huggy a raison (comme souvent), je vois pas l'intérêt d'encapsuler PDO... Fais-en un singleton, plutôt..! Et utilise ses méthodes... C'est un objet déjà plutôt bien fait!

Pour mettre un peu de propre dans ton code, tu devrais, premièrement faire une class statique qui contient tes constantes!

class DBNewsCredentials {
    const LOGIN = "login";
    const PWD = "password";
    const HOST = "host";
    const DBNAME = "dbname";
}

class DBOtherCredentials {
    const LOGIN = "login";
    const PWD = "password";
    const HOST = "host";
    const DBNAME = "dbname";
}

Puis faire un fournisseur de PDO en singleton!

class PDOProvider {

    private static $pdoNews = null;
    private static $pdoOther = null:

    private function __construct() {}

    public static function getDBNews() {

        if (self::$pdoNews === null)  {
            self::$pdoNews = new PDO("mysql:dbname=".DBNewsCredentials::DBNAME.";host=".DBNewsCredentials::HOST, DBNewsCredentials::LOGIN, DBNewsCredentials::PWD);

            self::$pdoNews->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            self::$pdoNews->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
        }

        return self::$pdoNews;
    }

    public static function getDBOther() {

        if (self::$pdoOther === null) {
            self::$pdoOther = new PDO("mysql:dbname=".DBOtherCredentials::DBNAME.";host=".DBOtherCredentials::HOST, DBOtherCredentials::LOGIN, DBOtherCredentials::PWD);

            self::$pdoOther->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            self::$pdoOther->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
        }

        return self::$pdoOther;
    }
}

Pis, quand t'as besoin de ta db, tu fais un PDOProvider::getDBNews() et tu manipules l'objet PDO qui se suffit largement à lui-même! Et tes infos de connexion sont à l'abri dans un fichier que tu ne mets jamais sur les forums, quand t'as besoin d'aide...

Merci Psylosoff, si je comprend bien je remplace ma class Database et ma fonctin getDatabase par tes 3 class pour que je soi plus embeté avec pdo et pour que le code soi plus propre.

Vais essai sa .

Je sais pas de combien de classes t'as besoin... En lisant vite j'ai cru que tu utilisais plusieurs DB!
L'idée c'est de faire une classe pour chaque paquet de constantes en lien avec la connexion à chaque DB + un fournisseur de pdo qui gère l'instanciation de chacun des pdo nécessaires..! Après, t'adaptes!

Normalemnent j'ai qu'une class qui gere la DB et j ai qu'une DB (db_jsp) avec plusieurs tables (news, users, role et notes).

Pour essayé de comprendre j ai creer une deuxieme class pour la db(pas bien c'est provisoire!!)

Vais essayé avec ton idée apres a force de cherché, modifié j'ai peut etre empiré le problme.
Merci a vous pour votre aide.

en fait en te proposant de faire un singleton( parce que dommage qu'il ne t'ai pas expliqué à quoi sert ce design pattern )
ça sert à rien d'instancier 30 fois PDO le design pattern Singleton comme single permet de te retourner une seule et unique instance de PDO si elle existe pas.

Merci mehdi j ai fait quelque recherche et j ai comprisle principe. mais pas encore eu le temps de m'y met. pour voir se que sa donne.
Des que j'ai testé je reviens vers vous.

Boh si, j'l'ai dit ^^ "Le fournisseur de pdo gère l'instanciation des pdos"! Et puis le code est franchement simple...

Le reste de son code est quand même bien fait! Donc j'estime qu'il en sait largement assez, vu que personne n'est sensé ignorer le fonctionnement du code qu'il utilise..!! Copier-coller = relecture et recherche de compréhension ;-)

Au fait, petitludo, si tu utilises php 7, tu peux typer les arguments de tes fonctions, genre : "function truc (string $truc)"! Ca permet de virer les vérifications de type, dans les setters de ton objet News, par exemple ^^

Note qu'en utilisant un provider de singleton tu n'as plus besoin de tes variables $db puisque tu peux simplement faire PDOProvider::get()->[execute, prepare, lastInsertId...]() ;-)

As-tu considéré le fait que tu utilises query() à la place de prepare() sans avoir modifié les requêtes? Donc en y laissant des ":variable"... Je suis pas sûr que ça le fasse!

oui psylozoff tu m'avais un peut expliqué!! mais j aime comprendre aussi en cherchant ( je comprend vite mais faut m expliquer longtemps lol) apres est que j en sais suffisamement euh pas sur!! mais j essaye de comprendre pour m amlioré.
j ai pas euh trop le temps aujourd hui de regarder ton singleton car au taf je bosse sur ma cles usb et a priori j ai un souci avec le serveur. Et effectivement j utilise guery donc non je n ai pas pensé "qu'en utilisant un provider de singleton tu n'as plus besoin de tes variables $db puisque tu peux simplement faire PDOProvider::get()->execute, prepare, lastInsertId... ;-)" merci pour votre aidre tiens si sa derange pas si j arrive a finir le site correctement car encore une enorme parti a faire apres les news je mettrais un lien vers se site

Ok ^^ Faut déjà qu'on règle ton histoire de fatal error sur tes requêtes sql :-D Ensuite ça ira plus vite ;-)

Bonsoir psylozoff question pourquoi sous PDOProvider::getDatabase() plus rien passe et j ai l erreur suivante "Parse error: syntax error, unexpected 'if' (T_IF) in C" dsl la question est surement con mais a force de chercher, de lire rerererererlire je me noie dans le code lol.

En aveugle, je dirais qu'il te manque un point-virgule avant le 'if'
le mieux serait que tu nous montres le code

pfff quel idiot pas bonne idee d essayé de programmer apres le taff merci huggy une erreure si bete que je la voyais pas

maintenant j ai Warning: require(PDOProvider.php): failed to open stream: No such file or directory in C:\wamp64\www\SiteJSP1\class\Bootstrap.php on line 9

Fatal error: require(): Failed opening required 'PDOProvider.php' (include_path='.;C:\php\pear') in C:\wamp64\www\SiteJSP1\class\Bootstrap.php on line 9

bootstrap;

<?php

//__ gestion des erreurs
ini_set('display_errors','on');
error_reporting(E_ALL);

function app_autoload($class){

    require "$class.php";

  }

spl_autoload_register('app_autoload'); 

et app.php

class App{

    /**
     * @var null
     */
    /*static $db = null;

    /**
     * @return Database|null
     */

    static function getDatabase(){

        if(!self::$db){
            self::$db = new Database('root', '', 'db_jsp' );

        }

        return self::$db; 
    }

     /**
     * @return Auth
     */
    static function getAuth(){
        return new Auth(
            Session::getInstance(),
            ['restriction_msg' => 'Accès interdit !']);
    }

    /**
     * @param $page
     */
    static function redirect($page) {
        header('Location: '.$page);
        exit();
    }
}

je crois que j ai besoin d une pause les ligne de code se melange ds mon tit cerveau!!

Tu l'appelles d'où ton bootstrap?? T'as un auto_prepend_file dans ta config apache?

C'est de la grosse merde l'autoload ^^' Jadis, quand je m'emmerdais encore à faire du PHP, j'avais essayé de jouer avec cette API mais impossible d'en faire un truc simple et intuitif :-s

M'enfin bref, va jeter un oeil dans la doc, y'a une section dédiée, tu verras le bordel... J'imagine que le problème est que tu requiers la classe PDOProvider à partir d'un fichier qui se trouve dans un dossier! Vu qu'il me semble que la fonction "require" recherche à partir du dossier dans lequel se trouve le fichier appelant si tu prévois pas le coup -_-' Histoire de bien casser les couilles ;-)

Si tes fichiers sont bien rangés, je te conseille d'écrire les require en dur dans chaque fichier où c'est nécessaire et, une fois que ça marche, d'adapter une fonction d'autoload jusqu'à ce que ça remarche ^^'

psylozoff euh sa fonctionnais avant que j essaie ton singleton (j avoue que j ai du mal avec mais des que j aurai bien pigé le truc sa va aller lol, j ai regardé la doc et j ai eu peur lol bah tout mes fichiers class et bootstrap sont dans le meme dossier!!

dans ton autoloader tu dois faire référence à un répertoire
par exemple

require __DIR__ . "/class/" . $class . ".php";

la constante DIR c'est le dossier de ton autoloader
à corriger en fonction de l'endroit où tu mets tes classes

merci huggy bon j ai corrigé mon auloader et sa l air de fonctionner lol

bootstrap.php

function app_autoload($classname){

     if (file_exists($file = __DIR__ . '/' . $classname . '.php'))
    {
    require $file;
     }

  }

spl_autoload_register('app_autoload'); 

mais la j ai une erreure avec $this? Fatal error: Uncaught Error: Using $this when not in object context in C:\wamp64\www\SiteJSP1\class\PDOProvider.php:33 Stack trace: #0 C:\wamp64\www\SiteJSP1\membres\login.php(4): PDOProvider::getDatabase() #1 {main} thrown in C:\wamp64\www\SiteJSP1\class\PDOProvider.php on line 33

PDOProvider.php

class PDOProvider{

    private static $pdo = null;

    private function __construct() {}

    public static function getDatabase() {

        if ($this->pdo === null)  {
            $this->pdo = new PDO("mysql:dbname=".DBDatabase::DBNAME.";host=".DBDatabase::HOST, DBDatabase::LOGIN, DBDatabase::PWD);

            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
        }

        return $this->pdo;
    }

     /**
     * @param $query
     * @param bool|array $params
     * @return PDOStatement
     */

     public function query($query, $params = false) {
        if ($params) {
            $req = $this->pdo->prepare($query);
            $req->execute($params);
        } else {
            $req = $this->pdo->query($query);
        }

        return $req;
    }

    /**
     * @return string
     */
    public function lastInsertId() {
        return $this->pdo->lastInsertId();
    }
}

Ah oui, exact X-D mea culpette :-p Je corrige!

C'est bon ^^

$this fait référence à l'instance d'un objet! Or, le PDOProvider n'est pas instanciable... Son seul rôle est de gérer ses instances internes de PDO! Du coup, pour référence la classe à l'intérieur d'elle-même on utilise "self" ;-) Ainsi on peut référencer ses membres "static"!

Par contre, vire les méthodes lastInsertId et query du provider... Ces méthodes existent déjà sur PDO et sont largement suffisantes! Sans compter que tu en as fait des méthodes d'instances :-s Donc ça marchera pas, de toute façon X-)

euh tu corrige quoi?

Ma classe PDOProvider ^^ Mon bout de code! Au cas où si quelqu'un d'autre venait à vouloir s'en servir faut que ce soit clean :-s

ah oui c'est mieux, c est pour sa que j ai l'erreure!? C:\wamp64\www\SiteJSP1\class\PDOProvider.php:33 Stack trace: #0 C:\wamp64\www\SiteJSP1\membres\login.php(4): PDOProvider::getDatabase() #1 {main} thrown in C:\wamp64\www\SiteJSP1\class\PDOProvider.php on line 33

Fait voir ton fichier login.php... Et ton Provider corrigé ^^

Voici un singleton au sens propre, qui n'est instancié qu'une seule fois
et non pas une classe statique (qui fonctionne aussi)
Notez la variable $instance qui est statique mais pas la variable $pdo

class PDOProvider{
    private static $instance = null;
    private $pdo = null;

    // constructeur privé, bloque le 'new' en dehors de la classe
    private function __construct() {
        $this->pdo = new PDO("mysql:dbname=".DBDatabase::DBNAME.";host=".DBDatabase::HOST . ";charset=utf8", DBDatabase::LOGIN, DBDatabase::PWD);

        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);         
    }

    public static function getDatabase() {

        if (self::$instance === null)  {
            self::$instance = new PDOProvider();
        }

        return self::$instance->pdo;
    }
// A PARTIR D'ICI RIEN NE CHANGE PAR RAPPORT A LA CLASS DE @psylozoff
     /**
     * @param $query
     * @param bool|array $params
     * @return PDOStatement
     */

     public function query($query, $params = false) {
        if ($params) {
            $req = $this->pdo->prepare($query);
            $req->execute($params);
        } else {
            $req = $this->pdo->query($query);
        }

        return $req;
    }

    /**
     * @return string
     */
    public function lastInsertId() {
        return $this->pdo->lastInsertId();
    }
}

Le but de la classe Provider n'est pas d'avoir une unique instance de Provider! Si, éventuellement, on offre la possibilité d'instancier le Provider, peu importe le nombre d'instance vu que le rôle de cette classe n'est que de s'assurer qu'il n'existe qu'une unique instance de PDO :-s Après, effectivement, ça porte à confusion d'appeler ça un singleton, on est d'accord! C'est juste une classe statique...

Quand je parlais de singleton je pensais au DP factory, en fait... D'ailleurs j'ai pompé le concept de Provider dans Dagger Android :-p

bonjour,
Merci Psylozoffje et huggy Je comprend mieux apres je debute en POO .
Huggy avec ton singleton sa l'air de fonctionné (j ai essayé a l'arrache) a mon retour je l etudi me resteplus qu'a faire les modif de la variable $db en la remplacant par "PDOProvider::get()->execute ou prepare ou lastInsertId..." si j ai bien compris !!

Login.php

<?php 

require_once"../class/Bootstrap.php"; 
PDOProvider::getDatabase();

$auth = App::getAuth();

$session = Session::getInstance(); 
$auth->connectFromCookie($db);

if($auth->user()){
      App::redirect('account.php');
     }

if(!empty($_POST['mail']) && !empty($_POST['password'])){
    $user = $auth->login($db, $_POST['mail'],$_POST['password'], isset($_POST['remember']));

        if ($user) {
        $session->setFlash('success', 'Connexion effectuée');
        App::redirect('account.php');
        exit();
    } else {
        $session->setFlash('danger', 'Identifiant ou mot de passe incorrect');
    }
}
?>

    <?php require '../includes/haut_page.php'; ?>

<center><h2> Merci de vous connecter</h2>

<form action="" method="POST">    
    <div class="form-group">

        <input type="Email" name="mail" class="form-control" placeholder="Votre E-mail" required/></div>
    </br>
    <div class="form-group">

        <input type="password" name="password" class="form-control" placeholder="Mot de passe" required/>
    </div>
    <a href="forget.php">(Un oubli !?)</a></label><br/>

    <div class="form-group"><br />
        <label>
        <input type="checkbox" name="remember" value="1"/>Se souvenir de moi</label></br>
    </div> 
</br><button type="submit" class="btn_primary">Se connecter</button>
</br>
</form></center></br>

        <?php include '../includes/bas_page.php'; ?>

Avec Provider::get() t'obtiens un objet PDO configuré pour ta DB! Ensuite tu l'utilises simplement comme un PDO banal! Sauf que tu n'as pas besoin de stocker son instance puisqu'elle est stockée en interne par le Provider! Ton code sera plus simple à débugguer, ensuite ;-)

Bonsoir,

Soi j'ai loupé ou pas compris quelque chose car maintenant se connecter ou inscription ne fonctionne pas !!
j'ai l'erreur ci-dessous
Fatal error: Uncaught Error: Call to undefined method PDOProvider::get() in C:\wamp64\www\SiteJSP1\class\Auth.php:163 Stack trace: #0 C:\wamp64\www\SiteJSP1\membres\login.php(17): Auth->login('admin@jspnsf.fr', '123456', true) #1 {main} thrown in C:\wamp64\www\SiteJSP1\class\Auth.php on line 163

Auth.php

<?php

/**
 * Class Auth
 */
class Auth {
    private $options = [
        'restriction_msg' => "Vous devez vous connecter pour accéder à cette page !",
    ];
    private $session;

    /**
     * @param $session
     * @param array $options
     */
    public function __construct($session, $options = ['']) {
        $this->options = array_merge($this->options, $options);
        $this->session = $session;
    }

    public function hashPassword($password) {
        return password_hash($password, PASSWORD_BCRYPT);
    }

    /**
     * @param $db
     * @param $username
     * @param $password
     * @param $email
     */
    public function register($Nom, $Prenom, $Age, $mail, $Password){
        $Password = $this->hashpassword($Password);
        $token = str::random(60);

        PDOProvider::get()->prepare('INSERT INTO Users SET Nom = ?, Prenom = ?, Age = ?, roles_id = 8, mail = ?, Password = ?, confirmation_token = ?', [
            $Nom, 
            $Prenom, 
            $Age, 
            $mail, 
            $Password, 
            $token  
        ]);

        $users_id = PDOProvider::get()->prepare->lastInsertId();
        $mail = strip_tags($mail);

        $header = "From : ".$mail;
        $sujet = "Confirmation de votre mail";
        $message = "Afin de valider votre compte, merci de cliquer sur le lien ci dessous:\n\n
        http//".$_SERVER['SERVER_NAME']."/sitejsp1/membres/confirm.php?id=".$users_id."&token=".$token;

        mail($mail, $sujet, $message, $header);
    }

    /**
     * @param $db
     * @param $user_id
     * @param $token
     * @return bool
     */

 public function confirm($user_id, $token) {
        $user = PDOProvider::get()->prepare('SELECT * FROM users WHERE id = ?', [$user_id])->fetch();

        if ($user->confirmation_token == $token) {
            $req = PDOProvider::get()->prepare('UPDATE users SET confirmation_token = NULL, confirmed_at = NOW() WHERE id = ?', [$user_id]);

            $this->session->write('auth', $user);

            return true;

        $mail = strip_tags($mail);

        $header = "From : ".$mail;
        $sujet = "Validation de votre compte";
        $message = "Votre compte a bien été validé, cependant pour pleinement profiter des cours, faut attendre qu'un membres de l'encadrement valide votre compte.\n\n
        http//".$_SERVER['SERVER_NAME']."/sitejsp1/contact.php?";

        mail($mail, $sujet, $message, $header);
        }

        return false;

        $mail = strip_tags($mail);

        $header = "From : ".$mail;
        $sujet = "Validation de votre compte";
        $message = "Votre compte n'a pas été validé, merci de prendre contacte avec un membres de l'encadrement.";

        mail($mail, $sujet, $message, $header);
    }

    /**
     * function restrict
     */
    public function restrict(){
        if (!$this->session->read('auth==admin')){
            $this->session->setFlash('danger', $this->options['restriction_msg']);

            header('Location: login.php');
            exit();
        }
    }

        /**
     * @return bool
     */
    public function user(){
        if (!$this->session->read('auth')){
            return false;
        }
        $this->session->read('auth');
    } 
    /**
     * @param $user
     */
    public function autoconnect($user) {
        $this->session->write('auth', $user);
    }

    /**
     * @param $db
     */
    public function connectFromCookie(){
        if (isset($_COOKIE['remember']) && !$this->user()){
            $remember_token = $_COOKIE['remember'];
            $parts = explode('==', $remember_token);
            $user_id = $parts[0];

            $user = PDOProvider::get()->prepare('SELECT * FROM users WHERE id = ?',[$user_id])->fetch();

            if($user) {
                $expected = $user_id."==".$user->remember_token.sha1($user_id.'blackshadow');
                if ($expected == $remember_token){
                    $this->autoconnect($user);
                    setcookie('remember', $remember_token, time()+60*60*24*7);
                } else {
                    setcookie('remember', NULL, -1);
                }
            } else {
                setcookie('remember', NULL, -1);
            }
        }
    }
     /**
     * @param $db
     * @param $user_id
     */
    public function remember($user_id) {
        $remember_token = Str::random(250);
        PDOProvider::get()->prepare('UPDATE users SET remember_token = ? WHERE id = ?', [$remember_token, $user_id]);
        setcookie('remember', $user_id.'=='.$remember_token.sha1($user_id.'blakshadow'), time()+60*60*24*7);
    }

    /**
     * @param $db
     * @param $Nom
     * @param $password
     * @param bool $remember
     */
   public function login($mail, $password, $remember) {
        $user = PDOProvider::get()->prepare('SELECT users.prenom,users.age,users.password,roles.pseudo,roles.rang,roles.level FROM users left JOIN roles ON users.roles_id=roles.id WHERE (mail = :mail) AND confirmed_at IS NOT NULL ', ['mail' => $mail])->fetch();

        if (password_verify($password, $user->password)){
            $this->autoconnect($user);

            if ($remember){
                $this->remember($db, $user->id);
            }
            return $user;
        } else {
            return false;
        }
    }

  public function logout() {
        setcookie('remember', NULL, -1);
        $this->session->delete('auth');
    }

    public function resetPassword($mail) {
        $user = PDOProvider::get()->prepare('SELECT * FROM users WHERE mail = ? AND confirmed_at IS NOT NULL', [$mail])->fetch();
        if ($user){
            $reset_token = Str::random(60);

            PDOProvider::get()->prepare('UPDATE users SET reset_token = ?, reset_at = NOW() WHERE id = ?', [$reset_token, $user->id]);

            $mail=strip_tags($mail);

            $header = "From : ".$mail;
            $sujet = "Reset du password";
            $message = "Pour réinitialiser votre mot de passe, merci de cliquer sur le lien ci-dessous: lien\n\n
           http://".$_SERVER['SERVER_NAME']."/sitejsp1/membres/reset.php?id={$user->id}&token=".$reset_token;

            mail($mail, $sujet, $message, $header);

            return $user;
        }
        return false;
    }

    public function confirmToken( $user_id, $token) {
        return PDOProvider::get()->prepare("SELECT * FROM users WHERE id = ? AND reset_token = ? AND reset_at > DATE_SUB(NOW(), INTERVAL 30 MINUTE)",[$user_id, $token])->fetch();
    }
}

login.php

<?php 

require_once"../class/Bootstrap.php"; 
PDOProvider::getDatabase();

$auth = App::getAuth();

$session = Session::getInstance(); 
$auth->connectFromCookie('PDOProvider');

if($auth->user()){
      App::redirect('account.php');
     }

if(!empty($_POST['mail']) && !empty($_POST['password'])){
    $user = $auth->login($_POST['mail'],$_POST['password'], isset($_POST['remember']));

        if ($user) {
        $session->setFlash('success', 'Connexion effectuée');
        App::redirect('account.php');
        exit();
    } else {
        $session->setFlash('danger', 'Identifiant ou mot de passe incorrect');
    }
}
?>

    <?php require '../includes/haut_page.php'; ?>

<center><h2> Merci de vous connecter</h2>

<form action="" method="POST">    
    <div class="form-group">

        <input type="Email" name="mail" class="form-control" placeholder="Votre E-mail" required/></div>
    </br>
    <div class="form-group">

        <input type="password" name="password" class="form-control" placeholder="Mot de passe" required/>
    </div>
    <a href="forget.php">(Un oubli !?)</a></label><br/>

    <div class="form-group"><br />
        <label>
        <input type="checkbox" name="remember" value="1"/>Se souvenir de moi</label></br>
    </div> 
</br><button type="submit" class="btn_primary">Se connecter</button>
</br>
</form></center></br>

        <?php include '../includes/bas_page.php'; ?>

merci pour votre aide!

Elle est où ta class Provider?

Pk tu utilises "prepare" au lieu de "query"..?

Ah et si tu veux pouvoir écrire Provider::get() faudrait p't'être que get() soit définie dans Provider...

Prepare c'etait pour tester mais avec query j ai la meme erreur
PDOProvider.php

<?php
class PDOProvider{

    private static $instance = null;
    private $pdo = null;

    // constructeur privé, bloque le 'new' en dehors de la classe
    private function __construct() {
        $this->pdo = new PDO("mysql:dbname=".DBDatabase::DBNAME.";host=".DBDatabase::HOST . ";charset=utf8", DBDatabase::LOGIN, DBDatabase::PWD);

        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);         
    }

    public static function getDatabase() {

        if (self::$instance === null)  {
            self::$instance = new PDOProvider();
        }

        return self::$instance->pdo;
    }

     /**
     * @param $query
     * @param bool|array $params
     * @return PDOStatement
     */

     public function query($query, $params = false) {
        if ($params) {
            $req = $this->pdo->prepare($query);
            $req->execute($params);
        } else {
            $req = $this->pdo->query($query);
        }

        return $req;
    }

    /**
     * @return string
     */
    public function lastInsertId() {
        return $this->pdo->lastInsertId();
    }
}

Et donc? Tu la vois où la méthode get??

Je vois pas pk tu nous poses la question ^^' Ton message d'erreur est parfaitement clair...

Call to undefined method PDOProvider::get()

bonsoir psylozoff, effectivement la fonction get n'est pas presente dans les fonction me suis melangé les meninges entre get et guery j'ai lu plus haut qu'il fallai utilisé PDOProvider::get() mais je pense qu il faut utilisiser PDOProvider::query() helas avec query j ai l'erreur suivante :
Fatal error: Uncaught Error: Using $this when not in object context in C:\wamp64\www\SiteJSP1\class\PDOProvider.php:57 Stack trace: #0 C:\wamp64\www\SiteJSP1\class\Auth.php(163): PDOProvider::query('SELECT users.pr...', Array) #1 C:\wamp64\www\SiteJSP1\membres\login.php(17): Auth->login('**', '*****', true) #2 {main} thrown in C:\wamp64\www\SiteJSP1\class\PDOProvider.php on line 57 ==> $req = $this->pdo->prepare($query);
sa correspond a la fnction query.

public static function query($query, $params = false) {
        if ($params) {
            $req = $this->pdo->prepare($query);
            $req->execute($params);
        } else {
            $req = $this->pdo->query($query);
        }

        return $req;
    }

Bon, attends petitludo, deux secondes! En réalité tu es très très débutant? J'avais pensé que non...

Comprends-tu la différence entre static et $this?

Saurais-tu identifier, dans ton Provider, la méthode qui te permet de récupérer un objet PDO?

Cette méthode "query" qui se trouve dans ton Provider, tu peux la supprimer! C'est de la merde ^^'

La base serait de relire ton code et de bien comprendre ce qui s'y passe en le commentant, au cas où tu oublies... Si tu copie-colle bêtement du code, tu ne fais que retarder le moment où tu devras t'y coller tout en complexifiant le processus en amoncelant un gros pâté informe :-s

Oui je suis debutant je vous les dit ! si j ai bien compris static on peut en faire l'appel sans l intancier et apres de la lecture a priori this n'ai pas compatible avec static maintenants la difference entre static et this ??
je te rasure je colle pas betement j'essaie de comprendre sinon aucun interet.
Si je me trompe pas c est la fonction getdatabase qui permet de recuperer l objet pdo!!?? car la fonction construc me permet de faire la connexion a la BD

Excuse-moi, je voulais dire : "la différence entre self et $this" ^^'

Comprends-tu ce qu'est une instance? Et la différence d'avec une classe? Et qu'est-ce que $this? Donc qu'est-ce que self? Et ainsi, pourquoi $this ne pouvait pas s'appliquer?

Je ne pense pas qu'utiliser le code d'Huggy soit une bonne idée... Il voulait simplement te montrer à quoi ressemble réellement un singleton car il est vrai que j'ai utilisé le terme de façon parfaitement abusive! Un singleton est une classe qui ne peut être instanciée qu'une fois, or mon Provider est une classe statique, jamais instanciée..!

Dans ton code actuel, c'est bien la méthode getDatabase qui permettrait de récupérer le PDO ^^ Donc ce serait elle qu'il faudrait utiliser...

Cependant, pour ton Provider, ce code suffit!

<?php
class PDOProvider {

    private static $pdo = null;

    // constructeur privé, interdit l'instanciation
    private function __construct() {}

    public static function get() {

        if (self::$pdo === null) {

            self::$pdo = new PDO("mysql:dbname=".DBDatabase::DBNAME.";host=".DBDatabase::HOST . ";charset=utf8", DBDatabase::LOGIN, DBDatabase::PWD);
            self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            self::$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);     
        }

        return self::$pdo;
    }

Si tu avais besoin de méthodes d'instance dans ta classe Provider, on serait obligé d'en faire un singleton mais de ce que je vois une simple classe statique suffit!

Ta méthode "lastInsertId" est inutile puisqu'elle ne contient qu'une ligne... Et ta méthode "query" est merdique car elle encapsule "prepare" qui peut s'utiliser de diverses façon et ainsi nécessiter plus d'opérations que celles que tu utilises dans ta méthode :-s

Je confirme ce que dit @Psylozoff, une classe statique fait le taff et c'est plus simple.
ça résoud aussi le cas où la fonction utilisatrice force $pdo à null pour vider/nettoyer la connection (voir la doc pdo)

bonjour,
"Excuse-moi, je voulais dire : "la différence entre self et $this" ^^'"
$this c'est pour l'instance en cours qui ne peux pas etre une instance static, alors que self peut etre static

"Comprends-tu ce qu'est une instance? Et la différence d'avec une classe?
Instance=> c'est comment un objet va fonctionner en fonction de la classe
Classe=> permet de creer un pbjet

Bien essayé :-) Tu devrais te renseigner sur ces notions ;-) Je vais essayer d'être clair mais bon, d'autres tuto le seront sûrement plus!

  • Une classe est une recette, un modèle de génération, un descriptif!

  • Une instance est un objet manipulable qui correspond à ce modèle, qui a été généré en suivant cette recette...

  • Dans une classe on précise des modules variables mais aussi, potentiellement, des modules non-variables qu'on appelle statiques ou constants...

  • Chaque instance dispose de ces modules variables en leur appliquant des valeurs diverses alors, qu'évidemment, les modules statiques sont partagés!

Du coup, comment accède-t-on à ces 2 parties, en PHP?

  • on utilise l'opérateur de "référence" pour accéder aux modules variables d'une instance "->"

  • on utilise l'opérateur de "classe" pour accéder aux modules constants "::"

  • Les fonctions et variables NON "static" sont des modules variables! On ne peut donc pas y faire référence dans un contexte statique puisqu'on ne sait pas quelle seront les valeurs allouées à ces modules variables ni même s'il y aura des valeurs allouées ou non..!

  • Hors de la définition d'une classe, on créé une instance avec l'opérateur "new" ("$instance = new Classe()") puis on se sert de la référence stockée dans une variable pour accéder à ses modules variables "$instance->module_variable()" ainsi qu'à ses modules statiques "$instance::module_statique()"...

  • On pourrait, de façon parfaitement équivalente, appeler ses modules statiques en s'épargnant l'utilisation de la référence d'instance ainsi : "Classe::module_statique"..!

  • A l'intérieur de la définition d'une classe, $this correspond à l'instance en cours d'utilisation, utilisable dans un contexte variable, et self correspond à la classe elle-même, pour faire référence aux modules statiques, donc!

bonsoir psylozoff,

sa parai si simple à vous lire!!! je n'ai pas fait d html ou de php depuis 20ans et la me sens clairement et completement larguer!! j'ai decouvert la poo en suivant un tuto video et en lisant des tutos sur le net mais finalement je suis completement perdu!!!

C'est important de faire la différence entre une classe et les instances de cette classe ^^ C'est un peu la base de la POO! Qu'est-ce que tu ne comprends pas de mon précédent message? On peut décortiquer chaque chose qui coince, si tu veux! En parallèle, tu peux continuer à nous faire part de l'état de ton application ;-)

la class => c la recettei!!
les fonctions => sont des methodes pour realiser la recette
l instance c'est l utilisation de la recette et pour y avoir acces faut la creer avec $xx = new blabla() une fois stocker on peut l appeller
soit si non static "$xx->blabla" ou si statiques "$xx::blabla()".
Pour l avancement c'est pas gagné actuellement j ai une erreur :Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: mode must be an integer in C:\wamp64\www\SiteJSP1\class\Auth.php:173 Stack trace: #0 C:\wamp64\www\SiteJSP1\class\Auth.php(173): PDO->query('SELECT users.pr...', Array) #1 C:\wamp64\www\SiteJSP1\membres\login.php(16): Auth->login(Object(PDO), 'admin@xxx.fr', '123456', true) #2 {main} thrown in C:\wamp64\www\SiteJSP1\class\Auth.php on line 173

visiblement je recupere bien les données!! l'erreur corrzspond a : if (password_verify($password, $user->password)){
$this->autoconnect($user);

public function login($db, $mail, $password, $remember) {
        $user = $db->query('SELECT users.prenom,users.age,users.password,roles.pseudo,roles.rang,roles.level FROM users left JOIN roles ON users.roles_id=roles.id WHERE (mail = :mail) AND confirmed_at IS NOT NULL ', ['mail' => $mail])->fetch();

        if (password_verify($password, $user->password)){
            $this->autoconnect($user);

            if ($remember){
                $this->remember($db, $user->id);
            }
            return $user;
        } else {
            return false;
        }
    }

merci de votre patience!!

Ca veut dire que tu passes autre chose qu'un "int" à une fonction qui attend un int!

Tu sais que tu peux virer tes variables $db, partout... Si t'as besoin de ton PDO tu peux utiliser Provider::get, directement, de n'importe où!

Quand je parle de classe, je parle de la définition de la classe ^^ Cette définition de classe est le modèle qui sert à instancier les objets qui seront du type de cette classe!

Les fonctions ne sont pas des méthodes pour réaliser la recette mais font partie du résultat de cette recette! On appelle "méthode" les fonctions qui font partie d'une classe! Une méthode c'est juste une fonction que l'on appelle via une classe... Les méthodes non-statiques, qu'on appelle méthodes d'instance, sont uniquement disponibles sur les instances de la classe et servent à manipuler les variables d'instance ^^

Il n'existe qu'une seule et unique classe de chaque type mais il peut exister autant d'instances de cette classe que nécessaire! Le but de l'existence des instances est de pouvoir disposer de plusieurs coquilles correspondant au modèle utilisé mais dont l'état interne est différent d'une instance à l'autre!

Et donc, les méthodes et variables de classe, les trucs statiques, sont uniques et partagées par toutes les instances de la classe!

Dans le cas de mon Provider, c'est une classe qui ne peut pas être instancié! Donc on appelle ça une classe statique... Son seul rôle est de garantir l'unicité de son contenu ^^

tu crois que tu utilises la méthode query, celle de ta classe mais en fait tu utilises celle de PDO qui attend un FETCH_MODE en second argument
je t'avais prévenu ...

en plus tu n'as pas sélectionné l'id dans ta requête et tu l'utilises en dessous

Et un singleton n'est pas équivalent à cette notion de classe statique car un singleton est une classe qui garantit qu'elle ne sera instanciée qu'une seule et unique fois! Mais ce sera bien une instance de la classe! Contrairement à notre classe statique qui n'est jamais instanciée!

Wow! Bien vu Huggy!!

J'ajouterais que pour améliorer la visibilité dans tes requêtes tu pourrais écrire un truc comme ça : 'SELECT u.prenom, u.age, u.password, r.pseudo, r.rang, r.level FROM users as u LEFT JOIN roles as r ON u.roles_id = r.id WHERE mail = :mail AND confirmed_at IS NOT NULL'

bonjour, waouh beaucoup d'info merci a vous! quand je pense que se site devais etre tous simple en html et il fini en usine php lol.
Je rame mais je n'aime pas ne pas comprendre ni ne pas reussir !!!
oui j'ai remis une sauvegarde de mon fichier auth et j ai oublié de viré les $db, vais le faire ce soir.

Psyllozoff si j ai bien compris j'ecris la 1er lettres "d'users et de roles" et avec le "as" je dit a quel table sa correspond? j'ai fait un noeud entre les tables euh c'est pas noeud mais jointure!? car des que j aurai reglé les problemes avec la fonction login/inscription/news faut que je creer une fonction qui fera la diference d'accés d'apres de la fonction du connecter.

pour le singleton je pense avoir compris son principe mais vu mon niveau c'est encore trop flou pour vouloir l utilisé, prefere resté et bien comprendre deja les class, fonction, les histoires de static, protected, etc..

allez vais essayer d avancer pour deja faire fonctionner l'inscription/login/news.

merci a vous, euh parter pas trop loin lol

mettre un attribut d'une classe en protected dis que si une classe A hérité d'une classe B les attributs protected de la classe A Son accessible sans getter ($this->A)
static permet par exemple pour une classe de base de données au lieu de faire un new Db de faire Db::getDb() sans instancier l'objet.

J'imagine que tu as connaissance de ce site et que tu as, au moins, commencé à lire cette page? http://php.net/manual/fr/langref.php

Bonsir,
Merci mehdi, plus clair ton explication !! Psylozoff oui j'ai commencer a lire les pages de ce site et d'un autre qui me parait plus clair.

moi tu vas rigoler j'ai commencé à côtoyer php à mes 12 ans j'en ai 23 aujourd'hui et je suis en école d'ingénieur en développement moi si tu veux une technique pour être bon tu as deux possibilités à l'heure actuelle tu n'es pas capable d'utiliser un framework PHP si tu ne maîtrise pas déjà tout ce qui est programmation orientée objet et tout ce qui appelle statique et en même temps si tu connais pas le modèle MVC qu'un design pattern voir les façades pour laravel je te proposerai de te donner un petit projet en tête que tu peux jeter à la poubelle plus tard ou que tu peux après demander de l'aide pour faire du refactoring tu pars sur une base ou tu fais du php brut après tu te dis bon le site est fonctionnel maintenant j'aimerais bien que le code ressemble à quelque chose alors là petit à petit tu vas petit à petit rentrer dans le monde de la programmation orientée objet à la suite de ça tu auras beaucoup de notion à rajouter de type autoloader namespace exetera exetera maintenant une fois qu'après tu vois comment fonctionne tout ce qui est modèle MVC et le reste là tu peux te dire bon bah maintenant j'ai les notions qui manque plus qu'à sauter sur un bot framework de type symphonie ou laravel tu me pardonneras s'il y a des fautes je parle avec ma commande vocale parce que je te réponds alors que je conduis en même temps par la suite si tu as besoin de réponse plutôt rapide je suis bien évidemment sur discord si tu le souhaites et je serais bien ouvert à se former sur des notions que tu ne comprends pas bien amicalement

Alors, Mehdikacim, j'ai eu énormément de mal à te lire mais je suis globalement d'accord avec toi ^^ De ton côté, tu pourrais aller regarder un tuto concernant l'art de l'expression écrite et surtout de la ponctuation :-) Je dis ça sérieusement... J'espère que tu n'écris pas comme ça quand tu rédiges un cahier des charges :-s
@petitludo, comme le dit Mehdi, bien comprendre la POO est essentiel! Puis ensuite tu peux la mettre en pratique en étudiant des modèles de conception comme MVC, MVP, Observer, Factory, Strategy... Les modèles de conception ça permet réellement d'ajouter des lames à ton couteau suisse mental de développeur ^^ Mais bon, bien comprendre et maitriser la POO, en priorité absolue!!

Non, je ne parle pas comme ça habituellement, comme je le disai, j'étais en voiture, donc j'utilisai la commande vocale de google :)

Sinon je ne pense pas que j'aurai eu un bac, bts, licence etc ...

Ah ok X-D J'avais pas lu la fin... Y'a pas moyen de faire de la ponctu sur google voice? C'est nul :-s

Tu sais, j'ai vu des types en BTS avec un niveau qui fait peur... Evidemment, ils ont eu leur BTS ^^'

C'est de la pitier internationale xD

Après on se demande pk y'a des diplomés qui finissent caissiers ^^' M'enfin bon, trêve de hors-sujet :-p

bonsoir,
j'adore le hors sujet lol.

mehdi dit moi c est quoi ton projet ?
Les news lol j ai avancé un tit peux lol j ai plus d'erreur quand je vais sur login, forget et sign_up c'est un debut.
J'ai repris la lecture php et php poo (mais j'ai peux de temps), histoire de bien tous comprends car apres plus de 15 ans j avoue que je rame pas mal lol.
Neanmoins, je ne comprends ps pourquoi je n'arrive pas a me connecter ou a demander un nouveau PWD, j'ai toujours le message compte inexcitant ou mauvais mot de passe, j'ai pas tester l'inscription mais je pense que je vais avoir aussi un msg d'erreur!!.

forget.php

<?php
 require_once "../class/bootstrap.php"; 
if (!empty($_POST) && !empty($_POST['mail'])){

    $auth = App::getAuth();
    $session = Session::getInstance();
    if ($auth->resetPassword(PDOProvider::get(), $_POST['mail'])) {
        $session->setFlash('success', 'Le rappel du mot de passe à été envoyé par mail');

        App::redirect('login.php');
    }else{
        $session->setFlash('danger', 'Aucun compte ne correspond à cette adresse');
    }
}
?>

    <?php require '../includes/haut_page.php'; ?>

<h1><center> Réinitialisation du mot de passe</h1>

    <form action="" method="POST">   
    <div class="form-group">
        <label for="">Email</label>
        <input type="email" name="mail" class="form-control" required/></div>

    <br>

<button type="submit" class="btn btn_primary">Réinitialisation du mot de passe</button>

</form> <br/></center>

<?php include '../includes/bas_page.php'; ?>

login.php

<?php 

require_once"../class/Bootstrap.php"; 

$auth = App::getAuth();

$session = Session::getInstance(); 
$auth->connectFromCookie();

if($auth->user()){
      App::redirect('account.php');
     }

if(!empty($_POST['mail']) && !empty($_POST['password'])){
    $user = $auth->login($_POST['mail'],$_POST['password'], isset($_POST['remember']));

        if ($user) {
        $session->setFlash('success', 'Connexion effectuée');
        App::redirect('account.php');
        exit();
    } else {
        $session->setFlash('danger', 'Identifiant ou mot de passe incorrect');
    }
}
?>

    <?php require '../includes/haut_page.php'; ?>

<center><h2> Merci de vous connecter</h2>

<form action="" method="POST">    
    <div class="form-group">

        <input type="Email" name="mail" class="form-control" placeholder="Votre E-mail" required/></div>
    </br>
    <div class="form-group">

        <input type="password" name="password" class="form-control" placeholder="Mot de passe" required/>
    </div>
    <a href="forget.php">(Un oubli !?)</a></label><br/>

    <div class="form-group"><br />
        <label>
        <input type="checkbox" name="remember" value="1"/>Se souvenir de moi</label></br>
    </div> 
</br><button type="submit" class="btn_primary">Se connecter</button>
</br>
</form></center></br>

        <?php include '../includes/bas_page.php'; ?>

et auth.php

<?php

/**
 * Class Auth
 */
class Auth {
    private $options = [
        'restriction_msg' => "Vous devez vous connecter pour accéder à cette page !",
    ];
    private $session;

    /**
     * @param $session
     * @param array $options
     */
    public function __construct($session, $options = ['']) {
        $this->options = array_merge($this->options, $options);
        $this->session = $session;
    }

    public function hashPassword($password) {
        return password_hash($password, PASSWORD_BCRYPT);
    }

    /**
     * @param $db
     * @param $username
     * @param $password
     * @param $email
     */
    public function register($Nom, $Prenom, $Age, $mail, $Password){
        $Password = $this->hashpassword($Password);
        $token = str::random(60);

        PDOProvider::get()->prepare('INSERT INTO Users SET Nom = ?, Prenom = ?, Age = ?, roles_id = 8, mail = ?, Password = ?, confirmation_token = ?', [
            $Nom, 
            $Prenom, 
            $Age, 
            $mail, 
            $Password, 
            $token  
        ]);

        $users_id = $PDOProvider->lastInsertId();
        $mail = strip_tags($mail);

        $header = "From : ".$mail;
        $sujet = "Confirmation de votre mail";
        $message = "Afin de valider votre compte, merci de cliquer sur le lien ci dessous:\n\n
        http//".$_SERVER['SERVER_NAME']."/sitejsp1/membres/confirm.php?id=".$users_id."&token=".$token;

        mail($mail, $sujet, $message, $header);
    }

    /**
     * @param $db
     * @param $user_id
     * @param $token
     * @return bool
     */

 public function confirm($user_id, $token) {
        $user = PDOProvider::get()->prepare('SELECT * FROM users WHERE id = ?', [$user_id])->fetch();

        if ($user->confirmation_token == $token) {
            $user = PDOProvider::get()->execute('UPDATE users SET confirmation_token = NULL, confirmed_at = NOW() WHERE id = ?', [$user_id]);

            $this->session->write('auth', $user);

            return true;

        $mail = strip_tags($mail);

        $header = "From : ".$mail;
        $sujet = "Validation de votre compte";
        $message = "Votre compte a bien été validé, cependant pour pleinement profiter des cours, faut attendre qu'un membres de l'encadrement valide votre compte.\n\n
        http//".$_SERVER['SERVER_NAME']."/sitejsp1/contact.php?";

        mail($mail, $sujet, $message, $header);
        }

        return false;

        $mail = strip_tags($mail);

        $header = "From : ".$mail;
        $sujet = "Validation de votre compte";
        $message = "Votre compte n'a pas été validé, merci de prendre contacte avec un membres de l'encadrement.";

        mail($mail, $sujet, $message, $header);

    }

    /**
     * function restrict
     */
    public function restrict(){
        if (!$this->session->read('auth')){
            $this->session->setFlash('danger', $this->options['restriction_msg']);

            header('Location: login.php');
            exit();
        }
    }

        /**
     * @return bool
     */
    public function user(){
        if (!$this->session->read('auth')){
            return false;
        }
        $this->session->read('auth');
    } 
    /**
     * @param $user
     */
    public function autoconnect($user) {
        $this->session->write('auth', $user);
    }

    /**
     * @param $db
     */
    public function connectFromCookie(){
        if (isset($_COOKIE['remember']) && !$this->user()){
            $remember_token = $_COOKIE['remember'];
            $parts = explode('==', $remember_token);
            $user_id = $parts[0];

            $user = PDOProvider::get()->prepare('SELECT * FROM users WHERE id = ?',[$user_id])->fetch();

            if($user) {
                $expected = $user_id."==".$user->remember_token.sha1($user_id.'blackshadow');
                if ($expected == $remember_token){
                    $this->autoconnect($user);
                    setcookie('remember', $remember_token, time()+60*60*24*7);
                } else {
                    setcookie('remember', NULL, -1);
                }
            } else {
                setcookie('remember', NULL, -1);
            }
        }
    }
     /**
     * @param $db
     * @param $user_id
     */
    public function remember($user_id) {
        $remember_token = Str::random(250);
        PDOProvider::get()->execute('UPDATE users SET remember_token = ? WHERE id = ?', [$remember_token, $user_id]);
        setcookie('remember', $user_id.'=='.$remember_token.sha1($user_id.'blakshadow'), time()+60*60*24*7);
    }

    /**
     * @param $db
     * @param $Nom
     * @param $password
     * @param bool $remember
     */
   public function login($mail, $password, $remember) {
        $user = PDOProvider::get()->prepare('SELECT users.prenom, users.age, users.password, roles.id, roles.pseudo, roles.rang, roles.level FROM users left JOIN roles ON users.roles_id=roles.id WHERE (mail = :mail) AND confirmed_at IS NOT NULL ', ['mail' => $mail])->fetch();
var_dump($mail);  

var_dump($password);

        if ($user && password_verify($_POST['password'], $user->password)){
            $this->autoconnect($user);

            if ($remember){
                $this->remember($user->id);
            }
            return $user; 
        } else {
            return false;
        }
    }

  public function logout() {
        setcookie('remember', NULL, -1);
        $this->session->delete('auth');
    }

    public function resetPassword($mail) {
       $user = PDOProvider::get()->prepare('SELECT * FROM users WHERE mail = ? AND confirmed_at IS NOT NULL', [$mail])->fetch();
        if ($user){
            $reset_token = Str::random(60);

            $user = PDOProvider::get()->execute('UPDATE users SET reset_token = ?, reset_at = NOW() WHERE id = ?', [$reset_token, $user->id]);

            $mail=strip_tags($mail);

            $header = "From : ".$mail;
            $sujet = "Reset du password";
            $message = "Pour réinitialiser votre mot de passe, merci de cliquer sur le lien ci-dessous: lien\n\n
           http://".$_SERVER['SERVER_NAME']."/sitejsp1/membres/reset.php?id={$user->id}&token=".$reset_token;

            mail($mail, $sujet, $message, $header);

            return $user;
        }
        return false;
    }

    public function confirmToken($user_id, $token) {
        return PDOProvider::get()->prepare("SELECT * FROM users WHERE id = ? AND reset_token = ? AND reset_at > DATE_SUB(NOW(), INTERVAL 30 MINUTE)",[$user_id, $token])->fetch();
    }
}

Merci de votre aide!!

Utilisation dans forget.php

$auth->resetPassword(PDOProvider::get(), $_POST['mail'])

déclaration dans auth.php

public function resetPassword($mail)

T'as plus besoin de passer ton PDO en argument, hein ;-)

Et t'as pas corrigé ta requête SQL dans auth->login -_-

Tâche de bien prendre en compte ce qui a été dit auparavant avant de revenir poser des questions :-s On ne peut rien te dire de plus que ce qui a déjà été dit! Le problème c'est qu'on aurait tendances à partir du principe, logiquement, que tu as déjà corrigé ce que l'on t'a dit de changer et passer à côté de ce que l'on a déjà signalé! Tu m'étonnes que t'avances pas si tu ne corriges que virtuellement O_o!

Là, par exemple, Huggy t'as indiqué quoi corriger dans la requête mais tu ne l'as pas fait et ça fait déjà 3 pages que je te dis de virer les pdo que tu n'utilises pas directement mais ça n'a pas encore été totalement réalisé... C'est un peu frustrant, je trouve..!

Hello
Psylozoff , j'ai remplacé les $db par PDOProvider::get()->prepare ou excecute, helas sa ne change rien je ne peux plus me connecter ou demander un nouveau MDP!!!

J'imagine que tu n'as rien modifié depuis mes derniers messages remontant à 24h... Et que tu passes toujours ton PDO à la fonction resetPassword..?

hello,

je passe que $mail a la fonction resetPassword!! je sais que je comprend vite mais faut m expliquer longtemps mais quand meme lol

 public function resetPassword($mail) {
        $user=PDOProvider::get()->prepare('SELECT * FROM users WHERE mail = ? AND confirmed_at IS NOT NULL', [$mail])->fetch();
        if ($user){
            $reset_token = Str::random(60);

            $user = PDOProvider::get()->execute('UPDATE users SET reset_token = ?, reset_at = NOW() WHERE id = ?', [$reset_token, $user->id]);

            $mail=strip_tags($mail);

            $header = "From : ".$mail;
            $sujet = "Reset du password";
            $message = "Pour réinitialiser votre mot de passe, merci de cliquer sur le lien ci-dessous: lien\n\n
           http://".$_SERVER['SERVER_NAME']."/sitejsp1/membres/reset.php?id={$user->id}&token=".$reset_token;

            mail($mail, $sujet, $message, $header);

            return $user;
        }
        return false;
    }

    forget.php
    <?php
 require_once "../class/bootstrap.php"; 

if (!empty($_POST) && !empty($_POST['mail'])){
   PDOProvider::get();
    $auth = App::getAuth();
    $session = Session::getInstance();
    if ($auth->resetPassword($_POST['mail'])) {
        $session->setFlash('success', 'Le rappel du mot de passe à été envoyé par mail');

        App::redirect('login.php');
    }else{
        $session->setFlash('danger', 'Aucun compte ne correspond à cette adresse');
    }
}
?>

soi ne je pige pas comment utiliser et placer pdoprovider::get ()!!? possible!!!
neanmoins je n'ai plus d'erreur d'execution mais je ne peux toujours pas me connecter ou demander un nouveau mdp car sa me dit "Identifiant ou mot de passe incorrect" ou "aucun compte ne correspond à cette adresse" pour l'inscription etant donné que l erreur me dit que register ai une methode non definie dans pdo sa doit etre un truc tous bete !!! lol

C'est pas comme ça qu'on utilise "prepare"... T'as besoin de faire un tour dans la doc! Et prends des notes!! ;-)

Pour l'instant t'es en train de "fetch" un "PDOstatement" vide...

Et puis, il y a tant à dire de ton code au niveau des optimisations :-s

  • pk tu "select *" si tu n'as besoin que de l'id..??
  • à quoi sert ton PDO:get dans forget..?
  • pour obtenir le contenu des globales GET, POST ou SERVER, il vaut mieux utiliser les filtres dédiés!
  • "à été envoyé" c'est le verbe avoir ;-p
  • et surtout... Surtout!! On envoie pas des infos sensibles sur le réseau en clair (http)!! Si j'intercepte ton mail je peux reset le compte à la place de son propriétaire...

hello
pk tu "select *" si tu n'as besoin que de l'id..?? ==> je selectionne toute ma table users c'est pas bien !?
à quoi sert ton PDO:get dans forget..? ==> a faire la connexion a la bd!, non?
pour obtenir le contenu des globales GET, POST ou SERVER, il vaut mieux utiliser les filtres dédiés! ok lesquels?
"à été envoyé" c'est le verbe avoir ;-p ==> corrigé mais je suis pas doué pour la grammaire ( comme pour la poo lol)
et surtout... Surtout!! On envoie pas des infos sensibles sur le réseau en clair (http)!! Si j'intercepte ton mail je peux reset le compte à la place de son propriétaire... ok donc je passe en https!?

C'est pas comme ça qu'on utilise "prepare"... T'as besoin de faire un tour dans la doc! Et prends des notes!! ;-)
ok!! euh j 'ai juste remplacer $db par pdoprovider donc je pige pas explique moi stp !!

Pour l'instant t'es en train de "fetch" un "PDOstatement" vide...
vide !! pourtant sur le var dump j ai bien les info de connection.

donc visiblement je n ai pas compris comment uiliser ta fonction static pdoprovider et get !!?
moi j ai compris que je devais virer les $db ok c est fait qe j ai remplacer par pdoprovider::get helas depyis je ne peut plus me loguer ni faire un rappel de mdp et je ne peux plus faire d inscription et la la vu mon tit niveau je comprends ou est le probleme!! snif

Tu auras toutes les réponses dans la doc... A quoi ça sert que je répète ce qui s'y trouve? Si t'as un problème avec un objet ou une fonction => documentation! En plus elle est en français..!

Ensuite, tu ne réponds pas à mes questions...

pk tu "select *" si tu n'as besoin que de l'id..?? ==> je selectionne toute ma table users c'est pas bien !? => toutes la ligne, tu veux dire? Et tu as besoin de toute la ligne..? N'utilises-tu pas seulement l'id..??

à quoi sert ton PDO:get dans forget..? ==> a faire la connexion a la bd!, non? => get ne sert pas à "faire" la connexion, il récupère juste l'instance de PDO, or tu n'en fais rien...

Tu trouveras un paquet d'info sur le filtrage dans la documentation!

https c'est un peu la base, aujourd'hui... Faut arrêter d'utiliser http! Maintenant les certifs sont gratos, donc bon, y'a plus d'excuse!

De quel var_dump tu parles...?

Plus globalement, serait-il possible que tu relises mes questions plusieurs fois en te référant au code que tu m'as fourni et que tu tâches d'être absolument sûr d'avoir bien compris ce que je dis et de quoi je parle? Serait-il possible que tu ne parles plus jamais de quoi que ce soit qui n'est pas visible? Parce que "le vardump" ça m'avance à que dalle!! Mets-toi un peu à ma place... Si tu parles d'un truc qui n'existe pas, fais au moins l'effort de le matérialiser --
Réfère-toi à la doc pour bien comprendre comment l'objet PDO fonctionne, comment utiliser ses fonctions touça! C'est bien plus que la simple base, c'est le genre de truc que tu as, si tu es normal et sensé, et que tu ne nous prends pas pour des cons, déjà fait plusieurs fois, n'est-ce pas? Qui irait demander de l'aide sans même avoir pris la peine de s'aider lui-même, après tout? Ca ferait de lui une larve...

Hello psylozoff

J'ai repondu a tes questions en fonction de mes petites connaissances !! mais je demande qu'a apprendre et comprendre !!
DSl mais je pense que j ai du louper un truc voir plusieurs lol car j'ai jamais compris comment utiliser ton provider et ton get .
Et oui je suis normale pas mongole et sensé je connai mes lagunes egalement, d'autre part je ne pense pas vous avoir pris pour des cons, comme je te les dit a plusieurs reprise j'ai pas compris comment utilisé ton provider et avant de venir ici j'ai chercher plus d une semaine avant de me decider a demander de l'aide.
donc j'ai repris une sauvegarde et je suis revenu avec mes problemes sur l'ajout, modification d'une news et maintenant je cherche une solution!!! Mais je n'ose pas vous demander de l aide car tu risque de penser que je vous prend pour des cons si je comprend pas tes explication!!!! oui a mon age on apprend et comprend moins vite mais j ai bonne espoir de trouver une solution en reprenant les fonctions news a zero!!

merci de votre aide meme si finalement j ai resolut aucun probleme et que j en ai eu plus finalement lol mais je pense qu'on ai pas parti dans la bonne direction....

La bonne direction serait d'assimiler les bases... Si tu ne comprends pas le code basique du provider c'est mal barré :-s
Et les problèmes que tu rencontres ont plus à voir avec le PDO que tu sembles ne pas connaitre! Or, il existe une documentation complète à ce sujet...
Reposte un extrait de ton code, genre le Provider ainsi qu'un endroit où tu l'utilises, genre la fonction resetPassword, avec chaque ligne commentée, pour voir un peu ce que tu en comprends, ce que tu crois que ton code fait ;-) Choisis bien tes mots pour que ce soit compréhensible!
Je trouve ça complètement ouf que tu ne bites rien O_o Du coup, j'aurais besoin que tu m'expliques exactement ce que tu crois de ton code, tu comprends? Comme ça je verrais clairement en quoi ta perception est biaisée!

Hello

Desolé pour cette long attente pour la reponse!!

le pdoprovider

class PDOProvider {

    private static $pdo = null;

    // constructeur privé, interdit l'instanciation
    private function __construct() {}

    public static function get() { /*cree une instance de pdo*/

        if (self::$pdo === null) {

            self::$pdo = new PDO("mysql:dbname=".DBDatabase::DBNAME.";host=".DBDatabase::HOST.";port=".DBDatabase::PORT. ";charset=utf8", DBDatabase::LOGIN, DBDatabase::PWD); /*cree un nouvel objet pdo et fait la liaison avec la bd*/
            self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); /*gestion des erreurs*/
            self::$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);    /* idem*/
}

        return self::$pdo; /* retour l'objet de pdo*/

}
     /**
     * @param $query
     * @param bool|array $params
     * @return PDOStatement
     */
/* fonction supprimée
    public function query
    public function lastInsertId(){*/

}

le fonction reset

public function resetPassword($db, $mail) {
 /*    recupere la ligne de l user */
        $user = self::$pdo ->query('SELECT * FROM users WHERE mail = ? AND confirmed_at IS NOT NULL', [$mail])->fetch(PDO::FETCH_ASSOC); 

        if ($user){ /*si l'user est present on genere un token */
            $reset_token = Str::random(60);
mise a jour de la ligne de  luser en bd
            $db =self::$pdo ->query('UPDATE users SET reset_token = ?, reset_at = NOW() WHERE id = ?', [$reset_token, $user->id]);
/*envoie le mail si l'user existe*/
            $mail=strip_tags($mail);

            $header = "From : ".$mail;
            $sujet = "Reset du password";
            $message = "Pour réinitialiser votre mot de passe, merci de cliquer sur le lien ci-dessous: lien\n\n
           http://".$_SERVER['SERVER_NAME']."/sitejsp1/membres/reset.php?id={$user->id}&token=".$reset_token;

            mail($mail, $sujet, $message, $header);

            return $user;
        }
        return false; /* si pas d'utilisateur correspondant on retourne faux */
    }

Donc voila la derniere erreur:
2002SQLSTATE[HY000] [2002] Aucune connexion n�a pu �tre �tablie car l�ordinateur cible l�a express�ment refus�e.
Bizarre car j ai rentre les bonnes info pour la connexion a la bd !! possible probleme avec la BD!?

Fatal error: Call to a member function query() on string in G:\jsp\EasyPHP-Devserver-17\eds-www\SiteJSP1\class\Auth.php on line 195
$user = self::$pdo ->query('SELECT * FROM users WHERE mail = ? AND confirmed_at IS NOT NULL', [$mail])->fetch(PDO::FETCH_ASSOC);

merci

Wow, c'est terrible :-s

Bon, alors, exercices!

  • renseigne-toi concernant la façon dont on rédige des commentaires dans du code! Un idice, y'a déjà 3 commentaires que tu n'as pas rédigé dans le code que tu me montres!

  • renseigne-toi concernant les attributs que tu utilises pour ouvrir la connexion à la DB...

  • renseigne-toi concernant les méthodes de l'objet PDO, leurs arguments et types de retour...

  • C'est quoi $db dans ta fonction resetPassword?

  • Pk tu utilises self::??

Réponds à tout ça et mets de vrais commentaires et on en reparle ;-)

Et dans ton Provider, supprime "query" et "lastinsertid"! T'en as pas besoin, elles existent déjà dans PDO... Sans compter que ce sont des méthodes d'instances que tu ne pourras donc pas utiliser -_-

Et quand je disais "commente toutes les lignes" je voulais dire "commente toutes les lignes"!! Pas une sur 10...
J'ai l'impression que tu ne cherches pas vraiment à comprendre et que tu te bases sur de vagues souvenirs de ce que tu as pu lire...
Je crois bien que tu ne comprends absolument pas ton code..! Et ça, c'est un gros problème!

hello
Les commentaires qui n'etaient pas entouré des balises prevu pour cet effet, present dans les codes donnés sur mon dernier poste on ete rajouté juste ici ok j aurai du les entourer!!

pour le probleme de connexion a la BD, je les resolu!! pour la fonction query et lastinsertid je les aient supprimées.

pour le self:: c'etait une erreur c'etait juste pour provoquer des erreurs !
Ta peut etre raison oui j'essai de me souvenir de mes souvenirs!! et j'ai mis la charu avant les boeufs, mais j'essaie de comprendre la doc "beaucoup de mal" et de me depatouillé tous seul j'aime bien comprendre par moi meme oui sa peut etre long !! mais j'ai avancé avec le peux de temps que j'ai ,
me reste a refaire les requetes preparé et les execution !!! plus qu a bien comprendre comment struturé une requete preparé et son execution.

Tu connais discord? Tu veux un contact audio?

Bonjour.
Il y a quelque chose que j'ai du mal à comprendre, quel est l'intérêt du code suivant :

// constructeur privé, interdit l'instanciation
private function __construct() {}

Tu n'es aucunement obligé de créer la fonction __construct, lorsque tu crées une classe, sauf si tu veux quelle fasse quelque chose lors qu'elle est appelée, sauf que dans ton cas elle ne fait absolument rien et que la seule fonction restante est une fonction statique.
Par conséquent, je ne vois même pas l'utilité que tu définisses le constructeur en tant que fonction private.
Si par la suite tu comptes étendres les fonctionnalité de ta classe, il te sera toujours tant d'ajouter le constructeur et de le définir privé si nécessaire.

Ca permet d'interdire l'instanciation de la classe... Un réflexe issu de Java ;-)
Le constructeur est public par défaut, me semble-t-il...
La classe ne doit pas être instanciable, c'est la seule raison de ce code!

Bonsoir,
DSL de l'enorme delais de reponse !!
Mais j etait tres occupé entre le taff et la famille c'est compliqué de trouver des heures pour jouer avec php.
Aujourd'hui j ai eu un peux de temps helas impossible de me connecter !!
j ai fait des var_dump de $mail, $password le resultat
var_dump($mail); = object(PDO)#3 (0) { }
var_dump($password); = string(15) "admin@jspnsf.fr"
echo $password; = admin@jspnsf.fr

je comprends pas pourquoi echo $password renvoie l'adresse mail !!????

fonction login:

public function login($mail, $password, $remember) {

      $user = PDOProvider::get()->query("SELECT * FROM users WHERE 'mail = :mail' AND 'password = :password' AND confirmed_at IS NOT NULL")->fetch();

        var_dump($mail);
        var_dump($password); 
           echo $password;
            if ( password_verify($password, '$password->$user')){

            $this->autoconnect($user);

            if ($remember){
                $this->remember($user->id);
            }
            return $this->user;
        } else {
            return false;
        }
    }

Merci de votre aide

euh personne snif!!!