Page 1 sur 2

probleme jointure en POO

Posté : 03 juil. 2012, 22:24
par juliette
Salut a tous, je me lance dans le poo, j'ai donc créer un classe:
<?php

Class DB {

    private $host = 'localhost';
    private $username = 'root';
    private $password = '';
    private $database = 'chien-drouais';
    private $db;

    public function __construct($host = null, $database = null, $username = null, $password = null) {
        if ($host != null) {
            $this->host = $host;
            $this->username = $username;
            $this->password = $password;
            $this->database = $database;
        }
        try {
            $this->db = new PDO('mysql:host=' . $this->host . ';dbname=' . $this->database, $this->username, $this->password,
                        array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8', PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION, PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
        } catch (PDOException $e) {
            die('<h1>Impossible de se connecter a la base de donnees !</h1>');
        }
    }

    public function query($sql) {
        $req = $this->db->prepare($sql);
        $req->execute();
        return $req->fetchAll(PDO::FETCH_OBJ);
    }

}

?>
et je récupère les infos comme ca:
<?php
                                        // affichage du dernier blog
                                        $blogs = $DB->query('SELECT id_blog, titre, intro, post_member_id, timestamp FROM blog ORDER BY timestamp ASC LIMIT 1');
                                        foreach ($blogs as $blog):
                                            echo<<<HEREDOC
                                Blog N° $blog->id_blog --> $blog->titre <br />
                                $blog->intro <br />
                                Posté par $blog->post_member_id. le $blog->timestamp.<hr />
                                  
HEREDOC;
                                        endforeach;
?>
mon soucis est que je n'arrive plus a faire de jointures...
quelqu'un as t'il une idée de mon problème ?
merci d'avance Juliette.

en cas de jointure avec les commentaires du post, var_dump de $blogs ne me rend que le post et le dernier commentaire du post... #-o

Re: probleme jointure en POO

Posté : 04 juil. 2012, 09:14
par moogli
Salut,

as tu un exemple de requête avec jointure ?

pour info
<?php
try {
            $this->db = new PDO('mysql:host=' . $this->host . ';dbname=' . $this->database, $this->username, $this->password,
                        array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8', PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION, PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
        } catch (PDOException $e) {
            die('<h1>Impossible de se connecter a la base de donnees !</h1>');
        }
?>
tu définie deux fois le mode erreur, c'est pas forcément top :)
Le die pour les message d'erreur c'est moyen coté accessibilité du site, même si je sais bien que cette erreur est généralement "fatale" l'afficher correctement avec le thème du site c'est pas mal.
tu peux aussi ajouter le message d'erreur, c'est plus facile pour le debug ($e->getMessage()).

Pourquoi une requête préparée ? c'est totalement inutile dans ce cas.

Tu peux aussi faire hériter ta classe de PDO et donc avoir directement accès a toutes les méthodes de PDO directement dans ta classe tout en surchargeant le constructeur pour indiquer les infos de connexion perso.


@+

Re: probleme jointure en POO

Posté : 04 juil. 2012, 10:38
par juliette
Alors, pour la requete je fait comme ca:
<?php
                                        // affichage du dernier blog
                                        $blogs = $DB->query('SELECT 
                                            bl.id_blog            AS     id_blog, 
                                            bl.titre              AS     titre, 
                                            bl.intro              AS     intro, 
                                            bl.post_member_id     AS     member_post_bl, 
                                            bl.timestamp          AS     timestamp,
                                            
                                            com.id_commentaire_blog     AS    id_com,
                                            com.post_member_id          AS    member_post_com,
                                            com.id_blog                 AS    com_id_blog,
                                            com.commentaire             AS    commentaire,
                                            com.timestamp               AS    com_timestamp
                                            
                                            FROM blog bl
                                            
                                            LEFT JOIN commentaires_blog com   ON  bl.id_blog  =  com.id_blog
                                            
                                            ORDER BY timestamp ASC LIMIT 1');
                                        foreach ($blogs as $blog):
                                            echo<<<HEREDOC
                                Blog N° $blog->id_blog --> $blog->titre <br />
                                $blog->intro <br />
                                Posté par $blog->post_member_bl. le $blog->timestamp.<hr />
                                  
HEREDOC;
                                        endforeach;
A savoir, cette requête fonctionne dans phpmyadmin...

pour ma requête si je comprend bien, c'est dans la class qu'il me manque une fonction avec une requête non préparer ?
Tu peux aussi faire hériter ta classe de PDO et donc avoir directement accès a toutes les méthodes de PDO directement dans ta classe tout en surchargeant le constructeur pour indiquer les infos de connexion perso.
La je ne comprend plus #-o

Re: probleme jointure en POO

Posté : 04 juil. 2012, 13:12
par juliette
bon, je pense avoir correctement corrigé la classe, en tous cas ça marche...
<?php

Class DB {

    private $host = 'localhost';
    private $username = 'root';
    private $password = '';
    private $database = 'chien-drouais';
    private $db;

    public function __construct($host = null, $database = null, $username = null, $password = null) {
        if ($host != null) {
            $this->host = $host;
            $this->username = $username;
            $this->password = $password;
            $this->database = $database;
        }
        try {
            $this->db = new PDO('mysql:host=' . $this->host . ';dbname=' . $this->database, $this->username, $this->password,
                        array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8', PDO::ERRMODE_EXCEPTION, PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
        } catch (PDOException $e) {
            die($e->getMessage().'<h1>Impossible de se connecter a la base de donnees !</h1>');
        }
    }

    public function query($sql) {
        $req = $this->db->prepare($sql);
        $req->execute();
        return $req->fetchAll(PDO::FETCH_OBJ);
    }

}

?>
donc, j'ai maintenant besoin d'une 2eme fonction autre que prépare: c'est bien ça ???

Re: probleme jointure en POO

Posté : 04 juil. 2012, 13:34
par moogli
J'avoue qu'a part l'ajout du message d'erreur je ne vois pas trop de modif :)

je voyais plutôt vu quelque chose comme ça
<?php 
class DB extends PDO{

	private $host = 'localhost';
	private $username = 'root';
	private $password = '';
	private $database = 'chien-drouais';
	private $db;
	/**
	 * Constructeur
	 * @param String $host
	 * @param String $database
	 * @param String $username
	 * @param String $password
	 * @throws \Exception
	 */
	public function __construct($host = null, $database = null, $username = null, $password = null) {
		if (empty($host) == false) { // donc en considérant qu'un accès annonyme est possible et qu'un use laBase sera fait
			$this->host = $host;
			$this->username = $username;
			$this->password = $password;
			$this->database = $database;
		}
		try {
			parent::__construct('mysql:host=' . $this->host . ';dbname=' . $this->database, $this->username, $this->password,
					array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8', PDO::ERRMODE_EXCEPTION);
		} catch (PDOException $e) {
			throw new \Exception('<h1>Impossible de se connecter a la base de donnees !</h1>'.$e->getMessage());
		}
	}
	/**
	 * Retourne tout les résultats de la requete dans un tableau d'objet
	 * @see PDO::query()
	 */
	public function query($sql) {
		if (empty($sql) == false){
			$req = parent::query($sql);
			return $req->fetchAll(PDO::FETCH_OBJ);
		}
		else {
			throw new Exception('La requete SQL ne peux être vide');
		}
	}
}
?>
A tester

par contre si ta requete est fonctionnelle, ça ne devrait pas poser de problème.

Essai en ajoutant des var_dump() dans la classe pour vori ce que retourne l'execute.

Ma remarque quand l'execute est que tu n'a pas besoin de faire une requete préparé quand tu n'utilise pas ce mécanisme.
Les requete préparée sont utile dans le cas d'utilisation massive d'une requête, par exemple lors d'insertion en base des données d'un fichier c'est utilise et tu peux gagner en perf façon un l'utilisation d'une requete "normale".
Mais la aucun besoin, cette utilisation n'apporte absolument rien dans ton cas ;)

Re: probleme jointure en POO

Posté : 04 juil. 2012, 14:10
par juliette
en fait, je n'aurais pas su faire, je ne saisie pas encore tous...
la j'obtiens avec:
array
  0 => 
    object(stdClass)[5]
      public 'id_blog' => int 1
      public 'titre' => string 'titre' (length=5)
      public 'intro' => string 'intro' (length=5)
      public 'member_post_bl' => int 1
      public 'timestamp' => int 1330873498
      public 'id_com' => int 1
      public 'member_post_com' => int 1
      public 'com_id_blog' => int 1
      public 'commentaire' => string 'commentaire' (length=11)
      public 'com_timestamp' => int 0
  1 => 
    object(stdClass)[6]
      public 'id_blog' => int 1
      public 'titre' => string 'titre' (length=5)
      public 'intro' => string 'intro' (length=5)
      public 'member_post_bl' => int 1
      public 'timestamp' => int 1330873498
      public 'id_com' => int 2
      public 'member_post_com' => int 1
      public 'com_id_blog' => int 1
      public 'commentaire' => string 'commentaire 2' (length=13)
      public 'com_timestamp' => int 0
je t'avoue que je suis bien largué mais ça viendras mais pour le coup, je ne sais pas trop comment récupérer les informations des objets.
comme tu peux le voir, chaque objets contient le post du blog et 1 commentaire...

Re: probleme jointure en POO

Posté : 04 juil. 2012, 14:21
par xTG
echo $array[0]->titre;
Par exemple. :)

Re: probleme jointure en POO

Posté : 04 juil. 2012, 16:56
par moogli
Pour l'affichage il faut que tu fasse une "césure" dans la boucle pour n'afficher que les commentaire associé au "blog" et ainsi ne pas afficher toutes les autres infos. (en gros tu garde le nom / l'id du blog dans une variable et a chaque tour tu regarde si celui gardé est le même que celui "actuel" tu n'affiche que les commentaires, sinon tu affiche tout et remplace la sauvegarde par le nouveau.

en plus clair
<?php
$save = null;
while($truc) {
if (save != $truc->id){
$save = $truc->id;
echo 'j affiche les infos "globale"';
}
echo 'j affiche le commentaire courant';
}
?>
@+

Re: probleme jointure en POO

Posté : 07 juil. 2012, 12:43
par juliette
bon, encore un peut complexe pour moi, je suis revenu sur un code plus simple, ce que je ne comprend pas toujours, ce sont les thermes employé et les sous entendus sur les actions de php...
je n'abandonne pas l'objet :non: , au contraire mais je dois continuer a lire des trucs avant de vraiment pouvoir continuer... #-o

Re: probleme jointure en POO

Posté : 09 juil. 2012, 09:03
par moogli
ce que je ne comprend pas toujours, ce sont les thermes employé et les sous entendus sur les actions de php...
dit nous ce que tu ne comprend pas, on peux t'expliquer (c'est d'ailleurs pour cela que l'on traine ici :)).

au pire on te filera un liens ves un bon tuto :mrgreen:


@+

Re: probleme jointure en POO

Posté : 09 juil. 2012, 12:55
par juliette
je ne sais pas trop ce que je ne comprend pas, et ce n'est pas réellement que je ne comprend pas mais plutôt que j'avance trop vite je pense sans avoir une maîtrise complète de ce que je connais déjà...
en procédurale j'arrive a faire ce dont j'ai besoin mais la avec les objets, je ne comprend plus rien...
quand j'ai commencer avec cette classe, j'avais le but de faire une classe pour tous les types de requête que j'utilise et je n'ai rien réussi a faire avec la connexion que tu m'a donner pourtant elle fonctionne très bien, pour le coup j'ai tous recommencer et j'en suis arrivé la:
class connexion {
<?php
    private $host;
    private $user;
    private $pass;
    private $conn;
    private $pdo;

    public function __construct($bdd = "genea_bdd") {
        $this->host = "localhost";
        $this->user = "root";
        $this->pass = "";
        $this->conn = "host={$this->host};dbname={$bdd}";
        try {
            $this->pdo = new PDO("mysql:$this->conn", $this->user, $this->pass);
            $this->pdo->setAttribute(PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            echo "error " . $e->getMessage();
        }
    }
    
    // fonction pour rechercher un resultat unique
    public function unique($critere, $requete) {
        if ($critere !== null)
            $critere = array_values($critere); 
        $select = $this->pdo->prepare($requete);
        $select->execute($critere);
        $select->setFetchMode(PDO :: FETCH_OBJ);
        $objet = $select->fetch();
        return $objet;
    }

    // fonction pour faire une boucle
    public function boucle($critere, $requete) {
        if ($critere !== null)
            $critere = array_values($critere); 
        $select = $this->pdo->prepare($requete);
        $select->execute($critere);
        $select->setFetchMode(PDO :: FETCH_OBJ);
        return $select;
    }

    // fonction pour comptre des champs
    function compte($critere, $requete) {
        if ($critere !== null)
            $critere = array_values($critere);
        $count = $this->pdo->prepare($requete);
        $count->execute($critere);
        $nombre = $count->rowCount();
        return $nombre;
    }

    public function insert($critere, $requete) {
        if ($critere !== null)
            $critere = array_values($critere);
        $insert = $this->pdo->prepare($requete);
        $insert->execute($critere);
    }
    
    public function update($critere, $requete) {
        if ($critere !== null)
            $critere = array_values($critere);
        $update = $this->pdo->prepare($requete);
        $update->execute($critere);
    }

}

?>
peut être un mélange entre les différences version de php, je ne sais pas trop te dire. quoi qu'il en soit, je suis souvent dans la flou...

merci d'avance pour tous...

Re: probleme jointure en POO

Posté : 09 juil. 2012, 13:11
par juliette
et je fait une requete comme ca:
<?php
                                                $bdd = new connexion ();
                                                $critere = array();
                                                $requete = "SELECT * FROM members";
                                                $resulta = $bdd->boucle($critere, $requete);

                                                while ($champ = $resulta->fetch()) {
                                                    echo'
                                                    <tr>
                                                        <td>
                                                            '.$champ->member_id.'
                                                        </td>
                                                        <td>
                                                            '.$champ->firstname.'
                                                        </td>
                                                        <td>
                                                            '.$champ->lastname.' 
                                                        </td>
                                                        <td>
                                                            '.$champ->email.' 
                                                        </td>
                                                        <td>
                                                            '.date('j-m-Y à H:i:s', $champ->inscription).' 
                                                        </td>
                                                    </tr>';
                                                }
                                                ?>
en fait, on est sorti du sujet...
mon test avec la 1er classe était d'afficher le dernier post du blog avec ses commentaires et j'ai voulu faire le tout en une requête mais impossible de séparer les commentaires et blogs des objets, tu ma proposer césure et j'ai chercher mais je n'ai trouver que sur des chaines donc je n'ai pas réussi alors j'ai fait une requête pour avoir le dernier blog et ensuite une jointure pour avoir les message de ce dernier blog, et tous fonctionne bien même avec ta classe...
ensuite j'ai voulu préparer mes fonctions pour les requête mais la non plus, je n'ai rien réussi alors j'ai tous recommencer pour arriver a la dernière classe que j'ai affiché au dessus.
voila en gros l'historique de mes déboires avec php pour cet exercice :?

Re: probleme jointure en POO

Posté : 09 juil. 2012, 13:22
par Mazarini
Bonjour,

Je trouve ton code bien. Il manque une fonction pour le delete. Eventuellement, je factoriserai du code présent dans beaucoup de tes fonctions dans une fonction privée.

Il pourrait être intéressant de retourner l'id en cas d'insert, le nombre de lignes touchées en cas d'update ou de delete.

Pour les erreurs, tu pourrais déjà traiter les erreurs qui provoquent une fin de script dans cette classe pour ne traiter que de l'applicatif dans la partie qui utilise la classe. Je pense au "non trouvé" et au "clé en double"

Re: probleme jointure en POO

Posté : 09 juil. 2012, 13:36
par juliette
cool Mazarini, merci...
j'ai bien l’intention de la continuer, mais la tu vois ton post tombe a point, par exemple je ne comprend pas:
je factoriserai du code présent dans beaucoup de tes fonctions dans une fonction privée
traiter les erreurs qui provoquent une fin de script dans cette classe pour ne traiter que de l'applicatif dans la partie qui utilise la classe. Je pense au "non trouvé" et au "clé en double"
la est mon vrai problème, bien souvent je ne comprend que la moitié de ce qu'on me dis... #-o je ne désespère pas, ça viendras :wink:
merci a tous =D>

Re: probleme jointure en POO

Posté : 10 juil. 2012, 00:00
par moogli
Césure : dans notre cas cela consiste à organiser le changement de ligne.

Par exemple tu garde le blog courant et à chaque "tour" de while tu compare avec celui du tour d'avant.
Exemple
<?php
$save = null;
while( $req){
if($save !== null && $req-> blog === $save){
$save = $req->blog;
// affichage de la séparation 
echo 'affichage du nouveau blog';
}
echo 'affichage du commentaire quelque soit le blog';
}
?>
Quand au reste c'est assez "simple"

Factoriser c'est comme en math ;). Le but est de réduire le code au maximum.
C'est que tu fait en création une fonction ou une classe que tu va ré employer. (plus besoin de copier / coller partout la connexion pdo ou autre test de validation etc etc.

Le traitement d'erreur la le but c'est de faire en sorte que les messages d'erreurs s'affichent ( ou pas ) de façon à ce que le site reste navigable. Donc supprimer les Die et exit qui parfois pullule dans les scripts et empêche la page de s'afficher totalement.

Cela passe, par exemple, par l'utilisation de try / catch et le fait de vérifier les retours de fonction pour éviter les messages d'erreur du à un retour null / false.
Ça permet aussi de logger les erreurs pour les analyser ensuite (par exemple). Ça permet de masque les véritables erreurs afin de ne pas montrer à tout le monde des infos qui pourrait être utilisée à ton encotre ;).


@+