OVH Cloud OVH Cloud

Question de philosophie

39 réponses
Avatar
Alexandre
Bonjour,

je fais appel au grands experts du PHP.

Vous vous souvenez quand le register_global faisait des siennes. Pour un
grand nombre de developpeurs il a fallu reprendre le code notamment pour les
formulaire et changer:
$toto (issu du champs de formulaire ... name="toto">)
en
$_POST['toto'].

Pour ma part, je me suis dit qu'il etait hors de question de reprendre des
pages et des pages de codes faites par des predecesseurs ou moi meme.
J'ai donc cree ca:
if(isset($_POST)) {
foreach($_POST as $key=>$val) {
//echo $key.'=>'.$val.'<p>';
$$key = $val;
}
}

Que je mettais en haut de toutes mes pages. Et ca donctionne tres bien.

Puis je me suis dit que je pouvais faire la meme chose pour une requete
SELECT. Imaginons qu'une table contienne 70 champs et que vous souhaitez
tout afficher (les 70 champs).
J'ai donc fait ceci:

$requete = "SELECT * FROM gest_parc";
$resultat = mysql_query($requete);

while($row = mysql_fetch_array($resultat,MYSQL_ASSOC)){

foreach($row as $key=>$val) {
echo $key.'=>'.$val.'<p>';
$$key = $val;
}
}

Ce qui m'evite de faire:
while ($row=mysql_fetch_object($resultat)){
$id = $row->id;
$nom = $row->nom;
.
.
.
.
}

ou un fetch_array ou encoe un mysql_result...

Tout ceci fonctionne a merveille. MAintenant la question que je me pose
c'est que je n'ai jamais vu ce genre de code sur le net ni meme dans les
applis qu'on trouve en open-source.

Je me demandais alors si j'adoptais une bonne methode, si je n'allais pas a
l'encontre de l'efficacite ou d'un certain "bon procede".

Merci d'avance

Alex

10 réponses

1 2 3 4
Avatar
ftc
Enfin, ça ne rajoute toujours pas à la lisibilité du code.



La syntaxe est extremement alourdie avec les $_POST et les $_GET
obligatoires, du fait que les acces dans les tableaux ne se
dereferencent pas dans les chaines comme les variables simples.

Un exemple naif pour illustrer :

$sql = "insert into matable(var1, var2) values('$test1','$test2')";

est beaucoup plus lisible donc maintenable que

$sql = 'insert into matable(var1, var2) values(''.
$_POST[test1].'',''.$_POST[test2].'')';



A partir du moment ou on teste toutes les variables passées en argument
pour s'assurer de la cohérence des données fournies, je ne vois pas trop
la différence.

if ( isset( $_POST['variable1'] && ctype_digit( $_POST['variable'] ) ) {
$variable = (int) $_POST['mavariable'];
}
else {
$variable = null;
}

if ( isset( $_POST['variable2'] ) && testValeursAutorisees(
$_POST['variable2'] ) ) {
$variable2 = $_POST['variable2'];
}
else {
$variable2 = null;
}

a) on sait d'ou viennent $variable et $variable2

b) $variable et $variable2 sont importées dans l'espace de nom de façon
propre et sûre et uniquement celles ci comme on le fait avec un autre
langage de programmation.

c) dans tous le reste du script, on utilise $variable et $variable2

Ca ne rajoute aucune lourdeur puisque de toute façon il faut tester à un
moment ou un autre la cohérence des arguments.


Avatar
Nadine St-Amand
Bin, dupliquer inutilement toutes les variables $_REQUEST et tout ce qui
vient de la DB, ça prend du temps et des ressources... pour rien.


Je ne suis pas d'accord.

Cela depend du temps d'acces dans le hash versus le temps d'acces de la
variable sans hash versus le temps de duplication de la donnee.
et bien sur cela depend aussi du nombre d'acces de la variable dans le
script.

Supposons que :
temps d'acces dans le hash > temps d'acces de la variable

(comme je viens de l'univers du langage C et C++, j'ai tendance a penser
ainsi, et j'entends par > que c'est significativement superieur)

Bien le point d'equilibre c'est quand

temps_de_duplication_de_la_donnee
(temps_acces_hash - temps_acces_variable) * nombre_acces

Mais si on veut chipoter a ce point:
Si vous avez deja code manuellement un parseur et un interpreteur de
code, vous avez peut-etre deja vu le temps qu'il faut a un interpreteur
pour parser ses lignes de code (son input). Il ne faut pas oublier que
notre code devient donc l'input de cet autre programme, car on ne peut
pas coder en php comme on coderait en c.

La copie de donnees devient surement negigeable comparativement.

On peut reduire la longueur du nom des variables pour avoir un effet de
reduction du temps d'interpretation.

Par ailleurs, l'utilisation systematique des tableaux $_GET et $_POST
ajoutent en longueur (nombre de caracteres a ce processus) ce qui rend
mon equation precedente fausse

L'equilibre devient a :

temps_de_duplication_de_la_donnee
(temps_parsing_sup + temps_acces_hash - temps_acces_variable) * nombre_acces

Cette equation peut etre simplifiee si on sait que certaines choses sont
negligeables par rapport aux autres.


Bref il faudrait un bench pour etre fixe sur le point d'equilibre,
mais je parierais personnellement qu'a partir de 1 ou 2 acces, il est
depasse
Il devient alors nettement plus avantageux niveau vitesse d'execution de
sortir les variables du tableau associatif.

Il est donc evident que ce changement majeur du langage vient de
l'alourdir tout en le rendant plus haut niveau.
On peut difficilement avoir les avantages d'un langage bas niveau et
d'un langage haut niveau en meme temps, a moins de prendre un langage
bas niveau et de construire d'architecture que ce dont on a besoin pour
un projet donne.

--
Nadine St-Amand
Generation de code sql2php http://www.phpbackend.com/

Avatar
Nadine St-Amand
2) le premier exemple était une déclaration de chaîne avec des
Ce sont deux techniques totalement différentes, et il est tout à fait
possible d'utiliser les deux techniques sur des tableaux.


Oui mais a partir du moment ou la lisibilite est de toute facon
sacrifiee, n'est-il pas interessant de ne pas l'avoir sacrifiee pour
rien et de recuperer un petit peu de temps d'execution la-dessus ?
car tout le monde sait que la chaine entre guillemets simples ne sera
pas interpretee et cela donne une economie de temps d'execution.

Je te presentais les deux alternatives que moi j'utiliserais dans les
deux cas,
je ne faisais pas une comparaison de deux techniques equivalentes
(c'est pas un expose theorique)

$sql = "INSERT INTO matable(var1, var2) VALUES ('{$_POST['test1']}',
'{$_POST['test2']}')";


pas plus lisible que la concatenation.

3) De toutes façons, on intègre pas directement une variable dans une
requête SQL, surtout si elle est issue de GET, POST ou autre.


j'ai ecrit exemple naif pour ne pas generer de discussion sur ce nouveau
sujet et pour ne pas presenter ce code comme viable

ceci dit, si c'est dans une condition ou nom de table c'est evident
qu'il faut la traiter a l'acide (en tenant compte du contexte et en
etant coherent), mais c'est tout un sujet qu'il convient de traiter
separement. Ceci car la chaine fait partie du code sql comme tel.

Si c'est une donnee a inserer en chaine dans la base et presentee en
donnees et qu'elle est 'escapee' (d'une maniere ou d'une autre) elle ne
peut plus faire de mal, on a voulu recuperer la donnee intacte entree
par l'utilisateur, alors on l'a.

Bien sûr il y a magic_quotes_gpc qui réalisera automatiquement un
addslashes sur GET/POST/Cookie, addslashes qui équivaut à
mysql_escape_string. et de toutes façons c'est
du non-sens. Une variable est censée contenir son contenu, et non pas un
contenu altéré en vue d'un traitement spécifique.


Je suis d'accord avec toi la-dessus, mais pas au point d'enlever les
slashes puis ensuite de les remettre dans mes scripts :))

Sans doute que le php est tellement consacre a cet usage..

Mais ce n'est pas portable avec d'autres SGBDs


peux-tu m'en dire plus ? avec postgres par exemple, cela me semble
fonctionner, non ?

--
Nadine St-Amand
Generation de code sql2php http://www.phpbackend.com/
Livre de C++ http://cplusplus.cdoc.biz/

Avatar
Nadine St-Amand
P'tit Marcel wrote:
Nadine St-Amand wrote:
Il y a deja quelqu'un qui a dit : simple is beautiful.


là t'as bon

$sql = 'insert into matable(var1, var2) values(''.
$_POST[test1].'',''.$_POST[test2].'')';



là t'as pas bon :


je sais, un vieux reflexe pour lequel je dois constamment me relire.


Avatar
Olivier Miakinen

[...] tout le monde sait que la chaine entre guillemets simples ne sera
pas interpretee et cela donne une economie de temps d'execution.


Non, tout le monde ne sait pas que cela donne une économie de temps
d'exécution. Bien sûr, si tu compares 'chaîne avec $variable' et
"chaîne avec $variable", la première sera plus rapide que la seconde.
Mais entre "chaîne avec $variable" et 'chaîne avec ' . $variable, rien
n'est moins sûr.

Par ailleurs, tu parles de chipoter dans un autre article, eh bien je
crois que vouloir gagner quelques micro-secondes en remplaçant des " par
des ' alors qu'on dépense des milli-secondes dans une requête SQL, c'est
cela qui s'appelle chipoter...

$sql = "INSERT INTO matable(var1, var2) VALUES ('{$_POST['test1']}',
'{$_POST['test2']}')";


pas plus lisible que la concatenation.


Je suis d'accord. Cela dit, je ne vois par pourquoi $sql = "INSERT INTO
matable(var1, var2) VALUES ('$_REQUEST[test1]', '$_REQUEST[test2]')"; ne
fonctionnerait pas. Ceci *est* plus lisible que la concaténation.


--
Olivier Miakinen
Non, monsieur le juge, je vous le jure : jamais je n'ai cité
Bruxelles dans ma signature.


Avatar
Patrick Mevzek
$sql = 'insert into matable(var1, var2) values(''.
$_POST[test1].'',''.$_POST[test2].'')';


Mais comme de toute façon on utilise les prepared statements, ce problème
ne se pose pas...

--
Patrick Mevzek . . . . . . Dot and Co (Paris, France)
<http://www.dotandco.net/> <http://www.dotandco.com/>
Dépêches sur le nommage <news://news.dotandco.net/dotandco.info.news>

Avatar
loufoque
Nadine St-Amand a dit le 20/06/2005 à 16:56:

Oui mais a partir du moment ou la lisibilite est de toute facon
sacrifiee, n'est-il pas interessant de ne pas l'avoir sacrifiee pour
rien et de recuperer un petit peu de temps d'execution la-dessus ?
car tout le monde sait que la chaine entre guillemets simples ne sera
pas interpretee et cela donne une economie de temps d'execution.


La concaténation peut prendre plus de temps que l'interprétation des
variables au sein des guillemets doubles.

Et puis bon, quand même, je trouve
"INSERT INTO table VALUES ('{$_POST['value']}');"
plus lisible que
'INSERT INTO table VALUES (''.$_POST['value'].'');';


Je suis d'accord avec toi la-dessus, mais pas au point d'enlever les
slashes puis ensuite de les remettre dans mes scripts :))


Moi si, j'en suis au point de faire ça. Enfin la performance n'est pour
moi qu'une seconde priorité.
J'essaie tout de même de désactiver cette option via .htaccess si
possible (ou mieux, si j'y ai accès, suivant la plateforme de production).


peux-tu m'en dire plus ? avec postgres par exemple, cela me semble
fonctionner, non ?


Certains SGBDs utilisent un ' pour échapper un autre ', mais en fait on
peut activer ce comportement pour addslashes en activant
magic_quotes_sybase ou un truc du style.

Autre chose, addslashes remplace " par ".
Je ne sais pas si le fait qu'un slash précède un caractère non spécial
ne peut pas poser certains problèmes.

Avatar
loufoque
Olivier Miakinen a dit le 20/06/2005 à 21:35:

Je suis d'accord. Cela dit, je ne vois par pourquoi $sql = "INSERT INTO
matable(var1, var2) VALUES ('$_REQUEST[test1]', '$_REQUEST[test2]')"; ne
fonctionnerait pas. Ceci *est* plus lisible que la concaténation.


Par contre ça fait appel aux constantes test1 et test2 qui, n'existant
pas, souleveront un notice.

Avatar
Olivier Miakinen

Je suis d'accord. Cela dit, je ne vois par pourquoi $sql = "INSERT INTO
matable(var1, var2) VALUES ('$_REQUEST[test1]', '$_REQUEST[test2]')"; ne
fonctionnerait pas. Ceci *est* plus lisible que la concaténation.


Par contre ça fait appel aux constantes test1 et test2 qui, n'existant
pas, souleveront un notice.


Mais non ! Il n'y a pas de constantes puisque le tout fait partie d'une
chaîne de caractères entre guillemets doubles.


<cit. http://www.php.net/manual/fr/language.types.array.php>
$arr = array('fruit' => 'pomme', 'legume' => 'carotte');
define('fruit','legume');

// La suite est correcte si cela se passe dans une chaîne.
// Les constantes ne sont pas remplacées par leur valeur dans une chaîne
print "Bonjour $arr[fruit]"; // Bonjour pomme
</cit.>


<cit. http://www.php.net/manual/en/language.types.array.php>
$arr = array('fruit' => 'apple', 'veggie' => 'carrot');
define('fruit', 'veggie');

// The following is okay as it's inside a string. Constants are not
// looked for within strings so no E_NOTICE error here
print "Hello $arr[fruit]"; // Hello apple
</cit.>


Avatar
loufoque
Olivier Miakinen a dit le 21/06/2005 à 12:02:

Mais non ! Il n'y a pas de constantes puisque le tout fait partie d'une
chaîne de caractères entre guillemets doubles.


Ah oui ça marche.

1 2 3 4