Maniement Objet

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Maniement Objet

Re: Maniement Objet

par soycd » 15 oct. 2011, 16:15

Le fetch s'applique sur le query, pas sur la connexion :wink:

Re: Maniement Objet

par Snoops » 15 oct. 2011, 14:12

Bonjour messieurs,

J'ai mis du temps à revenir, mais c'était le temps de me familiariser un peu plus à PDO / Singleton / ... :twisted:
Déjà, merci de m'avoir mit sur cette voie, je pense effectivement que c'est exactement ce qu'il me fallait !!!

Ensuite, effectivement, j'avais inversé "mot de passe" / "utilisateur" ... ca ne pouvait forcément pas fonctionner ! :oops:

Et enfin, je reviens forcément avec au moins une question :P
Je vous copie d'abord mon code actuel, puis je la pose :

Ma nouvelle classe Connexion()
class Connexion {

	private static $instance = null;

	public static function getInstance()
	{
		if (is_null (self::$instance))
		{
			self::$instance = new Connexion();
		}
		return self::$instance;
	}

	private $connexion = null;
	const DB_HOST = "*******";
	const DB_USER = "*******";
	const DB_PASS = "*******";
	const DB_NAME = "******";
	
	function __construct ()
	{
		try {
			$this->connexion = new PDO ('mysql:host='.self::DB_HOST.';dbname='.self::DB_NAME, self::DB_USER, self::DB_PASS);
		} catch (PDOException $e) {
			echo 'Connexion échouée : ' . $e->getMessage();
		}
	}

	public function __get($property)
	{
		if (array_key_exists ($property, get_class_vars(__CLASS__)))
			return $this->$property;
		else
			die($property." est introuvable. Affichage impossible.");
	}
	
	public function __set($property, $value)
	{
		if (array_key_exists ($property, get_class_vars(__CLASS__)))
			$this->$property = $value;
		else
			die($property." est introuvable. Mise à jour impossible.");
	}

	public function prepare ($query)
	{
		return $this->connexion->prepare ($query);
	}

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

	public function exec($query)
	{
		return $this->connexion->exec ($query);
	}

	public function num_rows()
	{
		$count = 0;
		while ($row = $this->fetch())
			$count++;
		return $count;
	}

	public function fetch()
	{
		return $this->connexion->fetch (PDO::FETCH_BOTH);
	}

	public function show ()
	{
		echo "Connexion : <PRE>";
		print_r ($this->connexion);
		echo "</PRE><br/>";
		echo "BDD : ".self::DB_NAME."<br/>";
		echo "Host : ".self::DB_HOST."<br/>";
		echo "User : ".self::DB_USER."<br/>";
		echo "Mdp : ".self::DB_PASS."<br/>";
	}
}
Ma classe CategorieDAO()
require_once ("./class/connexion.class");

$sname = session_name ("toto");
if (!isset ($_COOKIE[ini_get('toto')]))
	session_start();

require_once ("./class/categories.class");
require_once ("./class/collection.class");


class CategorieDAO
{
	function __construct()
	{
	}

	public function GetMenu($menus = NULL, $categories = NULL)
	{
		$query_menu = "";
		if (is_null($menu))
			$query_menu = " WHERE id_menu != 0";
		if (is_array($menu))
		{
			$query_menu = " WHERE id_menu IN (";
			$tab_menus = "";
			for ($i = 0; $i < count($menu); $i++)
			{
				if ($tab_menus != "")
					$tab_menus .= ", ";
				$tab_menus .= $menu[$i];
			}
			$query_menu = ")";
		}
		if (!is_null($menu) && !is_array($menu))
			$query_menu = " WHERE id_menu = ".$menu;

		$query = "SELECT * FROM `Categories`".$query_menu.";";
		echo $query;
		Connexion::getInstance()->prepare($query);
		$collec = ($categories == NULL) ? new Collection () : $categories;

		foreach ($row = Connexion::getInstance()->fetch())
		{
			$cat = new Categorie ($row[0], $row[1], $row[2], $row[3]);
			$collec->addorUpdate($cat);
		}

		return $collec;
	}

	public function isMenu($menu)
	{
		$query = "SELECT * FROM `Categories` WHERE id_menu = ".$menu.";";
		echo $query;
		Connexion::getInstance()->prepare($query);
		return Connexion::getInstance()->num_rows();
		// return (Connexion::getInstance()->exec($query) == 1) ? true : false;
	}

	public function __get($property)
	{
		if (array_key_exists($property,get_class_vars(__CLASS__)))
			return $this->$property;
		else
			die("<p>Método Getter inexistente da classe ".__CLASS__."<br>");
	}
	
	public function __set($property, $value)
	{
		if (array_key_exists($property, get_class_vars(__CLASS__)))
			$this->$property = $value;
		else
			die("Método Setter inexistente da classe ".__CLASS__."<br>");
	}

	public function __isset ($name) {
		return isset ($this->data[$name]);
	}

	public function __unset ($name) {
		unset ($this->data[$name]);
	}
	
	public function show ()
	{
		echo $this->id." / ".$this->libelle." / ".$this->menu." / ".$this->id_parent;
	}
	
	public function search ($property, $value)
	{
		if (array_key_exists ($property, get_class_vars(__CLASS__)))
			if ($this->$property == $value)
				return 1;
		return 0;
	}
}
Je ne remet pas en copie Collection() et Categorie(), elles sont en haut et n'ont pas ou peu évoluées ...

Et enfin ma page qui me sert à tester le maniement de l'objet :
require_once ("./class/categories.class");
require_once ("./class/collection.class");
require_once ("./class/connexion.class");
require_once ("./class/categoriesDAO.class");

$sname = session_name ("toto");
if (!isset ($_COOKIE[ini_get('toto')]))
	session_start();

$menu = isset ($_GET['menu']) ? $_GET['menu'] : NULL;
$categories = isset ($_SESSION['categories']) ? $_SESSION['categories'] : new Collection ();

if ($menu == NULL)
{
	echo "menu is null";
	// header ("Location: http://*********.com/");
	// exit;
}

$cats = new CategorieDAO();

$is_menu = $cats->isMenu($menu);
echo $is_menu;
if (!$is_menu)
{
	echo "is_menu is null";
	// header ("Location: http://********.com/");
	// exit;
}
$cats->GetMenu($menu, &$categories);

$categories->rewind();

do
{
	echo $categories->current()->show()."<br/>";
} while ($categories->next());

Et voici donc la dite question :
Lorsque j'exécute mon fetch(), j'ai l'erreur suivante :

Code : Tout sélectionner

Fatal error: Call to undefined method PDO::fetch() in /homez.420/latiendan/www/recette/class/connexion.class on line 72
Je suis évidemment sur que c'est une erreur de ma part, car la fonction existe bien ...
J'espère juste qu'elle n'est pas aussi bête que mes 2 précédentes !

Et perso, je ne sais plus quoi regarder car :
- La fonction est valable depuis PHP 5.1.0 => le serveur est en 5.2.x
- Il faut avoir un PDOStatement => j'ai bien un Connexion::getInstance()->prepare($query); juste avant ... de plus l'erreur aurait été différente (...on a non-object...)
- J'ai essayé avec ou sans le paramètre facultatif PDO::FETCH_BOTH => même résultat

J'avoue que je place mes espoirs en vous là :oops:

Merci d'avance !!!

La fonction num_rows() est là uniquement pour me faire tester les différentes fonctions de PDO car sinon biensur je fais juste un count(*) dans ma requete et c'est plié.

Re: Maniement Objet

par moogli » 08 oct. 2011, 19:42

Pour le singleton t'a une définition par la => http://en.wikipedia.org/wiki/Singleton_pattern les principe est le même que partout a priori. L'article c'est des exemple java mais c'est pas bien différent de php.

et la un exemple de multiton en php

et oui : SQLSTATE[28000] [1045] Access denied for user 'User'@'IP' (using password: YES) c'est utilisateur / mot de passe pas bon t'a du mal recopier :)

après tu peux garder ton objet collection en session si tu ne veux pas refaire la recherche depuis la base a chaque affichage de page.
l'objet d'accès au sgbd n'a pas forcément à être en session sachant qu'a la fin du script la connexion est automatiquement fermé ;)

d'ailleurs l'accès persistant est souvent désactivé et peu utile dans ton cas étant donné que la connexion ne va être faite, au max, que 30s :)

@+

Re: Maniement Objet

par soycd » 08 oct. 2011, 18:06

Bah il est dispo le driver mysql là.

T'as juste mis de mauvais identifiants pour ta connexion.

Re: Maniement Objet

par Snoops » 08 oct. 2011, 17:27

Moogli, j'ai commencé à lire un peu PDO, et j'ai fait un premier test de connexion à une BDD pour voir
try {
	$dbh = new PDO ('mysql:host='.$host.';dbname='.$db, $user, $pass, array(PDO::ATTR_PERSISTENT => true));
} catch (PDOException $e) {
    print "Erreur !: " . $e->getMessage() . "<br/>";
    die();
}
Et voici l'info retournée par le browser :

Code : Tout sélectionner

Erreur !: SQLSTATE[28000] [1045] Access denied for user 'User'@'IP' (using password: YES)
Je suis parti voir la conf du serveur (chez OVH) :

Code : Tout sélectionner

PDO PDO support enabled PDO drivers sqlite, mysql, sqlite2 pdo_mysql PDO Driver for MySQL, client library version 5.0.32 pdo_sqlite PDO Driver for SQLite 3.x enabled PECL Module version (bundled) 1.0.1 $Id: pdo_sqlite.c 293036 2010-01-03 09:23:27Z sebastian $ SQLite Library 3.3.7
Et en gros, si je comprends bien, je peux pas l'utiliser en mysql car pas de driver installé ?

Ou j'ai rien compris sur toute la ligne ??? :P

Re: Maniement Objet

par Snoops » 08 oct. 2011, 17:10

tu pourrais étendre ta classe CategorieDAO de PDO ce qui fait que n'a pas besoin de garder en session un objet (je suppose que l'utilise comme variable globale ?).
Bah comme je t'ai dis je ne connais pas du tout PDO et du coup je comprends carrément pas le "pas besoin de garder un objet en session" :P
Je vois pas comment d'une page à l'autre garder tes valeurs, ou alors effectivement sur chaque page tu recrées ton objet depuis la bdd et tu le sauvegardes en bdd a la fin de chaque script ...
bref, je vais pas plus en parler tant que je n'ai pas lu un minimum d'informations sur PDO.
si tu a plusieurs objets qui utilise la base de donnée et que tu souhaite ne faire qu'une seule connexion au sgbd tu peux implémenter un singleton pour PDO ;)
Tiens j'ai un collègue qui m'a parlé récemment de singleton (mais lui n'y connais pas grand chose en php et ne savait pas si c'était possible ou pas ...), je vais me pencher la dessus aussi alors
function CategorieDAO() ça c'est => function __construct() bon c'est pinailler mais c'est plus claire :)
Oui je sais, je comptais les changer, parce que sur connexion(), j'ai un soucis
Quand je fais un new Connexion($host, $user, $pass) ... il me sauvegarde pas mes valeurs dans l'objet ...
Je suis obligé de refaire un set() derrière :(
Donc je voulais changer déjà ça pour voir si ça faisait évoluer mon schmilblik ou pas ...
enfin pas collection d'ailleurs c'est parce que c'est mis dans la doc ?
Pas compris, désolé :oops:
voila après je ne pige pas pourquoi categorie et catégorieDAO mais bon j'suis pas super fort en design d'application ^^
Vu avec ce dit collègue qui manie l'objet 1000 fois mieux que moi et qui m'a expliqué que pour ordonner le code, il était préférable de séparer le coté objet du coté accès BDD ...

Re: Maniement Objet

par moogli » 08 oct. 2011, 16:31

Ah si, peut etre une dernière question, vous qui devez avoir un oeil beaucoup plus avisé que moi en PHP Objet, a part le PDO, vous voyez d'autres choses que je ne fais pas de facon optimale ?
optimal je ne sais pas et cela dépend du fonctionnement globale de ton applis, mais par exemple tu pourrais étendre ta classe CategorieDAO de PDO ce qui fait que n'a pas besoin de garder en session un objet (je suppose que l'utilise comme variable globale ?).

si tu a plusieurs objets qui utilise la base de donnée et que tu souhaite ne faire qu'une seule connexion au sgbd tu peux implémenter un singleton pour PDO ;)

dans cette même classe tu peux éviter le mélange poo php4 et php 5 :)
function CategorieDAO() ça c'est => function __construct() bon c'est pinailler mais c'est plus claire :)

idem pour toute tes classes en fait (enfin pas collection d'ailleurs c'est parce que c'est mis dans la doc ?)

voila après je ne pige pas pourquoi categorie et catégorieDAO mais bon j'suis pas super fort en design d'application ^^


@+

Re: Maniement Objet

par Snoops » 08 oct. 2011, 15:31

Yop,

dans le code donnée tu n'implemte pas la méthode current() vu que tu implémente l'interface je suppose que c'est faire quelque part ? (sinon erreur => Class Collection contains 5 abstract methods and must therefore be declared abstract or implement the remaining methods (Iterator::current, Iterator::next, Iterator::key, ...)).
En fait si, je l'implemente, mais je voulais pas "trop" charger le post de code, donc j'ai mis "..." pour dire qu'il y avait d'autres fonctions ...
Mais comme me l'a fait remarqué popy, j'ai oublié le "()" de ma fonction current() comme un imbécile (on mettra ca sur le dos de la fatigue au boulot :P )
Tu peux remplacer ta classe connexion par PDO
ca fait déjà 2 fois que j'entends parler de PDO ... Je vais aller m'informer sur le sujet !

Merci encore à vous deux !
Et désolé pour le dérangement du coup :-(

Ah si, peut etre une dernière question, vous qui devez avoir un oeil beaucoup plus avisé que moi en PHP Objet, a part le PDO, vous voyez d'autres choses que je ne fais pas de facon optimale ?

Dorian

Re: Maniement Objet

par Snoops » 08 oct. 2011, 15:27

$menus->current() ->show(); à la place de $menus->current->show(); ?
Je suis un boulet :-(
c'était ca mon erreur de débutant !!! :oops:

Merci 100 fois !

Re: Maniement Objet

par moogli » 07 oct. 2011, 23:30

Yop,

dans le code donnée tu n'implemte pas la méthode current() vu que tu implémente l'interface je suppose que c'est faire quelque part ? (sinon erreur => Class Collection contains 5 abstract methods and must therefore be declared abstract or implement the remaining methods (Iterator::current, Iterator::next, Iterator::key, ...)).

Tu peux remplacer ta classe connexion par PDO

Perso je viens de tester
<?php

class Collection implements Iterator
{
    private $var = array();
    private $position;

    public function __construct($array = "") {
        $this->position = 0;
        if (is_array($array))
                        $this->var = $array;
    }

    public function add($object) {
        $this->var[count($this->var)] = $object;
    }
    public function rewind() {
        $this->position = 0;
    }

    public function current() {
        return $this->var[$this->position];
    }

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

    public function next() {
        ++$this->position;
    }
    public function valid() {
        return isset($this->var[$this->position]);
    }
    
}
class Categorie
{
        private $id;
        private $libelle;
        private $menu;
        private $id_parent;

        function Categorie ($id, $libelle, $menu, $id_p)
        {
                $this->id = $id;
                $this->libelle = $libelle;
                $this->menu = $menu;
                $this->id_parent = $id_p;
        }

        public function __get ($property)
        {
                if (array_key_exists ($property, get_class_vars(__CLASS__)))
                        return $this->$property;
                else
                        die($property." est introuvable. Affichage impossible.");
        }
       
        public function __set ($property, $value)
        {
                if (array_key_exists ($property, get_class_vars(__CLASS__)))
                        $this->$property = $value;
                else
                        die($property." est introuvable. Mise à jour impossible.");
        }
       
        public function show ()
        {
                echo $this->id." / ".$this->libelle." / ".$this->menu." / ".$this->id_parent;
        }
}
class Connexion {

        private $connexion;
        private $bdd;
        private $host;
        private $user;
        private $mdp;
       
        function Connexion ($host = NULL, $user = NULL, $mdp = NULL, $bdd = NULL)
        {
                $this->host = $host;
                $this->user = $user;
                $this->mdp = $mdp;
                $this->bdd = $bdd;
        }

        public function open ()
        {
                $this->connexion = mysql_connect($this->host, $this->user, $this->mdp) or die ("Impossible de se connecter au serveur : " . mysql_error());
                $this->select_db();
                return true;
        }
        public function exec($q ) {
            return mysql_query($q);
        }
        public function fetch($r,$type='row'){
            switch ($type) {
                case 'assoc':
                    $x =mysql_fetch_assoc($r);
                    break;
                case 'object':
                    $x = mysql_fetch_object($r);
                    break;
                case 'row'  :
                default     :
                    $x = mysql_fetch_row($r);
                    break;
            }
            return $x;
        }
        public function select_db(){
            mysql_select_db($this->bdd);
        }
        public function close(){
            mysql_close();
        }
}

class CategorieDAO
{
        private $connexion;

        function CategorieDAO()
        {
                if (isset ($_SESSION['c']))
                        $this->connexion = $_SESSION['c'];
                else
                        die ("Vous n'etes pas connectes a la BDD.");
        }

        public function GetMenu()
        {
                $this->connexion->open();

                $query = "SELECT * FROM `Categories`";// WHERE id_categorie = id_parent;
                $result = $this->connexion->exec($query);
                $collec = new Collection ();

                while ($row = $this->connexion->fetch($result))
                {
                        $cat = new Categorie ($row[0], $row[1], $row[2], $row[3]);
                        $collec->add($cat);
                }

                $this->connexion->close();

                return $collec;
        }
}

$c = new Connexion ('localhost', 'root', 'mdp', 'test');

$_SESSION['c'] = $c;

$categories= new CategorieDAO();
$menus = $categories->GetMenu();
// $menu est un objet collection (qui contient des objets categorie)
while ($menus->valid()!== false){
    $menus->current()->show();
    echo '<hr />';
    $menus->next();
}
$menus->rewind();
echo '<h1>Apr&egrave;s un rewind</h1>';
while ($menus->valid()!== false){
    $menus->current()->show();
    echo '<hr />';
    $menus->next();
}
?>
en ajoutant les méthodes manquantes dans les classes il n'y a aucun problème.
1 / test / menu / 0<hr />
2 / test1 / menu1 / 0<hr />
3 / test2 / menu2 / 0<hr />
4 / ceci est un libelle / ceci est un menu / 0<hr />
<h1>Apr&egrave;s un rewind</h1>
1 / test / menu / 0<hr />
2 / test1 / menu1 / 0<hr />
3 / test2 / menu2 / 0<hr />
4 / ceci est un libelle / ceci est un menu / 0<hr />
A tu bien toute les méthodes ?
edit : Ce qui suis est une ânerie (dans le sens de la réponse de popy pas sur la réalité de la chose ^^), j'ai mal pigé ce que voulais dire popy, heu donc dsl popy :/
$menus->current() ->show(); à la place de $menus->current->show(); ?
nan nan $menu est un objet "collection" qui implemente l'interface iterator et ces objet doivent avoir une methode current().

Étant donné que l'objet collection contient des objets "categories" qui eux on une méthode show() donc $iterateur->current()->show() ;)

j'ai aussi du mal avec type de comportement, je prend cela comme l'interprétation direct du return.
au lieu de
$x = $iterateur->current();
$x-> show();
on fait $iterateur->current()->show();
car current est définit ainsi
function current() {
return $this->array[$this->position];
}

(par exemple :) )

@+

Re: Maniement Objet

par popy » 07 oct. 2011, 17:19

$menus->current() ->show(); à la place de $menus->current->show(); ?

Maniement Objet

par Snoops » 07 oct. 2011, 16:59

Bonjour tout le monde,

Voilà, je débute dans l'objet PHP (j'ai fais de l'objet en Java / C#, et du PHP pointeur, mais pas d'objet PHP) et j'ai quelques difficultés à m'adapter :(
Alors voilà ce que j'essaye de faire :
J'ai des classes d'objets, et une classe qui gérera des "collections" d'objets sous forme de tableau.
class Collection implements Iterator
{
    private $var = array();

    public function __construct($array = "") {
        if (is_array($array))
			$this->var = $array;
    }

    public function add($object) {
        $this->var[count($this->var)] = $object;
    }
    ...
}
class Categorie
{
	private $id;
	private $libelle;
	private $menu;
	private $id_parent;

	function Categorie ($id, $libelle, $menu, $id_p)
	{
		$this->id = $id;
		$this->libelle = $libelle;
		$this->menu = $menu;
		$this->id_parent = $id_p;
	}

	public function __get ($property)
	{
		if (array_key_exists ($property, get_class_vars(__CLASS__)))
			return $this->$property;
		else
			die($property." est introuvable. Affichage impossible.");
	}
	
	public function __set ($property, $value)
	{
		if (array_key_exists ($property, get_class_vars(__CLASS__)))
			$this->$property = $value;
		else
			die($property." est introuvable. Mise à jour impossible.");
	}
	
	public function show ()
	{
		echo $this->id." / ".$this->libelle." / ".$this->menu." / ".$this->id_parent;
	}
	...
}
J'ai aussi une classe qui gère ma connexion à la BDD
class Connexion {

	private $connexion;
	private $bdd;
	private $host;
	private $user;
	private $mdp;
	
	function Connexion ($host = NULL, $user = NULL, $mdp = NULL, $bdd = NULL)
	{
		$this->host = $host;
		$this->user = $user;
		$this->mdp = $mdp;
		$this->bdd = $bdd;
	}

	public function open ()
	{
		$this->connexion = mysql_connect($this->host, $this->user, $this->mdp) or die ("Impossible de se connecter au serveur : " . mysql_error());
		$this->select_db();
		return true;
	}
	...
}
Ainsi des classes DAO pour chaque objet : (question : on ne peut pas utiliser de template en PHP vu que faiblement typé ?)
class CategorieDAO
{
	private $connexion;

	function CategorieDAO()
	{
		if (isset ($_SESSION['c']))
			$this->connexion = $_SESSION['c'];
		else
			die ("Vous n'etes pas connectes a la BDD.");
	}

	public function GetMenu()
	{
		$this->connexion->open();

		$query = "SELECT * FROM `Categories` WHERE id_categorie = id_parent;";
		$result = $this->connexion->exec($query);
		$collec = new Collection ();

		while ($row = $this->connexion->fetch($result))
		{
			$cat = new Categorie ($row[0], $row[1], $row[2], $row[3]);
			$collec->add($cat);
		}

		$this->connexion->close();

		return $collec;
	}
	...
}
Et ma page index où j'essaye de manipuler un peu tout ça pour mieux controler et comprendre le fonctionnement :
$c = new Connexion ($HOST, $USER, $PASS, $DB);

$_SESSION['c'] = $c;

$categories= new CategorieDAO();
$menus = $categories->GetMenu();
Jusque là, aucun problème !

Par contre, lorsque je souhaite afficher mes objets "Categorie" dans ma collection $menus avec la fonction show() ... ca plante :
$menus->rewind();

do
{
	echo $menus->current->show();
	echo "<br/>";
} while ($menus->next());
L'erreur :

Code : Tout sélectionner

Fatal error: Call to a member function show() on a non-object in /homez.420/latiendan/www/recette/index.php on line 30
Pourtant, si avant mon rewind() je fais un print_r(), j'ai bien mon contenu :

Code : Tout sélectionner

Collection Object ( [var:private] => Array ( [0] => Categorie Object ( [id:private] => 1 [libelle:private] => Chicky Robes [menu:private] => 1 [id_parent:private] => 1 ) [1] => Categorie Object ( [id:private] => 2 [libelle:private] => Prêt à porter [menu:private] => 2 [id_parent:private] => 2 ) ...
Pourriez-vous m'aiguiller sur l'erreur que je commets SVP ?

Merci beaucoup d'avance !
Dorian