Pb avec la class de news de FhX

Résolu
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 - 16 juil. 2008 à 17:15
 bZx - 20 nov. 2010 à 15:22
Bonjour à tous,

Je me présente, je m'appelle Nicolas, j'ai 24ans et la POO en PHP est nouveau pour moi.

Je me suis mis en tête d'utiliser la class de news posté par FhX (lien sur phpcs)

Super leçon d'architecture Web en PHP, utilisation des design pattern (Factory, Singleton) mais je suis perdu lorsqu'il faut l'utiliser...

en gros mon problème est :
comment on récupère le resultat quand on fait un getMultipleNews(0,3) ?

j'ai comme code :

$NewsFactory = new NewsFactory();
$news = $NewsFactory->GetMultipleNews(0,3);
var_dump($news);

le truc c'est que le var_dump me renvoi bien un array mais qu'avec une seule news dedans... ! je comprends pas pourquoi...

Ensuite comment on fait pour utiliser la méthode AddNews, le truc c'est que cette méthode est typé NewsObject d'accord donc quand je fais ça est-ce correct ?

Code:
$monActu  = array("titre"=>"Un test de titre", "contenu"=>"Un contenu");
$ajoutActu = new NewsObject($monActu);

$NewsFactory = new NewsFactory();
$news = $NewsFactory->AddNews($ajoutActu);

je sais pas si c'est bon mais ça fonctionne pas !

Bref, si quelqu'un avait des réponses et/ou des solutions, se serait merveilleux !!!

Merci de votre aide, moi je suis dans le brouillard et là je vois plus rien

Nicolas

ps: j'ai posté un commentaire demandant des exemples, je lui ai écrit un message privé et maintenant je poste sur le forum... je sais je suis un boulet !

30 réponses

codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
18 juil. 2008 à 20:42
//Classe NewsIterator

class NewsIterator implements Iterator {

 
    private $_oDb;

    private $_rResult;

    private $_aCurrentArray = array ();

    private $_oCurrentNewsObject;

     
    //constructeur

    public function __construct ($Db, $Resultat) {

        $this->_oDb = $Db;

        $this->_rResultat = $Resultat;

    }

     
    //rambobine le tableau

      public function rewind() {}

 
    //retourne la position courante

     public function current() {

        return $this->_oCurrentNewsObject;

      }

     
    //retourne la clé

      public function key() {

      }

     
    //accéde à la position suivante

    public function next() {

        // J'ai fait quelques modifications ici, on stoque maintenant le tableau retourné par la requete sql ET l'objet NewsObject crée

        // Tout simplement pour tester si le tableau est valide (différent de false, qui est la fin de fetching dans mysql)

        // Et il est stocké dans la classe (le tableau) car il est encore testé dans la méthode "valid"

        // On stocke l'object $_oCurrentNewsObject pour le donner à manger dans la méthode "current", tout simplement :)

        $this->_aCurrentArray = $this->_oDb->get_array($this->_rResultat);

        $this->_oCurrentNewsObject = new NewsObject($this->_aCurrentArray);

        return ($this->_aCurrentArray === false) ? false : true;

     }

     
    //valide l'objet en cours

      public function valid() {

          // Modifications effectuées ici :

              // Il faut indiquer si les valeurs sont valides ou pas, afin d'indiquer au boucles (foreach, while) quand s'arreter)

              // Je teste donc mon tableau pour savoir s'il vaut false, c'est la fin du fetching dans mysql, donc on arrete !

              // Comme mon tableau avait été à l'originie initialisé à array () (voir en tete de la classe), la premiere fois que la méthode valid est appelée, elle possede array () et pas false.

              // Si on avait pas mis la valeur par défaut à array (), la valeur aurait été nulle

          return ($this->_aCurrentArray === false) ? false : true;

    }

}



J'ai mis en commentaires (en gras) les modifications que j'ai faites.

Maintenant ca marche chez moi, donc ca devrait etre bon chez toi aussi !
Si tu a aussi un probleme d'encodage, utilise utf8_encode (ou decode je sais jamais :p)

Oui je pouvais attendre jusque lundi, mais tu te serai arraché la tete tout le week end ! :)

Je t'invite par contre à regarder les classes d'abstractions sgbd que tu trouvera sur phpcs et réalisée par Fhx, Malalam, et moi même, entre autres, nous utilisons les itérateurs, qui montrent un très bon exemple de leur implémentation. Tu comprendra ptete mieux leur utilité et leur fonctionnement (vu que dans ton cas tu ne vérifiait pas la validité (méthode valid) par exemple :))

Courage!

http://www.ReFlectiv.Net
3
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
17 juil. 2008 à 12:40
$news = $NewsFactory->GetMultipleNews(0,3);
$news ne retourne qu'une valeur car il faut itérér dessus pour avoir les autres
si tu fait un
foreach ($news as $new) {
var_dump ($new);
}

tu devrais avoir 3 var_dump d'affiché

Pour ton probleme d'ajout de news, ca devrait marcher
que te retourne un
var_dump ($ajoutActu); ?

http://www.ReFlectiv.Net
0
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
17 juil. 2008 à 14:10
grand merci à toi de t'interessser à mon problème !

je desesperé de plus en plus ...

sinon mauvaise nouvelle... j'ai déjà essayé de boucler avec foreach et le truc c'est que ça ne fonctionne pas

Voici ce que me retourne le var_dump dans le foreach

//actu 3
int(3)

string(18) "Une troisième actu"

string(33) "et c'est parti pour la troisièmre"

string(10) "2008-07-16"

string(10) "2008-07-16"

//actu 2
NULL

//actu 1
NULL

c'est louche non ?!!!!

var_dump($ajout_actu) me retourne bien un objet de type NewsObject

object(NewsObject)#3 (7) {

     ["id"]=>
int(0)

     ["titre"]=>
string(16) "Un test de titre"
     ["contenu"]=>
string(10) "Un contenu"

     ["dateInsertion"]=>
NULL

     ["dateModification"]=>
NULL

     ["publication"]=>
NULL

     ["validation"]=>
NULL
}
 le truc c'est que rien ne s'insère en base...
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
17 juil. 2008 à 14:23
A en voir le code, le problème se situerait dans son code.
En effet, par défaut, la sortie est un objet.
Il fait un fetch_array (return $this->{$this->_option['outputMethod']}( $this->db->fetch_array() );
) dans la méthode toObject, qui fait instancie la classe NewsObject avec le tableau en parametre.
Le probleme, c'est que NewsObject n'est là que pour une entrée. Il devrait faire plusieurs instances de NewsObject. Donc voila pourquoi tu n'a qu'une entrée !

Tu utilise quoi pour l'acces à la base de donnée ?
Parce que Fhx utilise une classe propre à lui apparement, tu l'a récupérée aussi ?

Personnellement, à moin bien t'y connaitre en poo, tu peux changer de classe :p

Pour récuperer les valeurs tu peux directement utiliser les tableaux et dans getMultipleNews, tu peux remplacer return $this->{$this->_option['outputMethod']}( $this->db->fetch_array() ); 
par return $this->db->fetch_array(); (en espérant qu'il te retourne un array complet)

Si tu veux passer par la classe NewsObject, va falloir implémenter du Iterator :p

Tu peux aussi contacter Fhx (en mp ou sur sa source directement) afin de lui indiquer que sa source à quelques problemes en espérant qu'il aie le temps de la remettre à jour :)

http://www.ReFlectiv.Net
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
17 juil. 2008 à 14:31
c'est exactement ce que je ne voulais pas entendre !!!

en effet j'utilise ma propre class mysql, je savais (et tu me l'as confirmé)  que le problème venait de l'instanciation des objets NewsFactory, en fait tel quel, le resultat précédent et écrasé par le resultat suivant, d'ou la récuperation unique de la dernière actu demandé.

ta solution est valide, je l'ai essayé, mais c'est un peu bête de sortir de la fabrique sans passé par une sortie NewsObject !!!!

j'ai déjà demandé de l'aide à FhX en message privé mais il ne m'a pas donné signe de vie (et oui les vacances !)

je vais plancher sur Iterator, ça va donner l'occasion de l'implémenter...

je reste quand même ouvert aux solutions !!! plus on est de fous, plus on rit !

Merci à toi CodeFalse

Nico
[auteur/CODEFALSE/2677.aspx ]
0
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
17 juil. 2008 à 14:33
je viens de me relire, pardon pour les fautes !!! l'émotion, surement !
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
17 juil. 2008 à 14:48
Je sais pas si tu à déjà joué avec des itérator en php. Si non je peux te donner une idée de structure pour le code de Fhx et donner quelque chose d'a peu pres fonctionnel.

Tu va faire une classe NewsIterator (par exemple) qui implémente Iterator, Seekable (optionnel) et Countable.

Tu implémente toutes les fonctions nécéssaire (renseigne toi du coté de la spl pour cela). Tu fait un constructeur qui accepte un tableau en entrée, tableau que tu stockera dans une variable privée.

Chaque appel à la  méthode current retournera une instance de NewsObject avec le tableau $aTableau[$iIndex]. $iIndex étant un variable qui indique l'index de la position dans le tableau (qui démarre à -1 lors de l'instanciation, et qui est incrémenté de +1 à chaque appel de next).

Je te conseil par ailleur d'éviter de faire return new NewsObject ($aTableau[$iIndex]) dans la méthode current, au cas ou l'utilisateur ferait plusieurs fois appel à current.
Mais plutot de mettre dans next un truc du genre
$this->_iIndex++;
$this->_oCurrentNewsObject = new NewsObject ($aTableau[$this->iIndex]) ;

et de ne retourner que $this->_oCurrentNewsObject lors de l'appel à current ();

count () retourne count ($this->_aTableau);

Et dans la méthode GetMultipleNews de Fhx, tu fait
return new NewsIterator ($this->db->fetch_array());

Bon du coup tu perd toute la possibilité de l'option Objet/Xml mais bon ...

http://www.ReFlectiv.Net
0
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
17 juil. 2008 à 15:27
ok je vais tenter un truc du genre !

mais j'ai menti avant en fait tu m'as dit

Pour récuperer les valeurs tu peux directement utiliser les tableaux et dans getMultipleNews, tu peux remplacer returnoutputMethod']}(
$this->db->fetch_array() );  par return
$this->db->fetch_array(); $this->{$this->_option['(en espérant qu'il te retourne un array
complet)

oups ! le truc retourne pas un arret complet ! ce que je ne comprends pas...

je vais tenter de créer la class IteratorNews... je te tiens au jus... j'espere que tu vas avoir encore un peu temps à me consacrer !

nico
0
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
17 juil. 2008 à 16:29
j'ai essayé de faire un truc mais j'ai pas encore pu tester (et oui on me dérange toutes les 2min)

class NewsIterator implements Iterator, Countable {

    private $mesActus = array();
    private $position = 0;
    private _oCurrentNewsObject;
   
    //constructeur
    public function __construct($mesActus) {
        if(is_array($mesActus) {
            $this->mesActus = $mesActus
        }
    }
   
    //rambobine le tableau
    public function rewind() {
        reset($this->mesActus);
    }

    //retourne la position courante
    public function current() {
        return $this->_oCurrentNewsObject;
     }
   
    //retourne la clé
    public function key() {
        $mesActus = key($this->mesActus);
        return $mesActus;
     }
   
    //accéde à la position suivante
    public function next() {
        $this->position++;
        $this->_oCurrentNewsObject = new NewsObject($this->mesActus[$this->position]) ;
     }
   
    //valide l'objet en cours
      public function valid() {
        $mesActus = $this->current() !== false;
        return $mesActus;
     }
     
    //méthode pour compter les objets
    public function count() {
        return sizeof($this->mesActus);
    }
}

tu peux corriger le truc, je commence à comprendre l'interet des Iterateurs...

nico
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
17 juil. 2008 à 21:35
    //retourne la clé
    public function key() {
        $mesActus = key($this->mesActus);
        return $mesActus;
     }

pourquoi ne pas faire
return key($this->mesActus);

    //valide l'objet en cours
      public function valid() {
        $mesActus = $this->current() !== false;
        return $mesActus;
     }
idem

Après je n'ai rien de spécial à dire, ton code est correct.
Comme tu le vois, c'est ultra simple d'utiliser les itérateurs, et c'est super utile et très puissant !!!! :)

Par ailleur, les itérateurs, c'est qu'un début ! Ca fait partie de la Spl, si tu jete un oeil aux autres possibilités, tu va voir que les options sont infinies.

Par contre, ne pas oublier, php doit tourner en 5.2 !! (T'a vérifié sur ton serveur ? (je parle en connaissance de cause :p))

Courage en tout cas :)

http://www.ReFlectiv.Net
0
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
18 juil. 2008 à 09:15
Bonjour CodeFalse,

j'ai envie de dire c'est le b....l ! j'ai un problème avec l'implémentation de l'itérateur, du style "Notice: Undefined offset: 1 in ..."
bref, en gros quand je fais un print_r dans le constructeur de NewsIterator j'ai qu'une news !!!!!!!!!!

ça veut dire que lorsque j'appelle new NewsIterator dans le return de GetMultipleNews j'ai toujours qu'une actu... je pete les plombs !

Revoici la méthode :

    public function GetMultipleNews($start, $limit) {

        if( !$this->flag) {
            $requete = 'SELECT
                        id, titre, contenu, dateInsertion,dateModification
                        FROM actualites
                        WHERE publication="1"
                        ORDER BY id DESC LIMIT '.$start.', '.$limit;

            $resultat = $this->db->Send_Query($requete, $this->linkBDD);
       
            $this->flag = TRUE;
        }

       //conseillé par CodeFalse
        $sortie = $this->db->get_array($resultat);
        return new NewsIterator($sortie);
       
        //return $this->{$this->option['sortie']}($this->db->get_array($resultat) );
           
    }

Le truc c'est lorsque je fais un while direct dans la méthode c'est ok !
je sors un tableau associatif ... (mysql_fetch_assoc), devrais-je sortir en mysql_fetch_array ? (je vais tester)

while($sortie = $this->db->get_array($resultat) {
    echo $sortie['titre'];
}

tu as une explication ? moi je comprends plus rien ...
Voici le lien des mes sources Fichier PHP
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
18 juil. 2008 à 09:42
Ah mon avis, le probleme vient de la classe de gestion à la bdd.
L'appel à la méthode get_array te retourne qu'une entrée. Peut-etre existe-t-il une autre méthode du style getAllArray ?

Bon, ce n'est pas ce qui est recommandé.

Dans le cadre d'un retour de query, il est préférable de passer l'instance de l'objet bdd à ton itérateur, qui fera un fetch dans le next, et récupere le résultat sous forme de tableau qu'il retourne.

Donc probablement que ton code ne devrait pas etre
//return $this->{$this->option['sortie']}($this->db->get_array($resultat) );

mais ca :
return new NewsIterator($this->db, $resultat);

Dans ton constructeur tu met
public function __construct ($oDb, $rResult) {
$this->_oDb = $oDb;
$this->_rResult = $rResult;
}

et là dans ton next tu met un
$this->_aCurrentArray = $this->_oDb->get_array($rResultat);

et dans ton current
return $this->_aCurrentArray

essaye voir :)

http://www.ReFlectiv.Net
0
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
18 juil. 2008 à 10:16
j'ai une page blanche !!! tu me diras c'est bien, il y a plus d'erreurs... et ne passe plus par NewsObject

voici la class NewsIterator

class NewsIterator implements Iterator {
   
    private $Db;
    private $Resultat =  array();
    private $actuCurrentArray;
   
    //constructeur  
    public function __construct ($Db, $Resultat) {
        $this->Db = $Db;
        if (is_array($Resultat) { $this->Resultat = $Resultat; }
    }
  
   public function rewind() {
   }

   public function current() {
        return $this->actuCurrentArray;
   }
   
   public function key() {
   }
   
   public function next() {
        $this->actuCurrentArray = $this->Db->get_array($this->Resultat);
   }
   
   public function valid() {
    }
}

je sais pas si c'est bon, le truc c'est que si je fais un echo dans le constructeur de NewsIterator, je devrais avoir affiché le message 3 fois non ?! parce que j'ai q'un message qui s'affiche....

je suis vraiment paumé !!!
0
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
18 juil. 2008 à 10:19
quand j'appel la class depuis l'exterieur, je fais ça :

//connexion MySQL
$Bdd = Mysql::singleton();
if(!$link = $Bdd->connect('localhost', 'root', '', 'test'))
die( $Bdd->return_error() );

//Appel des news
$NewsFactory = new NewsFactory($link);
$news = $NewsFactory->GetMultipleNews(0,3);

    foreach ($news as $key => $value) {
        echo "$key => $value
";
    }

c'est bon ou pas ???????????
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
18 juil. 2008 à 11:05
$Resultat ca ne devraitp as etre un tableau mais une resource normallement.
La resource générée par la requete effectuée.

Ton tableau, tu devrait le voir trois fois dans la fonction next

   public function next() {
        $this->actuCurrentArray = $this->Db->get_array($this->Resultat);
        var_dump ( $this->actuCurrentArray);
   }

http://www.ReFlectiv.Net
0
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
18 juil. 2008 à 11:27
pardon pour l'erreur, effectivement $Resultat est une ressource mysql.

cependant, je reste avec une page blanche, j'essaye d'effectuer une trace de passage dans next et j'y rentre pas ! je pense que la classe NewsIterator est fausse... (je déprime)

j'ai essayé un truc du genre dans le return du GetMultipleNews

public $output = array(); // propriété de la class NewsFactory

while ($data = $this->db->get_array($resultat) ) {
     $this->output[] = $data;
}
       
return $this->output;

du coup lorsque je l'instancie :

    $NewsFactory = new NewsFactory($link);
    $news = $NewsFactory->GetMultipleNews(0,3);
    echo ""; var_dump($news); echo "

";

je retrouve bien mes trois news. (idem sur un print_r)

par contre je suis obligé de faire un foreach imbriqué :

    foreach($news as $key=>$value) {
        foreach($value as $key2=>$valeur) {
            echo "$key2 : $valeur
";
        }
    }

je trouve que ça pue un peu ce truc ! j'aimerai vraiment passé par NewsObject !

tu en penses quoi ? devrais-je bataillé avec les itérateurs ?

ps : (( en tout cas je te remercie de me consacrer de ton temps et de ton experience, j'avance vraiment. Merci ))
0
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
18 juil. 2008 à 11:41
bon j'ai parlé trop vite, en faite pour pouvoir utiliser NewsObject il faut faire une truc du genre dans le return de GetMultipleNews

while ($data = $this->db->get_array($resultat) ) {
    $this->output[] = $this->{$this->option['sortie']}($data);
}
       
return $this->output;

du coup on peut conserver la méthode de sortie et $this->output devient une sorte de collection d'objet (d'où l'utilisation des itérateurs...)

en utilisation cela donne : (je veux récuperer le titre des news par exemple)

    $NewsFactory = new NewsFactory($link);
    $news = $NewsFactory->GetMultipleNews(0,3);

    foreach($news as $value) { //$value est un objet NewsObject
        echo stripslashes($value->titre).'
';
    }

Ce qui donne en rendu XHTML :

Une troisième actu
Une deuxième actu
Une première actu

voili voilou, je suis preneur d'une solution avec les itérateurs.

Merci à CodeFalse pour sa précieuse aide et son savoir.

Nico
0
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
18 juil. 2008 à 11:42
je vais maintenant testé et bataillé avec les autres méthodes et vous tiens vite au courant !

Nico
0
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
18 juil. 2008 à 12:26
Tu passe dans next quand tu fait un foreach, tu a bien fait un foreach ?

parce que normallement tu passe ton objet et ta ressource à ton itérateur, et tu fait un foreach sur ton objet, ca devrait marcher :

$tonNewsIterator = $tonObj->getAllNews (0, 3);

foreach ($tonNewsIterator as $oValue) {
// $oValue sera une instance de NewsObject
// car dans ton next tu aura fait un $this->_aCurrentObject = new NewsObject ($this->_oDb->get_array ($this->_rResult));
// donc :
echo $oValue->titre;
}

Tu vois ou je veux en venir ?

http://www.ReFlectiv.Net
0
acidline Messages postés 21 Date d'inscription vendredi 9 décembre 2005 Statut Membre Dernière intervention 21 juillet 2008 1
18 juil. 2008 à 14:28
je dois vraiment déconné grave car j'arrive à rien avec les Itérateurs

Je résume, dis moi là ou ça déconne :

La méthode GetMultipleNews
public function GetMultipleNews($start, $limit) {
    $requete = 'SELECT id, titre, contenu, dateInsertion,dateModification
                      FROM actualites WHERE publication="1" ORDER BY id DESC LIMIT '.$start.', '.$limit;

    $resultat = $this->db->Send_Query($requete, $this->linkBDD);
    return new NewsIterator($this->db, $resultat);
}

La class NewsIterator
class NewsIterator implements Iterator{

    private $Db;
    private $Resultat =  array();
    private $actuCurrentArray;

    public function __construct ($Db, $Resultat) {
        $this->Db = $Db;
        if(is_array($Resultat) { $this->Resultat = $Resultat; }
    }
   
    public function rewind() { }

    public function current() {
        return $this->actuCurrentArray;
    }
   
    public function key() { }
   
    public function next() {
        $this->actuCurrentArray = new NewsObject( $this->Db->get_array($this->Resultat) );
     }
   
    public function valid() {}
}

L'utilisation :

try {

    $NewsFactory = new NewsFactory($link); //$link est défini plus haut
    $news = $NewsFactory->GetMultipleNews(0,3);
 
    foreach ($news as $oValue) {
        echo $oValue->titre."
";
    }

} catch(Exception $e) {
    echo $e->getMessage();
}

Ma class NewsIterator doit surement merdée (et je pense que c'est le mot ! )

Pour info $news est bien un "object(NewsIterator)"

Et  "["Resultat:private"]=> resource(7) of type (mysql result)" ==> bien
      "["actuCurrentArray:private"]=>NULL ==> pas bien

va vraiment falloir que je potasse serieux SPL...
0
Rejoignez-nous