Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

POO vs procedural, mysql et les débutants php

1 réponse
Avatar
Gunbaty
Bonjour,
voil=E0 une question qui semble souvent revenir:

faut-il utiliser un objet pour abstraire le SQL du php et ainsi gagner=20
en claret=E9 avec juste des Array comme requete SQL ou utiliser un m=E9la=
nge=20
SQL / PHP avec un risque d'erreur plus grand, tout cela pour produire=20
plus vite ?

je m'explique voici un script classique avec de SQL :


/* *************************************** */

$query_base =3D "select b.*, c.* from biens b left join caracteristiques =
c=20
on c.caracteristique_biens_id =3D b.biens_id where b.biens_category_id =3D=
2=20
order b.biens_prix asc ";

$query_base_cnt =3D "select count(b.biens_id) from biens b left join=20
caracteristiques c on c.caracteristique_biens_id =3D b.biens_id where=20
b.biens_category_id =3D 2 ";

$result =3D mysql_query($query_base." limit 0, 20");

$result_cnt =3D mysql_query($query_base);
// solution 2
// $result_cnt =3D mysql_query($query_base_cnt);

if($result && is_ressource($result) && (mysql_num_rows($result)>0) )
{
echo '<br /> il y a '.mysql_num_rows($result)." affich&eacute;, et=20
au total ".mysql_num_rows($result_cnt);
while(($line =3D mysql_fetch_object($result)))
{
echo "<br /> ".$line->caracteristique_description." ::=20
".$line->biens_prix;
}
}


/* *************************************** */

voici maintenant une alternative objet de ma conception et utilis=E9 par =

de nombreux CMS / Framework

$_obj_sgbd =3D new StorageManagerSGBD(); // ne se connecte que lors de =

l'envoie d'une requete SQL

$result =3D (($_obj_sgbd->fetchEnt(
array(
"biens"=3D>array(

storagemanager_queryfield=3D>array(

"biens_prix"=3D>array(">"=3D>2000),

"biens_category_id"=3D>2

),

storagemanager_returnfield=3D>array("*"),
storagemanager_limitfield=3D>array(0=3D>20),

storagemanager_orderfield=3D>array("biens_prix"=3D>"asc")
),
"caracteristiques"=3D>array(

storagemanager_queryfield=3D>array(

"caracteristiques_biens_id"=3D>array("=3D"=3D>"biens_=
id")

),

storagemanager_returnfield=3D>array("*"),
),
)
)
)?$_obj_sgbd:$_obj_sgbd);


if($result && count($result)>0 )
{

echo '<br /> il y a '.count($result)." affich&eacute;, et au=20
total ".$result->count_all();
foreach($result as $_k_biens =3D> $_v_biens)
{
echo "<br /> ".$_v_biens->caracteristique_description." ::=20
".$_v_biens->biens_prix;
}
}

/* *************************************** */


Voil=E0 pour les exemples ...

dans la solution 1, pour modifier la requete et nombre de resultats il=20
faut intervenir sur les Deux Requete et si l'on veux changer les liaison =

ou critere entre les table il faut connaitre le SQL.

Dans la solution Deux, tout n'est que Array et formulation uniforme pour =

toutes les requete, l'objet est prevu pour se connecter UNIQUEMENT en=20
car de requete SQL.

Autre chose, dans le cas de la solution Deux, le comptage TOTAL et avec=20
le Limit SQL est dispo de suite pas de requete supplementaire (avec=20
mysqli), de ce fait un devellopeur ne connaissant rien a SQL peux=20
l'utiliser et tout les Script profite d'une claret=E9 avec un simple=20
foreach, autre avantage, le prochain resultat de BDD est charg=E9 =E0 cha=
que=20
passage du foreach grace a SPL ArrayIterator sur l'objet, la=20
reutilisation du code est simplifier car abstrait de SQL et de toutes=20
confusion de variable, les updates, deletes et inserts se font avec des=20
primitives sur l'objet tels que : fetchEnt(), insertEnt(), deleteEnt(),=20
toutes acceptant un Array ou une Chaine SQL.

Donc meme un d=E9butant en php peux l'utiliser, car les indexes du Array =

sont le nom SQL des colonnes de la BDD et l'indice est la condition ou=20
liaison dans la requete sql.

Cepandant, je fait face a un chef de projet qui me dit ne pas comprendre =

mon choix en POO et pretent que le "=E0 l'ancienne ..." est plus rapide e=
t=20
plus clair, ce que je conteste, car le taux d'erreur sur l'ancienne=20
methode et plus grand et ne gere en aucun cas les erreur, si ce n'est au =

prix d'un code repetitif et avec plus de variable, donc un script plus=20
long a charger et comprendre.


Que en pensez-vous et quel solution preferez-vous ou proposeriez vous,=20
voire un commentaire sur ce post ?

1 réponse

Avatar
Mickaël Wolff
FU2: fr.comp.developpement

Je pense que c'est plus en charte sur fr.comp.developpement.

On 01/03/11 23:04, Gunbaty wrote:
faut-il utiliser un objet pour abstraire le SQL du php et ainsi gagner
en clareté avec juste des Array comme requete SQL ou utiliser un mélange
SQL / PHP avec un risque d'erreur plus grand, tout cela pour produire
plus vite ?



En fait, ce n'est pas une question d'OO ou de procédural, mais plutôt
de répétition des erreurs.

$_obj_sgbd = new StorageManagerSGBD(); // ne se connecte que lors de
l'envoie d'une requete SQL


Pas forcément. C'est effectivement une (éventuelle) optimisation
courante, mais elle n'est pas garantie. On peut très bien imaginer une
bibliothèque qui requiert un comportement fainéant à la demande
explicite de l'utilisateur (de la bibliothèque).

storagemanager_queryfield=>array(


Juste en passant, en PHP5, une chaine de caractères doit être entre
quotes ou double-quotes pour éviter des condlits étranges avec
d'éventuelles constantes définies par define.

dans la solution 1, pour modifier la requete et nombre de resultats il
faut intervenir sur les Deux Requete et si l'on veux changer les liaison
ou critere entre les table il faut connaitre le SQL.



Ce qui fait que le design viole un principe de base de tout bon
programmeur : Don't Repeat Yourself (DRY). Bien sûr, on est pas obligé
de faire de l'objet, on peut imaginer utiliser des fonctions sans
classe. Mais c'est tellement plus simple avec des objets (surtout qu'en
PHP on a pas de structures, en dehors des array).


de ce fait un devellopeur ne connaissant rien a SQL peux l'utiliser


Non. D'expérience (avec SQLAlchemy et PDO) l'usage de classes
d'abstration ne dispence pas d'une connaissance intime du SGBDR. Tu as
vite fait d'écrire du code qui construit des requêtes tellement
compliquées que ton application sera inutilisable.

et tout les Script profite d'une clareté avec un simple
foreach,


En fait, composer des objets métiers implémentés en terme de tables
serait encore plus simple à utiliser.

autre avantage, le prochain resultat de BDD est chargé à chaque
passage du foreach grace a SPL ArrayIterator sur l'objet, la
reutilisation du code est simplifier car abstrait de SQL et de toutes
confusion de variable, les updates, deletes et inserts se font avec des
primitives sur l'objet tels que : fetchEnt(), insertEnt(), deleteEnt(),
toutes acceptant un Array ou une Chaine SQL.


Ça évite surtout les pitfalls classiques de la construction de
requêtes SQL.

Donc meme un débutant en php peux l'utiliser, car les indexes du Array
sont le nom SQL des colonnes de la BDD et l'indice est la condition ou
liaison dans la requete sql.


Le mieux serait encore que l'utilisateur ne saches même pas que ce
soit une requête SQL. Mais ça requiert un peu de boulot.

Cepandant, je fait face a un chef de projet qui me dit ne pas comprendre
mon choix en POO et pretent que le "à l'ancienne ..." est plus rapide et
plus clair,


Plus rapide en quoi ? À taper, c'est effectivement plus immédiat
quand on a l'habitude de créer des générateurs de requête SQL. Quand à
la clareté, franchement, quand on voit les horeurs à base de
concaténation qui gangrainent les applications PHP, j'ai comme un doute.

ce que je conteste, car le taux d'erreur sur l'ancienne
methode et plus grand et ne gere en aucun cas les erreur, si ce n'est au
prix d'un code repetitif et avec plus de variable, donc un script plus
long a charger et comprendre.


C'est surtout qu'il n'est pas facilement possible d'écrire des tests
pour des scripts écrits à l'arrache.

Que en pensez-vous et quel solution preferez-vous ou proposeriez vous,
voire un commentaire sur ce post ?


Il faut faire des compromis, il n'y a pas de solutions miracles. Mais
une chose est certaine : je trouve plus clair et error-proof un truc
dans ce genre :

<?php

$doc = null ;
try
{
$category = 'knives' ;
$products = $catalog->get('products')
->by_category($category)
->order_by('price')
->limit(20) ;

// $products->execute() ;
$page = count($products)
? new page_product_list($products)
: new page_404 ;
}
catch(exception $e)
{
$page = new page_500($e) ;
}
?>

Mais on pourrait discuter pendant des heures sur chaque choix que
j'ai fait dans cet exemple ;)