Précédent   Forum des professionnels en informatique > PHP > Langage > Formulaires
Formulaires Forum d'entraide sur les formulaires avec PHP. Avant de poster -> FAQ formulaires, Cours de formulaires et Sources de formulaires
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 05/12/2011, 20h21   #1
Invité de passage
 
Inscription : février 2008
Messages : 7
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 7
Points : 2
Points : 2
Par défaut Avis/conseils/suggestions sur mon formulaire d'inscription

Bonjour,

je débute en php et souhaiterais avoir quelques conseils et suggestions concernant mon formulaire d'inscription.
J'ai quelques questions :

1. est il nécessaire d'échapper les variables issus d'un formulaire lorsque l'on utilise des requêtes préparées ? Ne serais ce pas doublon ?

2. Je n'ai pas echappé mes variables 'entier' avec intval notamment à cause de la variable code postal '$cp' ligne 17, qui est ensuite testé comme condition ligne 35 afin notamment de pouvoir obtenir le message d'erreur correspondant.
Suis je obligé de l'échapper uniquement au moment de la condition ? Car si je l'échappe avant, ma condition sera tirs validée puisque 'intval' l'aura transformée en entier meme si cette dernière est à l'origine un string ? (serais dans ce cas égal à 0)

3. N' y at'il pas moins fastidieux que le 'try' et 'catch' de PDO pour capturer les erreurs et empêcher aux membres de voir des infos stratégiques en cas d'erreur de la db ?

4. LE PLUS IMPORTANT : AVEZ VOUS DES CONSEILS, REMARQUES ET SUGGESTIONS POUR AMELIORER LA LISIBILITE, LA SECURITE ET LES BONNES PRATIQUES A UTILISER POUR M'AMELIORER ?

Merci d'avance à tous et longue vie à développez.com





Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
<?php
 
if (isset($_POST['envoyer']))
{		
	// On échappe les variables pour sécuriser
	$pseudo=mysql_real_escape_string($_POST['pseudo']);
	$password=mysql_real_escape_string($_POST['password']);
	$password_verification=mysql_real_escape_string($_POST['password_verification']);
	$email=mysql_real_escape_string($_POST['email']);
	$email_verification=mysql_real_escape_string($_POST['email_verification']);
	$genre=$_POST['genre'];
	$prenom=mysql_real_escape_string($_POST['prenom']);
	$nom=mysql_real_escape_string($_POST['nom']);
	$birthday=$_POST['birthday'];
	$adresse=mysql_real_escape_string($_POST['adresse']);
	$adresse_complement=mysql_real_escape_string($_POST['adresse_complement']);
	$cp=$_POST['cp'];
	$ville=mysql_real_escape_string($_POST['ville']);
 
	if ((!empty($email)) && (!empty($email_verification)) && (!empty($password)) && (!empty($password_verification)) && (!empty($pseudo)) && (!empty($genre)) && (!empty($prenom)) && (!empty($nom)) && (!empty($birthday)) && (!empty($adresse)) && (!empty($cp)) && (!empty($ville)))
	{
		// On vérifie que les deux mails sont identiques
		if ($email==$email_verification)
		{	
			// On vérifie que les deux mots de passe sont identiques
			if ($password==$password_verification)
			{
				// On vérifie que le format du mail est valide
				if(verifmail($email))
				{
					// On vérifie que le mot de passe soit égal ou supérieur à 6 caractères
					if((strlen($password))>=6)
					{
						// On vérifie que le code postal est un entier
						if(intval($cp))
						{
							// On vérifie que le login ne soit pas deja utilisé
							try
							{
								$pdo_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
								$bdd=new PDO('mysql:host='.$host.';dbname='.$db.'',''.$db_user.'',''.$db_password.'');
								$rep=$bdd->prepare('SELECT login FROM user WHERE login=:login');
								$rep->execute(array(
									'login'=>$pseudo));
								$resultat=$rep->fetch();
								$rep->closeCursor();
							}
							catch (Exception $e)
							{
      							die('Erreur : ' . $e->getMessage());
							}
							if($resultat['login'] != $pseudo)
							{
								// On vérifie que le mail ne soit pas deja utilisé
								try
								{
									$pdo_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
									$bdd=new PDO('mysql:host='.$host.';dbname='.$db.'',''.$db_user.'',''.$db_password.'');
									$rep=$bdd->prepare('SELECT email FROM user WHERE email=:email');
									$rep->execute(array(
										'email'=>$email));
									$resultat=$rep->fetch();
									$rep->closeCursor();
								}
								catch (Exception $e)
								{
      								die('Erreur : ' . $e->getMessage());
								}
								if($resultat['email'] != $email)
								{					
									// On ajoute l'utilisateur en base de donnée
									try
									{
										$pdo_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
										$bdd=new PDO('mysql:host='.$host.';dbname='.$db.'',''.$db_user.'',''.$db_password.'');
										$rep = $bdd->prepare('INSERT INTO user (login, password, date_signup, email, genre, prenom, nom, birthday, adresse, adresse_complement, cp, ville) VALUES(:login, :password, :date_signup, :email, :genre, :prenom, :nom, :birthday, :adresse, :adresse_complement, :cp, :ville)');														$rep->execute(array(
											'login'=> $pseudo,
											'password'=> sha1($password),
											'date_signup'=> date("Y-m-d H:i:s"),
											'email'=> $email,
											'genre'=> $genre,
											'prenom'=> $prenom,
											'nom'=> $nom,
											'birthday'=> $birthday,
											'adresse'=> $adresse,
											'adresse_complement'=> $adresse_complement,
											'cp'=> $cp,
											'ville'=> $ville));
										$rep->closeCursor();
									}
									catch (Exception $e)
									{
      									die('Erreur : ' . $e->getMessage());
									}
									$form=false;  
									echo "Votre compte a été créée"; 
 
								}
								else
								{
									$form=true;
									$error='Email déjà utilisé';
								}
							}
							else		
							{
								$form=true;
								$error='Login déjà utilisé';	
							}		
						}
						else
						{
							$form=true;
							$error='Code postal invalide';		
						}
					}
					else
					{
						$form=true;
						$error='Votre mot de passe doit comporter 6 caractères ou plus';		
					}
				}
				else
				{
					$form=true;
					$error='L\'adresse mail entrée est invalide';					
				}
			}
			else
			{
				$form=true;
				$error='Les deux mots de passe entrés sont différents.';
			}
		}
		else
		{
			$form=true;
			$error='Les deux adresses mails entrées sont différentes.';
		}	
	}
	else
	{
		$form=true;
		$error='Tous les champs sont necessaires';
	}	
}
else 
{
	$form=true;
}
 
 
if ($form)
{
	if (isset($_SESSION['login']))
	{
		redirect('?page=404');
	}
	else 
	{?>
		<h2>Créez votre compte</h2><?php 
		if (isset($error))
		{ 
			echo '<p class="alert">'.$error.'</p>';
		}?>
		<form name="inscription"  action="" method="post">
			<table>
				<tr>
					<td class="colonne_titre_champ"><label for="email">Email</label></td>
					<td class="colonne_champ"><input type="text" name="email" id="email" value="<?php echo $email ?>"></td>
				</tr>
				<tr>
					<td class="colonne_titre_champ"><label for="email_verification">Retapez votre email</label></td>
					<td class="colonne_champ"><input type="text" name="email_verification" id="email_verification" value="<?php echo $email_verification ?>"></td>
				</tr>
				<tr>
					<td class="colonne_titre_champ"><label for="password">Mot de passe</label></td>
					<td class="colonne_champ"><input type="password" name="password" id="password" value="<?php echo $password ?>"></td>
				</tr>
				<tr>
					<td class="colonne_titre_champ"><label for="password_verification">Retapez votre mot de passe</label></td>
					<td class="colonne_champ"><input type="password" name="password_verification" id="password_verification" value="<?php echo $password_verification ?>"></td>
				</tr>
			</table><br/>
 
			<table>
				<tr>
					<td class="colonne_titre_champ"><label for="pseudo">Pseudo</label></td>
					<td class="colonne_champ"><input type="text" name="pseudo" id="pseudo" value="<?php echo $pseudo ?>"></td>
				</tr>
			</table><br/>
 
			<table>		
				<tr>
					<td class="colonne_titre_champ"><label for="genre">Genre</label></td>
					<td class="colonne_champ">
						<select name="genre" id="genre">
							<option value="1">Monsieur</option>
							<option value="2">Madame</option>
						</select>
					</td>
				</tr>	
				<tr>
					<td class="colonne_titre_champ"><label for="prenom">Prénom</label></td>
					<td class="colonne_champ"><input type="text" name="prenom" id="prenom" value="<?php echo $prenom ?>"></td>
				</tr>		
				<tr>
					<td class="colonne_titre_champ"><label for="nom">Nom</label></td>
					<td class="colonne_champ"><input type="text" name="nom" id="nom" value="<?php echo $nom ?>"></td>
				</tr>	
				<tr>
					<td class="colonne_titre_champ"><label for="birthday">Date de naissance</label></td>
					<td class="colonne_champ"><input type="date" name="birthday" id="birthday" value="<?php echo $birthday ?>"></td>
				</tr>
			</table><br/>
 
			<table>		
				<tr>
					<td class="colonne_titre_champ"><label for="adresse">Adresse</label></td>
					<td class="colonne_champ"><input type="text" name="adresse" id="adresse" size="60" value="<?php echo $adresse ?>"></td>
				</tr>
				<tr>
					<td class="colonne_titre_champ"><label for="adresse_complement">Complément d'adresse</label></td>
					<td class="colonne_champ"><input type="text" name="adresse_complement" id="adresse_complement" size="60" value="<?php echo $adresse_complement ?>"></td>
				</tr>
				<tr>
					<td class="colonne_titre_champ"><label for="cp">Code Postal</label></td>
					<td class="colonne_champ"><input type="text" name="cp" id="cp" size="5" value="<?php echo $cp ?>"></td>
				</tr>
				<tr>
					<td class="colonne_titre_champ"><label for="ville">Ville</label></td>
					<td class="colonne_champ"><input type="text" name="ville" id="ville" value="<?php echo $ville ?>"></td>
				</tr>				
				<tr>
					<td colspan="2" class="boutons"><input type="submit" value="Envoyer" name="envoyer"><input type="reset" value="Annuler"></td>
				</tr>	
			</table>
		</form><?php
	}
}
?>
skhattane est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 06/12/2011, 11h23   #2
Modératrice
 
Avatar de Celira
 
Femme
Développeuse PHP/Java
Inscription : avril 2007
Messages : 3 664
Détails du profil
Informations personnelles :
Sexe : Femme
Âge : 27
Localisation : France

Informations professionnelles :
Activité : Développeuse PHP/Java

Informations forums :
Inscription : avril 2007
Messages : 3 664
Points : 5 390
Points : 5 390
Citation:
Envoyé par skhattane Voir le message
1. est il nécessaire d'échapper les variables issus d'un formulaire lorsque l'on utilise des requêtes préparées ? Ne serais ce pas doublon ?
Effectivement, normalement PDO s'occupe d'échapper les variables.

Citation:
Envoyé par skhattane Voir le message
3. N' y at'il pas moins fastidieux que le 'try' et 'catch' de PDO pour capturer les erreurs et empêcher aux membres de voir des infos stratégiques en cas d'erreur de la db ?
Ben, en théorie la gestion d'exceptions est censée faciliter la vie... je vois pas en quoi encadrer ta requête par un try/catch est plus fastidieux qu'un bon vieux or die.

Sinon au niveau structure : au lieu de faire tes tests dans des ifs imbriqués, tu peux tout tester dans des ifs successifs et renseigner un booléen $en_erreur. Ensuite, tu encadres tes requêtes avec un if qui teste ton booléen $en_erreur. (le même principe que ton booléen $form en fait)
__________________
Modératrice PHP
Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)

Pour afficher votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur)
Celira est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/12/2011, 12h13   #3
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 991
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 991
Points : 5 031
Points : 5 031
Citation:
est il nécessaire d'échapper les variables issus d'un formulaire lorsque l'on utilise des requêtes préparées ? Ne serais ce pas doublon ?
Toujours vérifier / valider / nettoyer les données à manipuler !

PDO échappe les variables mais ça ne te protège pas contre les XSS, pour ça il y a les filtres et strip_tags.

Les filtres sont un must have en qualité de sécurisation des entrées sorties (à mettre des deux cotés donc pour se prémunir des attaques).

Citation:
Je n'ai pas echappé mes variables 'entier' avec intval notamment à cause de la variable code postal '$cp' ligne 17, qui est ensuite testé comme condition ligne 35 afin notamment de pouvoir obtenir le message d'erreur correspondant.
Suis je obligé de l'échapper uniquement au moment de la condition ? Car si je l'échappe avant, ma condition sera tirs validée puisque 'intval' l'aura transformée en entier meme si cette dernière est à l'origine un string ? (serais dans ce cas égal à 0)
C'est pas bien grave, PDOStatement::bindParam ou PDOStatement::bindValue prends un paramètre qui permet de typer tes données.

Citation:
N' y at'il pas moins fastidieux que le 'try' et 'catch' de PDO pour capturer les erreurs et empêcher aux membres de voir des infos stratégiques en cas d'erreur de la db ?
Tu n'est pas obligé de spécifier l'attribut ERRMODE à Exception, en revanche, il faut systématiquement vérifier le retour de PDOStatement::execute.

Citation:
Ben, en théorie la gestion d'exceptions est censée faciliter la vie... je vois pas en quoi encadrer ta requête par un try/catch est plus fastidieux qu'un bon vieux or die.
La gestion des exception n'est pas là pour simplifier la vie du programmeur. Déjà, les exception ne sont levées par PDO que si l'attritbut ATTR_ERRMODE est à ERRMODE_EXCEPTION. Quand une exception est levée, il n'est pas forcément nécéssaire de la catcher, l'exception va remonter la pile d'appels jusqu'à la racine où elle provoquera une erreur fatale si elle n'est pas attrapée entre temps ou si l'exception handler n'est pas défini.
Une exception est par définition exceptionnelle: on ne la lance que quand il n'y a plus rien d'autre à faire. L'exemple type est le cas de comportement incorrect au niveau d'un constructeur, vu qu'il ne renvoie rien, comment notifier le bloc parent qu'il y a eu un erreur ? On lève une exception.

Dans tous les cas il faut tout vérifier et ne JAMAIS faire de "or die". Cette pratique à été introduite dans beaucoup de scripts PHP par des développeurs incompétents et malheureusement dans énormément de tutoriaux. Il y a toujours quelque chose à faire en cas d'erreur critique (à minima mettre une info dans un fichier de log avant de sortir).

Citation:
AVEZ VOUS DES CONSEILS, REMARQUES ET SUGGESTIONS POUR AMELIORER LA LISIBILITE, LA SECURITE ET LES BONNES PRATIQUES A UTILISER POUR M'AMELIORER ?
Oui:
  • ne pas mélanger PDO et mysql_*
  • utilise des modes de fetch intelligents comme FETCH_INTO ou FETCH_CLASS pour réccupérer directement des instances de modèles prêtes à l'usage
  • wrappe tes instances de PDOStatment dans des IteratorIterator afin de pouvoir y coller des FilterIterator ou des LimitIIterator qui sont des solutions paliatives aux problèmes de portabilité de SQL en PHP
  • Utilise un Singleton PDO pour éviter d'ouvrir malencontreusement plusieurs instances (ce qui est aussi inutile que dangereux la plupart du temps)
  • LIS LA DOC (je suis sérieux, trop peu de gens le font vraiment)

Note:
  • Il n'est utile d'appeller PDOStatement::closeCursor que si on récuppère plusieurs sets de donnés (par exemple avec une procédure stoquée) ce n'est pas le cas dans ton code
  • mêler le PHP au HTML est une mauvaise pratique, sépare le traitement de la mise en forme au niveau des fichers (si possible, implémente le pattern MVC)
  • toute ta séquence de vérification peut être avantageusement réduite en utilisant filter_input_array
  • Ouvre la connection au début du script et émets une erreur si ça ne marche pas (si ton script ne peut pas fonctionner sans BDD, alors c'est inutile de l'executer si on n'arrive pas à ouvrir la connection)
  • tu ne vérifie pas le retour de PDOStatement::execute, comment peux-tu savoir si ça c'est mal passé ?
  • NE JAMAIS LAISSER REMONTER LES MESSAGES D'ERREUR DE PHP COTE CLIENT (comme tu le fais avec ton die) C'EST UNE FAILLE DE SECURITE
  • tu ouvres deux fois la connection à la base, c'est inutile, une seule connection suffit

Dans tous les cas, teste, teste et teste encore, c'est en essayant et en ratant inlassablement qu'on apprends le plus.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/12/2011, 23h45   #4
Invité de passage
 
Inscription : février 2008
Messages : 7
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 7
Points : 2
Points : 2
Bonsoir tout le monde, et merci pour ces deux réponses. C sympa
Sur vos conseils,j'ai lu la doc PDO, et j'ai appris pas mal de choses.
J'ai également regardé du coté des filtres et strip_tags et je pense en avoir compris l'intérêt.

Citation:
au lieu de faire tes tests dans des ifs imbriqués, tu peux tout tester dans des ifs successifs et renseigner un booléen $en_erreur. Ensuite, tu encadres tes requêtes avec un if qui teste ton booléen $en_erreur. (le même principe que ton booléen $form en fait)
J'ai imbriqué afin que le script ne doit pas interpréter toutes les conditions si ce dernier détecte des le début une condition non valide. Si je les met les uns à la suite des autres, meme en cas de condition non valide en début de script, elles seront toutes vérifiées. En même temps, cela permettrait d'avoir l'intégralité des messages d'erreurs à présenter en haut de mon formulaire en cas de multiples saisies erronées.
D'ailleurs a ce propos, auriez vous une structure en tête pour récupérer tous les messages d'erreurs et les afficher en entête de formulaire lors de saisies erronées ? Je ne trouve pas très élégant de créer une variable par erreur et afficher toutes ces variables au dessus du formulaire avec des if à gogo. Pas de possibilité d'utiliser un tableau associatif d'erreurs ou quelque chose du genre ?

Citation:
ne pas mélanger PDO et mysql_*
J'ai du mal à comprendre : je ne dois pas utiliser mysql_real_escape_string avec PDO?
Dans ce cas, il vaut mieux utiliser les filtres et strip_tags ? Pas certain d'avoir saisi.

Citation:
utilise des modes de fetch intelligents comme FETCH_INTO ou FETCH_CLASS pour réccupérer directement des instances de modèles prêtes à l'usage
Concernant les fetch de type FETCH_INTO ou FETCH_CLASS, le but est de renvoyer la reponse d'une requête sous forme d'objet (nouvelle instance). Cependant quel est l'intérêt de récupérer un objet à la place d'un tableau associatif ou numéroté ? C'est de pouvoir accéder aux méthodes de PDOStatement ?

Citation:
il faut systématiquement vérifier le retour de PDOStatement::execute.
Concrètement, je fais comment ?
Je verifie si "$mon_objet->execute()" renvoie "true" ?
et si ce n'est pas le cas, que dois je faire ? je balance un message d'erreur ou lève une exception ?

Citation:
wrappe tes instances de PDOStatment dans des IteratorIterator afin de pouvoir y coller des FilterIterator ou des LimitIIterator qui sont des solutions paliatives aux problèmes de portabilité de SQL en PHP
Alors la, j'avoue, j'ai rien compris.
Je me documente sur les iterator et je reviendrais aux questions, si j'ai un soucis.
Donc probablement bientôt

Pour le pattern MVC, c'est en cours, je ne voulais pas tout faire d'un coup. :lil:

Citation:
La gestion des exception n'est pas là pour simplifier la vie du programmeur. Déjà, les exception ne sont levées par PDO que si l'attritbut ATTR_ERRMODE est à ERRMODE_EXCEPTION. Quand une exception est levée, il n'est pas forcément nécéssaire de la catcher, l'exception va remonter la pile d'appels jusqu'à la racine où elle provoquera une erreur fatale si elle n'est pas attrapée entre temps ou si l'exception handler n'est pas défini.
Une exception est par définition exceptionnelle: on ne la lance que quand il n'y a plus rien d'autre à faire. L'exemple type est le cas de comportement incorrect au niveau d'un constructeur, vu qu'il ne renvoie rien, comment notifier le bloc parent qu'il y a eu un erreur ? On lève une exception.
Auriez vous un bon tuto/cours au sujet des exceptions /erreurs et gestionnaire d'erreurs ? Pacque la franchement

Citation:
toute ta séquence de vérification peut être avantageusement réduite en utilisant filter_input_array
J'y ai jeté un coup d'oeil, c'est noté.

Pour le singleton, et le fait que j'ai ouvert une connexion à la db plusieurs fois.
Nous sommes d'accord que le singleton permet de n'instancier qu'une seule fois la classe. (en gros de s'assurer qu'une seule connexion à la db est ouverte.)
Cependant je pensais que le closecursor permettait de fermer la connexion.
Hors je m'aperçois que cela n'a absolument rien à voir.

Donc question :
1. Dois t'on obigatoirement fermer la connexion à une db ? Si oui, en fin de script ? Et comment ? En tuant l'objet $connexion ? Si c'est en tuant l'objet, le simple fait d'aboutir à la fin du script, ferme donc automatiquement la connexion ?
2. Le closecursor sert concrètement a quoi ? j'ai lu la doc PDO et j'ai compris que c'est lorsque l'on n'a pas récupéré l'intégralité de la réponse d'une requete et que l'on souhaite exécuter une seconde requete. Dans mon script, cela veut il dire qu'étant donné que j'ai dans ma requete un WHERE qui limite ma réponse à une seule ligne, l'intégralité de la réponse est récupérée et que dans ce cas, je n'ai pas besoin de fermer le curseur pour exécuter la requête suivante ?

Questions subsidiaires :
1. Quelle différence entre PDO::exec et PDO::query ?

En tout cas, un grand merci de prendre de votre temps pour éclairer ma lanterne.
skhattane est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/12/2011, 10h09   #5
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 991
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 991
Points : 5 031
Points : 5 031
Citation:
J'ai du mal à comprendre : je ne dois pas utiliser mysql_real_escape_string avec PDO?
Dans ce cas, il vaut mieux utiliser les filtres et strip_tags ? Pas certain d'avoir saisi.
Soit tu utilise PDO soit tu utilise mysql_* mais pas les deux, c'est redondant et dangereux. Avec les requêtes préparées il n'est plus nécéssaire d'utiliser real_escape_string.

Citation:
Concernant les fetch de type FETCH_INTO ou FETCH_CLASS, le but est de renvoyer la reponse d'une requête sous forme d'objet (nouvelle instance). Cependant quel est l'intérêt de récupérer un objet à la place d'un tableau associatif ou numéroté ? C'est de pouvoir accéder aux méthodes de PDOStatement ?
Non, l'idée c'est de récupérer un objet avec des méthodes bien pratiques, par exemple, si tu récupères une ligne (tuple) de la table article sous forme d'objet, ce serait bien pratique de disposer d'une méthode pour obtenir tous les commentaires non ?
Code :
1
2
3
4
5
6
7
$query = "SELECT * FROM articles WHERE id=123";
$stmt = $pdo->query($query);
$stmt->setFetchMode(PDO::FETCH_CLASS, 'Article');
$article = $stmt->fetch();
foreach ($article->getComment() as $comment) {
  ...
}
Tu vois le principe ?

Citation:
Je verifie si "$mon_objet->execute()" renvoie "true" ?
et si ce n'est pas le cas, que dois je faire ? je balance un message d'erreur ou lève une exception ?
Oui, il faut systématiquement vérifier le retour. Si c'est false, à toi de décider ce qu'il faut faire mais en tout cas tu sais qu'il ne faut pas travailler avec les résultats.

Citation:
Citation:
wrappe tes instances de PDOStatment dans des IteratorIterator afin de pouvoir y coller des FilterIterator ou des LimitIIterator qui sont des solutions paliatives aux problèmes de portabilité de SQL en PHP
Alors la, j'avoue, j'ai rien compris.
Je me documente sur les iterator et je reviendrais aux questions, si j'ai un soucis.
Donc probablement bientôt
Explication sur ce thread: http://www.developpez.net/forums/d10...emnt-iterator/
Pour comprendre le mécanisme des itérateurs en PHP, je te renvoie à la doc.

Citation:
Auriez vous un bon tuto/cours au sujet des exceptions /erreurs et gestionnaire d'erreurs ? Pacque la franchement
Voir la doc: http://php.net/manual/fr/language.exceptions.php
La gestion des exceptions en PHP est très similaire à celle de Java, à l'exception () du mot clé finaly qui n'existe pas en PHP.

Citation:

Pour le singleton, et le fait que j'ai ouvert une connexion à la db plusieurs fois.
Nous sommes d'accord que le singleton permet de n'instancier qu'une seule fois la classe. (en gros de s'assurer qu'une seule connexion à la db est ouverte.)
Cependant je pensais que le closecursor permettait de fermer la connexion.
Hors je m'aperçois que cela n'a absolument rien à voir.
Avec PDO, il n'existe aucun moyen certain de fermer la connexion explicitement. closeCursor est une méthode de PDOStatement, c'est PDO qui caractérise la connection. En fait, PHP fermera la connexion à la fin du script ou s'il est mis à null et que le garbage collector passe dessus (en PHP 5.3 uniquement et impossible de savoir quand cela se produit).

Citation:
1. Dois t'on obigatoirement fermer la connexion à une db ?
Non, PHP le fait pour toi à la fin du script.

Citation:
2. Le closecursor sert concrètement a quoi ?
De mémoire, PDOStatement::closeCursor sert à libérer les résultats d'une requête en cas de requêtes non mises en cache (unbuffered queries). Vu qu'il est impossible d'effectuer de nouvelle requête tant qu'on a pas réccupéré tous les résultats de la requête en cours dans ce cas, on appelle closeCursor pour spécifier qu'on a fini de travailler sur ce jeu de résultat et qu'on va effectuer de nouvelles requêtes.
Appeler cette méthode est inutile si on n'a pas mis l'attribut PDO::MYSQL_ATTR_USE_BUFFERED_QUERY à false dans PDO donc par défaut c'est inutile.

Citation:
Quelle différence entre PDO::exec et PDO::query ?
PDO::exec renvoie directement le nombre de lignes affectées par la requête.
PDO::query renvoie un PDOStatement.
Donc exec est adapté aux INSERT, UPDATE, DELETE et query aux SELECT.
Je te recommande l'usage systématique de PDO::prepare
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/12/2011, 14h55   #6
Invité de passage
 
Inscription : février 2008
Messages : 7
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 7
Points : 2
Points : 2
Ok merci pour ces réponses. Je commence à comprendre.
Par contre concernant PDO::FETCH_CLASS

Code :
1
2
3
4
5
6
7
$query = "SELECT * FROM articles WHERE id=123";
$stmt = $pdo->query($query);
$stmt->setFetchMode(PDO::FETCH_CLASS, 'Article');
$article = $stmt->fetch();
foreach ($article->getComment() as $comment) {
  ...
}
Si je comprends bien, tu renvoies le résultat de la requête sous forme d'objet (instance de la classe 'Article') ?
L'intérêt est donc de pouvoir appeler les méthodes de la classe 'Article'.

Dans ce cas, 4 questions :

1. peux tu me confirmer que dans ce cas au préalable tu auras probablement un include('Article.class.php'); dans lequel une classe 'Article' sera déclarée ?

2. Si tel est le cas, comment récupère ton les résultats de la requete au sein de la classe ? D'apres ce que je lis dans la doc de PDO, il va renvoyer des variables avec les intitulés des colonnes de la table. Donc si je comprends, on récupère au sein de la classe des variables du type: $id $titre $auteur ,etc. correspondant aux noms des champs de la table articles ?

3. enfin ce système ne pose t'il pas de pbl avec l'utilisation d'un constructeur ?
Car si FETCH_CLASS instancie la classe articles et que pour x raisons, son constructeur l'instancie histoire d'avoir un objet tout prêt des qu'on l'appel (j'ai cru voir ça quelque part), cela ne pose t'il pas de soucis ? Ou je suis complètement à coté de la plaque ?

4. enfin si on récupère au sein de la classe des variables en fonction des noms de colonnes, je suppose qu'il est mal venu de les récupérer directement au sein de nos attributs. En gros faire un =, mais qu'il vaut mieux passer par la méthode _setAttribut implémentée plus bas dans la classe?

C'est peut être la qu'intervient la notion d'hydratation des objets ? Me trompe-je
Je ne sais pas si je suis complètement a coté de la plaque donc pas tapper si je raconte n'importe quoi ...

sam
skhattane est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2011, 11h45   #7
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 991
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 991
Points : 5 031
Points : 5 031
Citation:
peux tu me confirmer que dans ce cas au préalable tu auras probablement un include('Article.class.php'); dans lequel une classe 'Article' sera déclarée ?
Il faut soit que la classe Article soit chargée (avec include ou require) ou qu'un autoloader ait été mis en place (voir http://php.net/manual/fr/language.oop5.autoload.php)

Citation:
Si tel est le cas, comment récupère ton les résultats de la requete au sein de la classe ? D'apres ce que je lis dans la doc de PDO, il va renvoyer des variables avec les intitulés des colonnes de la table. Donc si je comprends, on récupère au sein de la classe des variables du type: $id $titre $auteur ,etc. correspondant aux noms des champs de la table articles ?
En fait, les valeurs des attributs de la classe correspondront à celles des colonnes. Il faut alors que ces attributs soient soit publiques soit que les méthodes magiques __get et __set soient définies.

Citation:
enfin ce système ne pose t'il pas de pbl avec l'utilisation d'un constructeur ?
Car si FETCH_CLASS instancie la classe articles et que pour x raisons, son constructeur l'instancie histoire d'avoir un objet tout prêt des qu'on l'appel (j'ai cru voir ça quelque part), cela ne pose t'il pas de soucis ? Ou je suis complètement à coté de la plaque ?
Lors de chaque fetch, le constructeur de la classe sera implicitement invoqué (par défaut sans paramètres, il est possible de spécifier sous forme de tableaux les paramètres du constructeurs).
Voici le prototype de setFetchMode à utilise dans ce cas:
- bool PDOStatement::setFetchMode ( int $PDO::FETCH_CLASS , string $classname , array $ctorargs )
(voir http://php.net/manual/fr/pdostatement.setfetchmode.php)

Citation:
enfin si on récupère au sein de la classe des variables en fonction des noms de colonnes, je suppose qu'il est mal venu de les récupérer directement au sein de nos attributs. En gros faire un =, mais qu'il vaut mieux passer par la méthode _setAttribut implémentée plus bas dans la classe?
PDOStatement va lui même renseigner les attributs de l'instance une fois la classe instancié (voir plus haut).
Ils sont directement utilisables avec l'opérateur -> comme pour n'importe quelle instance.

Citation:
C'est peut être la qu'intervient la notion d'hydratation des objets ? Me trompe-je
Connais pas... Je vais regarder. J'aurais tendance à dire que PDOStatement popule des instances.

Exemple

Considérons le jeu de données suivant:
Code :
1
2
3
4
5
6
7
8
9
mysql> select * from test;
+----+------+---------+
| id | name | surname |
+----+------+---------+
|  1 | foo  | bar     |
|  2 | foo2 | bar2    |
|  3 | foo3 | bar3    |
+----+------+---------+
3 rows in set (0.00 sec)
Nous allons créer une classe toute bête pour ces données:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Test {
	public $id;
	public $name;
	public $surname;
 
	public function __construct () {
		// Visualiser l'appel au constructeur
		var_dump(__METHOD__);
	}
 
	public function greeting () {
		echo "Bonjour {$this->name} {$this->surname}";
	}
}
La méthode greeting va nous permettre d'afficher un message de bienvenue.

Voici donc comment s'utilise le mode FETCH_CLASS:
Code :
1
2
3
4
5
6
7
8
9
$pdo = new PDO('mysql:dbname=test;host=localhost', 'root', '');
$stmt = $pdo->query('SELECT * FROM test');
 
$stmt->setFetchMode(PDO::FETCH_CLASS, 'Test');
 
foreach ($stmt as $item) {
	$item->greeting();
	echo "<br />";
}
Produit:
Code :
1
2
3
4
5
6
7
8
9
10
11
string 'Test::__construct' (length=17)
 
Bonjour foo bar
 
string 'Test::__construct' (length=17)
 
Bonjour foo2 bar2
 
string 'Test::__construct' (length=17)
 
Bonjour foo3 bar3
On remarque que le constructeur est appelé à chaque fois qu'on réccupère une nouvelle entrée, ceci contraste avec un autre mode de fetch lui aussi très utile: FETCH_INTO:
Code :
1
2
3
4
5
6
7
8
9
10
$pdo = new PDO('mysql:dbname=test;host=localhost', 'root', '');
$stmt = $pdo->query('SELECT * FROM test');
 
$test = new Test;
$stmt->setFetchMode(PDO::FETCH_INTO, $test);
 
foreach ($stmt as $item) {
	$item->greeting();
	echo "<br />";
}
Produit:
Code :
1
2
3
4
5
string 'Test::__construct' (length=17)
 
Bonjour foo bar
Bonjour foo2 bar2
Bonjour foo3 bar3
Dans ce deuxième cas, on utilise une instance existante et PDOStatement va la populer à chaque itération. L'avantage est d'éviter de se retrouver avec plusieurs instances et d’appeler plusieurs fois le constructeur.

Pour aller plus loin

Nous pouvons construire des classes de modèles implémentant un CRUD (Create, Retrieve, Update, Delete), ce sont des méthodes capables de faire respectivement des créations, réccupération, mise-à-jour et suppression de données, tout cela encapsulé dans une seule classe.

Voici un exemple de classe de modèle générique (extrait du framework Axiom):
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<?php
/**
 * Axiom: a lightweight PHP framework
 *
 * @copyright Copyright 2010-2011, Benjamin Delespierre (http://bdelespierre.fr)
 * @licence http://www.gnu.org/licenses/lgpl.html Lesser General Public Licence version 3
 */
 
/**
 * Model Base Class
 *
 * @abstract
 * @author Delespierre
 * @package libaxiom
 * @subpackage core
 */
abstract class Model {
 
    /**
     * Model key id
     * @var string
     */
    protected $_id_key = 'id';
 
    /**
     * Model's data
     * @var array
     */
    protected $_data = array();
 
    /**
     * Statements cache
     * @var array
     */
    protected $_statements = array();
 
    /**
     * Initialize a model statement (part of CRUD)
     * @abstract
     * @param string $statement
     * @return PDOStatement
     */
    abstract protected function _init ($statement);
 
    /**
     * Default constructor
     * @param mixed $id
     * @throws RuntimeException
     */
    public function __construct ($id = null) {
        if ($id !== null && $id !== false && !$this->find($id))
            throw new RuntimeException("Cannot instanciate model", 2009);
    }
 
    /**
     * __sleep overloading
     * @return array
     */
    public function __sleep () {
        return array('_id_key', '_data');
    }
 
    /**
     * Getter
     * @param string $key
     * @return mixed
     */
    public function __get ($key) {
        return isset($this->_data[$key]) ? $this->_data[$key] : null;
    }
 
    /**
     * Setter
     * @param string $key
     * @param mixed $value
     * @return void
     */
    public function __set ($key, $value) {
        $this->_data[$key] = $value;
    }
 
    /**
     * __isset overloading
     * @param string $key
     * @return boolean
     */
    public function __isset ($key) {
        return isset($this->_data[$key]);
    }
 
    /**
     * Get internal data
     * @internal
     * @return array
     */
    public function getData () {
        return $this->_data;
    }
 
    /**
     * Retrieve method
     * Will return false in case of error
     * @param mixed $id
     * @return Model
     */
    public function find ($id) {
        if (!$this->_init("retrieve"))
            throw new RuntimeException("Cannot initialize " . __METHOD__, 2010);
 
        if ($this->_statements['retrieve']->execute(array(":{$this->_id_key}" => $id))) {
            if ($this->_statements['retrieve']->rowCount()) {
                $this->_data = $this->_statements['retrieve']->fetch(PDO::FETCH_ASSOC);
                return $this;
            }
        }
        return false;
    }
 
    /**
     * Create methode
     * Will return false in case of error
     * @param array $data
     * @throws RuntimeException
     * @return Model
     */
    public function create ($data) {
        if (!$this->_init("create"))
            throw new RuntimeException("Cannot initialize " . __METHOD__, 2011);
 
        if ($this->_statements['create']->execute(array_keys_prefix($data, ':'))) {
            $id = Database::lastInsertId();
            return $this->find($id);
        }
        return false;
    }
 
    /**
     * Update method
     * @throws RuntimeException
     * @return boolean
     */
    public function update ($data = array()) {
        if (!$this->_init("update"))
            throw new RuntimeException("Cannot initialize " . __METHOD__, 2012);
 
        if (!empty($this->_data)) {
            $inputs = array_merge($this->_data, array_intersect_key($data, $this->_data));
            return $this->_statements['update']->execute(array_keys_prefix($inputs, ':'));
        }
        return false;
    }
 
    /**
     * Delete method
     * @throws RuntimeException
     * @return boolean
     */
    public function delete () {
        if (!$this->_init("delete"))
            throw new RuntimeException("Cannot initialize " . __METHOD__, 2013);
 
        if (!empty($this->_data))
            return $this->_statements['delete']->execute(array(":{$this->_id_key}" => $this->_data[$this->_id_key]));
        return false;
    }
}
Et voici un exemple de classe concrête de modèle (Model est abstraite car il manque une information: les requêtes à effectuer, il faut donc la faire hériter):
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<?php
/**
 * Axiom: a lightweight PHP framework
 *
 * @copyright Copyright 2010-2011, Benjamin Delespierre (http://bdelespierre.fr)
 * @licence http://www.gnu.org/licenses/lgpl.html Lesser General Public Licence version 3
 */
 
/**
 * User Model
 *
 * @author Delespierre
 * @version $Rev: 74 $
 * @subpackage User
 */
class User extends Model {
 
    protected function _init ($statement) {
        if (isset($this->_statements[$statement]))
            return $this->_statements[$statement];
 
        switch ($statement) {
            case 'create':
                $query = 'INSERT INTO `ax_users` (`login`,`password`,`name`,`surname`) VALUES (:login,:password,:name,:surname)';
                break;
            case 'retrieve':
                $query = 'SELECT * FROM `ax_users` WHERE `id`=:id';
                break;
            case 'update':
                $query = 'UPDATE `ax_users` SET `login`=:login, `password`=:password, `name`=:name, `surname`=:surname, '.
                		 '`creation`=:creation, `last_connection`=:last_connection WHERE `id`=:id';
                break;
            case 'delete':
                $query = 'DELETE FROM `ax_users` WHERE `id`=:id';
                break;
            default:
                throw new RuntimeException("$statement is unexepected for " . __METHOD__, 10001);
        }
 
        return $this->_statements[$statement] = Database::prepare($query);
    }
 
    public static function exists ($username, $password) {
        $query = "SELECT `id` FROM `ax_users` WHERE `login`=:login AND `password`=:password";
        $stmt = Database::prepare($query);
 
        $password = md5($password);
        $stmt->bindParam(':login', $username, PDO::PARAM_STR);
        $stmt->bindParam(':password', $password, PDO::PARAM_STR);
 
        if ($stmt->execute()) {
            if ($stmt->rowCount()) {
                $row = $stmt->fetch();
                return new self($row['id']);
            }
            return false;
        }
        else
            throw new RuntimeException("Error with query");
    }
 
    public static function getUsers ($search_params = array()) {
        $query = "SELECT * FROM `ax_users`";
 
        if (!empty($search_params)) {
            $pieces = array();
            foreach ($search_params as $key => $value)
                $pieces[] = "`$key`=:$key";
            $query .= " WHERE " . implode(' AND ', $pieces);
        }
 
        $stmt = Database::prepare($query);
        if ($stmt->execute(array_keys_prefix($search_params, ':'))) {
            $user = new self;
            $stmt->setFetchMode(PDO::FETCH_INTO, $user);
            return new PDOStatementIterator($stmt);
        }
        return false;
    }
}
On peut l'utiliser de cette façon:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// créer un utilisateur
$user = new User;
$user->create(array(
  'login' => 'test',
  'password' => md5('test'),
  'name' => 'Test',
  'surname' => 'FooBar',
));
 
// Trouver un utilisateur
if ($user = User::exists($login, $password)) ...
 
// Metter à jour un utilisateur
$user->name = "Random";
$user->update();
 
// Supprimer un utilisateur
$user->delete();
Plutôt sympa comme syntaxe non ? La création d'objets modèle est une partie cruciale du paradigme MVC, c'est quelque peu laborieux de créer toutes les classes nécéssaires mais l'avantage se fait clairement sentir en termes d'évolutivité, de portabilité et surtout de maintenance du code source.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2011, 12h01   #8
En attente de confirmation mail
 
Inscription : juin 2002
Messages : 6 164
Détails du profil
Informations forums :
Inscription : juin 2002
Messages : 6 164
Points : 6 404
Points : 6 404
Citation:
Envoyé par Benjamin Delespierre Voir le message
En fait, les valeurs des attributs de la classe correspondront à celles des colonnes. Il faut alors que ces attributs soient soit publiques soit que les méthodes magiques __get et __set soient définies.
Les attributs peuvent être de visibilité restreinte avec le mode FETCH_CLASS. Et, pour ceux qui ne sont pas publics, il n'y a pas d'appel à __set (uniquement pour les inexistants/non déclarés).

Tout l'opposé, ou presque, (attributs publics sinon __set requise) de FETCH_INTO où, du fait de son fonctionnement, __set ne sera exécutée qu'une seule fois pour chaque attribut inexistant.

Chacun de ces modes a ses avantages et ses inconvénients (FETCH_CLASS permet, en outre, plus de choses).

Citation:
Envoyé par Benjamin Delespierre Voir le message
Lors de chaque fetch, le constructeur de la classe sera implicitement invoqué (par défaut sans paramètres, il est possible de spécifier sous forme de tableaux les paramètres du constructeurs).
À noter, que par défaut (sans l'option PDO::FETCH_PROPS_LATE - introduit en 5.2.0), les propriétés de la classe sont initialisées avec les valeurs de la base avant l'appel du constructeur (donc, dans ces circonstances, le constructeur pourrait, volontairement ou non, écraser les valeurs issues de la base).
julp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/12/2011, 14h17   #9
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 991
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 991
Points : 5 031
Points : 5 031
Merci pour la correction J'utilise massivement le mode FETCH_INTO (quitte à utiliser clone par derrière) alors je ne l'avais jamais remarqué ce comportement.

Il est vrai également que la doc n'est pas toujours très explicite à ce sujet...
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/12/2011, 21h23   #10
Invité de passage
 
Inscription : février 2008
Messages : 7
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 7
Points : 2
Points : 2
Ouch la réponse !!!
C plus un forum, c'est un live tuto

Je comprends mieux le fonctionnement.
Je vais prendre un peu de temps a vraiment essayer de bien décortiquer les classes d'Axiom que tu as fourni. Je reviens aux questions si besoin. Ca risque ...

Deja une :
La diff entre FETCH_CLASS et FETCH_INTO signifie donc qu'avec INTO, il n'y aura jamais qu'une seule et unique instance qui sera mis a jour successivement par les résultats successifs de la requête. Si tel est le cas, si on appele ensuite une méthode de cette instance, celle ci se fera avec la dernière ligne de données que lui aura renvoyé la requêtes ?

Au fait concernant la notion d'hydratation, c'est dans le tuto sur la POO de vyk12 sur le siteduzero.
Concretement il s'agit d'une fonction "hydrate()" qui est appelée directement depuis le constructeur de la classe et qui va appeler automatiquement les setters en fonction du nom des attributs passés en paramètres lors de l'instanciacion de la classe.

Je pense que ca revient à peu près au même qu'un FETCH_CLASS sauf que l'attribution des valeurs aux attributs se fait via un tableau associatif.

J'ai testé la fonction, alors je met mon script : (soyez indulgents)
Celle ci impose de fait une convention de nommage des setters, ce qui n'est peut être pas plus mal.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?php
class User
{
	private $id;
	private $login;
	private $prenom;
	private $nom;    	
 
	public function __construct(array $tableau)
	{
		$this->hydrate($tableau);
	}
 
	public function hydrate(array $tableau)
       {
           foreach ($tableau as $key => $value)
           {
               $method = 'set'.ucfirst($key);
 
               if (method_exists($this, $method))
               {
                   $this->$method($value);
               }
           }
       }
 
/* ----------------- Setters-------------------*/
 
	public function setId($id)
		{
			$this->id = $id;
		}
 
	public function setLogin($login)
		{
			$this->login = $login;
		}
 
	public function setPrenom($prenom)
		{
			$this->prenom = $prenom;
		}
 
	public function setNom($nom)
		{
			$this->nom = $nom;		
		}
 
/* ----------------- Getters-------------------*/
 
	public function id()
		{
			return $this->id;
		}
 
	public function login()
		{
			return $this->login;
		}
 
	public function prenom()
		{
			return $this->prenom;
		}
 
	public function nom()
		{
			return $this->nom;
		}
 
}
 
$tab=array('id'=> 47,'login'=> 'Samlamenace','prenom'=> 'Tyler','nom'=> 'Durden');
$perso = new User($tab);
echo $perso->id().' '.$perso->login().' '.$perso->prenom().' '.$perso->nom();
?>
En tout cas, merci bcp pour l'aide que vous apportez, ça donne vraiment envie de progresser. C cool
skhattane est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/12/2011, 10h23   #11
Modératrice
 
Avatar de Celira
 
Femme
Développeuse PHP/Java
Inscription : avril 2007
Messages : 3 664
Détails du profil
Informations personnelles :
Sexe : Femme
Âge : 27
Localisation : France

Informations professionnelles :
Activité : Développeuse PHP/Java

Informations forums :
Inscription : avril 2007
Messages : 3 664
Points : 5 390
Points : 5 390
L'avantage de la méthode d'hydratation, c'est qu'on peut aussi s'en servir pour faire une mise à jour d'un objet existant (par exemple, dans le cas d'un formulaire modifiant un enregistrement existant)
Au passage, vu que tu as normé tes setters, autant aussi normer les getters en getMachin()
__________________
Modératrice PHP
Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)

Pour afficher votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur)
Celira est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 15h38.


 
 
 
 
Partenaires

Hébergement Web