Page 1 sur 1
Passage de php4 à 5, tableau d'objet ne fonctionne plus
Posté : 22 mai 2007, 10:46
par bubu666
Bonjour,
J'ai un de mes site qui vient de migrer d'un serveur php4 sous php5. Désormais j'ai un petit problème avec mes objets.
Objet : (je réalise une requete et je stocke le résultat dans un tableau que je retourne)
<?php
<?
class Item {
var $idItem;
var $nom;
var $descriptif;
function loadItem() {
$sql = "SELECT idItem, nom, descriptif FROM item ORDER BY idItem ASC LIMIT 2";
$req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());
while($data = mysql_fetch_assoc($req)){
$this->idItem = $data['idItem'];
$this->nom = $data['nom'];
$this->descriptif = $data['descriptif'];
$t[] = $this;
}
return $t;
}
}
?>
Lorsque je realise une print_r sur le tableau qui m'est retourné les deux enregistrements de mon tableaux sont identiques. Autrement dit, il contient 1 seul item en double alors que lorsque je fait un print_r sur $this dans ma classe à cette ligne :
print_r($this);
$t[] = $this;
Il me sort bien 2 items différents. C'est un peu comme si à chaque nouvel enregistrement dans ma table $t, ce dernier m'écrase tout les précédents.
Je ne sais pas si j'ai été très clair. Merci pour votre aide.
Yohann
Posté : 22 mai 2007, 11:12
par titerm
Tu affecte a un tableau la référence de l'objet. Tu le fais dans une boucle while, donc au final, tu auras autant de référence au meme objet que d'itération dans ta boucle.
Si tu veux retourner un tableau d'objet, il faut faire un new au debut du while, mettre a jours les properties, et affecter cette nouvelle instance a ton tableau.
Posté : 22 mai 2007, 11:32
par bubu666
Comme çà ? :
Code : Tout sélectionner
while($data = mysql_fetch_assoc($req)){
$item = new Item;
$item->idItem = $data['idItem'];
$item->nom = $data['nom'];
$item->descriptif = $data['descriptif'];
$t[] = $item;
}
Posté : 22 mai 2007, 11:39
par bubu666
En effet ça fonctionne, franchement un grand merci pour cette reponse claire et rapide.
Yohann
Posté : 22 mai 2007, 11:40
par naholyr
Pour la pédagogie je me permets cet intérmède : Pour que tu comprennes bien la nuance (par référence, par valeur, implicite en objet) mets-toi à la place de l'objet, et exécute ton code, voici ce qui se passe :
- Je fais une requête
- Je parcours une ligne
- Je change mes attributs selon cette ligne
- Je m'ajoute dans un tableau
- Je parcours une autre ligne
- Je rechange mes attributs
- Je m'ajoute à nouveau dans le tableau
etc...
C'est toujours le même "Je" qui s'ajoute au tableau, donc quand "Je" change mes attributs, évidemment que c'est valable pour "Moi" partout (donc aussi dans les tableaux ou je me suis ajouté).
PHP4 permettait ce type d'hérésie ce n'est dieu merci plus possible en PHP5.
Et sinon oui ta correction est bonne, tu peux d'ailleurs du coup appeler "loadItem()" en statique : $tableau = Item::loadItem() qui te renvoie une liste d'Item instanciés correctement.
Edit : owned
Posté : 22 mai 2007, 11:51
par bubu666
Ah ok, je comprend pouquoi ça ne fonctionnait pas. Du coup il faudrait programmé comme ça dorenavant même si je suis sous php4 en fait.
Ca me parait juste un peu bizzare de devoir instancier une classe dans laquelle je me trouve et dans une boucle while en plus, mais bon.
Posté : 22 mai 2007, 15:58
par titerm
une autre possibilité est d'utiliser clone lors de l'affectation dans le tableau pour dupliquer l'instance.
ton code du debut +
$t[] = clone $this;
Posté : 22 mai 2007, 16:29
par bubu666
Une solution moins lourde pour php au lieu de devoir instancier plusieurs fois la même classe?
Posté : 22 mai 2007, 16:57
par Sékiltoyai
Une classe est théoriquement faite pour être instanciée plusieures fois. A la base c'est pour cela que la POO a été inventée...
Posté : 22 mai 2007, 19:18
par titerm
Non, c'est juste une facon différente de faire une instanciation. Clone créé une nouvelle instance à partir d'une instance déjà existante. La seule différence, c'est que la methode __clone peut etre surchargé de facon a gérer le 'clonage' d'une facon spécifique. Cela peut éviter d'avoir a initialiser plusieurs fois avec les memes valeurs un objet, un clonage étant plus performant qu'un new suivi de n acces a des propriétés.
Posté : 22 mai 2007, 22:41
par Sékiltoyai
Cela peut éviter d'avoir a initialiser plusieurs fois avec les memes valeurs un objet
Je ne sais pas si php gère le clonage de la même manière qu'en java, mais en l'occurence, en java, le clonage est une copie superficielle, c'est à dire que s'il y a des objets ou des tableaux dans la classe, l'adresse des objets est recopiée, donc les objets à l'intérieur d'une classe ne sont pas cloné (le clonage n'est pas récursif). La redéfinition de la méthode clone() permet donc de faire une copie plus profonde, et à mon avis, c'est la même chose en php, puisque ca m'étonnerait que les développeurs se soient faits chier à implémenter un cloange récursif...
Posté : 22 mai 2007, 23:35
par titerm
Oui, le clonage fonctionne de la meme facon en php qu'en java, d'où l'existance de __clone si tu veux pouvoir cloner un object complexe, ce qui ne semble pas etre le cas dans le cas présent.
Posté : 23 mai 2007, 09:52
par bubu666
Ok merci pour toutes ces infos, donc vous passeriez par un clone plutot que de reinstancier la classe via un new?
C'est que je débute la refonte d'un site complet e-commerce qui est à la base en perl et que j'aimerais que ce soit un minimum propre.
Ent tout cas, je ne trouve aucune trace de clone dans le manuel php (php.net)
Merci.
Posté : 23 mai 2007, 11:23
par titerm
Clone est un mot clé, pas une fonction, il faut donc regarder dans la doc php, pas dans la doc des fonctions.
Doc clone
Clone était plus pour ton info personel, ca pouvait répondre rapidement a ton besoin de portage.
Dans le cadre d'une appli a réécrire, je ferais un objet basique dédié pour les propriétés et je dériverai cette objet pour ajouter les fonctions. Dans ton objet basique, prévoit un constructeur qui te permettent d'initialiser tes 3 propriétés.
Tu peux meme faire un objet Item basique et dérivé vers un arrayItem en implémentant l'interface
ArrayAccess de facon a pourvoir faire des foreach sur ton objet. Bref, il y a autant de facon de faire que de developper
