PHP quelle couche d'abstraction MySQL ?

Consultez la formation SEO spéciale Wordpress
par WebRankInfo / Ranking Metrics

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

PHP quelle couche d'abstraction MySQL ?

Message le Ven Déc 09, 2016 17:01

Bonjour

Pour terminer ce module de paiement Paypal pour mon site partenaire, je me suis mis en tête de programmer une couche d'abstraction MySQL.

J'utilise déjà PDO, et j'envisage une classe singleton ( Database ) pour les connexions, plus quelques fonctions ( = méthodes ) de classe :

Connexion : $conn = Database::getConnect();

Eventuellement des paramètres qui vont bien, ou des constantes.

Pour les résultats à une seule ligne ( select, insert, update, delete ) :

$array_result = $conn->num_fetch_row($sql) ( select : indices de champs par numéros ),
ou
$array_result = $conn->assoc_fetch row($sql); ( select : indices par noms de colonnes ).

( pour les autres que select, rendrait le code de retour ).

Pour les résultats à plusieurs lignes ( select uniquement ) :

Idem ( rows au lieu de row ) avec num_fetch_rows($sql) et assoc_fetch_rows($sql).

Dans le premier cas, un query ou un exec ( suivant type de requête ), suivi éventuellement ( select ), d'un fetch et cursorClose().

Dans le deuxième cas : prepare() => bindParam() => execute().

Le problème, serait de fixer le paramètre de prepare(), et ceux de bindParam().

Il faudrait donc, à partir de la requête MySQL, produire une chaîne traduisant les valeurs de critères après le(s) WHERE ( non suivis par SELECT ), en leur équivalents noms de colonnes préfixés par deux-points ( : ), et puis une array rendant les paramètres des bindParam().

Je comptais parser la requête MySQL, ( avec la librairie PHP-SQL-Parser-master de Github ) vers un arbre ( tree ), et pour chaque feuilles de type [expr_type]=const, remplacer [base_expr] par le [base_expr] de [expr_type] précédent ( = nom de la colonne comparée ).

J'ai mis dans un fichier texte, toutes les requêtes MySQL de mon site, je vais les classer par types ( complexité, syntaxe ) puis évaluer l'algorithme que je vais utiliser.

Merci de me dire de quelle manière vous avez résolu ce problème de couche d'abstraction SQL.

Respectueusement.


spout
WRInaute accro
WRInaute accro
 
Messages: 8337
Enregistré le: 14 Mai 2003

Re: PHP quelle couche d'abstraction MySQL ?

Message le Ven Déc 09, 2016 17:37

Je te conseille en librairie "standalone" Eloquent de Laravel:
https://github.com/illuminate/database
http://www.edzynda.com/use-laravels-eloquent-orm-outside-of-laravel/

Code: Tout sélectionner
$posts Post::all();
foreach (
$posts as $post) {
    echo 
$post->title;
    echo 
$post->category->name;
    echo 
$post->user->email;

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Ven Déc 09, 2016 18:31

Bonjour spout

Je vais voir si celà permet de faire des requêtes imbriquées, des requêtes complexes avec agrégats et je ne sais plus quoi.

J'ai rangé tous les types de requêtes select de mon site dans un fichier.

Je cherche ( surtout ) la performance en vitesse et la simplicité d'utilisation.

Merci beaucoup de ton aide.

Respectueusement.


spout
WRInaute accro
WRInaute accro
 
Messages: 8337
Enregistré le: 14 Mai 2003

Re: PHP quelle couche d'abstraction MySQL ?

Message le Ven Déc 09, 2016 18:56

Ca fait ORM et query builder et on px faire du "raw SQL" donc ça fait absolument tout.
Evidemment ce sera plus lent qu'autre chose car il "hydrate" (transforme) les resultset en objets PHP.

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Ven Déc 09, 2016 19:40

Bonjour spout

J'ai du traitement MySQL parfois pas très léger sur mon site.

J'ai mis dans un fichier ( et réduit ) toutes les syntaxes possible de select figurant dans mon site.

Je vais faire des parcours de l'arbre représentant la requête MySQL, en preorder récursif, pour reconstituer la requête MySQL traduite, en passant les valeurs intermédiaires dans une array à trois indices racines : Le tree intermédiaire, la requête MySQL traduite du prepare(), et l'array des paramètres de bindParam().

Je passerai en paramètre de cette fonction récursive, cette array triple, plus l'indicateur avant/après where, etc...

Je verrai çà ce week-end.

Respectueusement.

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Sam Déc 10, 2016 11:37

J'ajoute

Je suis mal barré, car je vais être obligé de découpler les prepare(), des bindParam() et execute().

En fin de compte, la seule fonctionnalité qu'il me reste à implémenter, est la production ( à partir du $query de départ ), des masques pour les prepare() et les bindParam().

Pensez-vous, que celà nécessite de transformer ce $query en arbre ( tree ) , ou que c'est possible algorithmiquement, de lire ce $query séquentiellement, et puis d'affecter la chaine du prepare(), et l'array des bindParam() ?

Il me semble, que la mise en arbre est gourmande en temps d'exécution.

Merci beaucoup de vos réponses.

Respectueusement.


spout
WRInaute accro
WRInaute accro
 
Messages: 8337
Enregistré le: 14 Mai 2003

Re: PHP quelle couche d'abstraction MySQL ?

Message le Sam Déc 10, 2016 12:15

ortolojf a écrit:Il me semble, que la mise en arbre est gourmande en temps d'exécution.

- Adjacency list (id/parent_id): oui car nécessite recursivité.
- MPTT (left/right): non
- Materialized path: non

Ressources:
https://www.sitepoint.com/hierarchical-data-database-2/
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
https://bojanz.wordpress.com/2014/04/25/storing-hierarchical-data-mate ... ized-path/
[...]

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Sam Déc 10, 2016 14:40

Bonjour spout

Je vais faire une très modeste fonction de parsing, qui sera en fait un très petit interpréteur de la $query.

Je n'ai pas besoin d'adapter ni d'utiliser ma librairie de parsing html.

Ce devrait être rapide. ;)

Respectueusement.

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Dim Déc 11, 2016 21:15

Rebond

Voilà, merci de tester à l'url :

https://www.pronostics-courses.fr/parse_function.php

Il suffit de donner le paramètre sql="instruction SQL" ( sans quotes simples ni doubles ) , qui est parsé pour en déduire les paramètres du prepare() et des bindParam().

Le bug : Il n'accepte pas d'espaces dans les valeurs ( constantes ou variables ) de WHERE.

Pour l'instant il ne traite que les SELECT.

Il affiche le sql du prepare() et les paramètres des bindParam().

Je vais voir pour les espaces.

Merci de vos suggestions.

Respectueusement.

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Dim Déc 11, 2016 23:16

Rebonjour

Le bug semble résolu.

Je n'ai plus qu'à adapter pour les INSERT UPDATE et DELETE.

Merci beaucoup de vos suggestions.

Respectueusement.

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Lun Déc 12, 2016 20:12

Rebonjour

Url : https://www.pronostics-courses.fr/parse_function.php

Voilà, j'ai fait cette petite fonction, qui à partir de l'ordre SQL, génère le paramètre de la fonction prepare(), et les paramètres des fonctions bindParam().

Merci de tester, en spécifiant un paramètre sql= ( sans quotes doubles ni simples autour ).

Valide théoriquement pour ces types d'instructions SQL : SELECT, INSERT, UPDATE, DELETE.

Pour l'instant en version alpha. ;)

Merci de me signaler les erreurs.

Respectueusement.


niap
WRInaute discret
WRInaute discret
 
Messages: 137
Enregistré le: 17 Oct 2009

Re: PHP quelle couche d'abstraction MySQL ?

Message le Lun Déc 12, 2016 20:15



Il faut tester comment ? Y a pas de champ ? 8O

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Lun Déc 12, 2016 20:45

Bonjour niap

Par exemple :

Code: Tout sélectionner

 https://www.pronostics-courses.fr/parse_function.php?sql=update CHEVAUX set NOMCH='aplusbegalix'  where NUMCH=345



Il ne faut pas mette d'apostrophes autour de la chaîne SQL, mais on peut en mettre où on veut à part çà.

Il ne faut pas d'espace avant ou après le signe égal du sql.

Par exemple : sql = SELECT ne marche pas.

Par contre, on peut mettre des espaces où on veut dans le paramètre SQL.

Merci beaucoup pour ton aide.

Respectueusement.

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mar Déc 13, 2016 0:07

niap a écrit:


Il faut tester comment ? Y a pas de champ ? 8O


Rebonjour niap

J'y ai mis un petit formulaire facile à remplir.

Merci beaucoup pour vos tests !

Mettez n'importe quel ordre SQL, du type select, ou insert, ou update, ou delete, il affiche le paramètre du prepare(), et puis les trois paramètres de chaque fonctions bindParam().

Ces deux fonctions, sont économiques en mémoire RAM, et plus performantes que les query() ou exec() directs.

Il va sans dire, que ces fonctions utilisent l'interface PDO de MySQL.

L'intérêt de ma fonction, est de simplifier le travail du programmeur SQL, je vais prochainement terminer mon interface d'abstraction MySQL.

Après, je n'aurai même plus besoin de songer aux détails de programmation, il y aura une fonction utilisant prepare() et bindParam() ( si besoin uniquement ), qui rendra l'array à deux indices des données ( en cas de lecture ), ou le code de retour sinon.

Pour le cas des prepare() séparés des bindParam() -> execute(), deux fonctions transparentes ( par exemple pour des boucles internes contenant des lectures/écritures de structures identiques. ).

Cà va me faciliter la vie, et accélérer beaucoup mon temps de développement.

Et puis, la vitesse d'exécution...

Bien à vous.

Respectueusement.


spout
WRInaute accro
WRInaute accro
 
Messages: 8337
Enregistré le: 14 Mai 2003

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mar Déc 13, 2016 6:16

Je vois vraiment pas l'intérêt de ton truc qui parse la requête SQL pour binder automatiquement les paramètres:
Code: Tout sélectionner
update CHEVAUX set NOMCH='aplusbegalix'  where NUMCH=345


Cette query tu dois quand même la construire en PHP:
Code: Tout sélectionner

$nomch 
= 'aplusbegalix';
$numch = 345;
$sql = "update CHEVAUX set NOMCH='$nomch'  where NUMCH=$numch"


En quoi c'est plus simple à ce que je t'ai montré:
ORM:
Code: Tout sélectionner
$cheval = Chevaux::find(345);
$cheval->nomch = 'aplusbegalix';
$cheval->save(); 


Query builder:
Code: Tout sélectionner
DB::table('chevaux')->where('id', 345)->update(['nomch' => 'aplusbegalix']); 


NB:
Code: Tout sélectionner
SELECT * FROM utilisateurs WHERE prenom LIKE '%ortolo%'

Ne fonctionne pas

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mar Déc 13, 2016 10:17

Bonjour spout

J'ai corrigé le problème.

J'avais omis de mettre le LIKE comme opérateur mathématique ( ou de comparaison ).

Je cherche avant tout la vitesse d'exécution.

Merci beaucoup de ton aide.

Respectueusement.

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mar Déc 13, 2016 21:59

Rebonjour

Je crois avoir bien avancé la mise au point de cette fonction.

Pour spout : Cette fonction n'est pas l'interface d'abstraction SQL.

Elle en constituera simplement le composant principal, avec la surcouche ( légère ;) ) en plus.

J'aurais besoin que vous testiez.

Normalement, la syntaxe supportée devrait inclure les sous-requêtes( avec IN et NOT IN ) , l'opérateur BETWEEN, les opérateur arithmétiques courants, mais il doit certainement manquer des opérateurs.

Je ne pratique que de la manipulation de données, pas d'administration.

On peut spécifier les mots-clés en majuscules ou minuscules.

Respectueusement.


niap
WRInaute discret
WRInaute discret
 
Messages: 137
Enregistré le: 17 Oct 2009

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mar Déc 13, 2016 23:03

$sql_query = SELECT * FROM test WHERE t.catId<>0

Erreur WHERE dans la fonction parse_myql().
2eme operande manquant.
$sql_prepare =


Warning: Invalid argument supplied for foreach() in /var/www/html/parse_function.php on line 1273
;-)

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mer Déc 14, 2016 8:46

Pardon

Je n'utilise jamais <> , toujours !=

J'inclus <> immédiatement aux opérateurs arithmétiques.

Respectueusement.


spout
WRInaute accro
WRInaute accro
 
Messages: 8337
Enregistré le: 14 Mai 2003

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mer Déc 14, 2016 9:01

T'as pas fini alors:
Code: Tout sélectionner
SELECT COALESCE(nickname, firstname, 'Mr./Mme.') || ' ' || lastname AS fullname FROM utilisateurs
SELECT * FROM utilisateurs WHERE id = '1'; DROP TABLE utilisateurs;--

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mer Déc 14, 2016 10:16

Voilà c'est fait.

Merci niap, la valeur 0 était considérée comme vide par empty().

J'ai eu des problèmes de regex multiples instantanées qui portaient sur le même élément plusieurs fois.

Pour spout : Je ne fais jamais en PHP d'instructions différentes qui se suivent ( séparées par des points-virgules ).

Ta première instruction SQL ( simple ) passe.

Maintenant, ma fonction attend les visiteurs. ;)

Merci beaucoup de votre aide.

Respectueusement.


spout
WRInaute accro
WRInaute accro
 
Messages: 8337
Enregistré le: 14 Mai 2003

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mer Déc 14, 2016 10:32

ortolojf a écrit:Pour spout : Je ne fais jamais en PHP d'instructions différentes qui se suivent ( séparées par des points-virgules ).

Mais ceux qui exploitent les failles d'injection SQL oui, donc il faut faire gaffe.


niap
WRInaute discret
WRInaute discret
 
Messages: 137
Enregistré le: 17 Oct 2009

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mer Déc 14, 2016 10:44

Mais s'il génère une requête préparée, il devrait être paré face aux injections sql, non ?

$sql_query = SELECT * FROM test WHERE t.catId<10 UNION select * from test2 t2 where t2.catId='10'

$sql_prepare = SELECT * FROM test WHERE t.catId<:t_catId_1: UNION SELECT * FROM test2 t2 WHERE t2.catId=:t2_catId_2:

$sql_bindParam[0] = :t_catId_1:
$sql_bindParam[1] = 10
$sql_bindParam[2] = 1

$sql_bindParam[0] = :t2_catId_2:
$sql_bindParam[1] = '10'
$sql_bindParam[2] = 2

J'imagine que $sql_bindParam[2] est le type de données ?
Dans ce cas ta fonction semble considérer que 10 est différent de '10'.
Modifié en dernier par niap le Mer Déc 14, 2016 10:51, modifié 1 fois.


spout
WRInaute accro
WRInaute accro
 
Messages: 8337
Enregistré le: 14 Mai 2003

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mer Déc 14, 2016 10:50

Oui mais il génère une requête préparée automatiquement.
Donc si:
Code: Tout sélectionner
$id = $_GET['id'];
$sql = "SELECT * FROM utilisateurs WHERE id=$id";

Si on passe ?id=1

Code: Tout sélectionner
$sql_prepare = SELECT * FROM utilisateurs WHERE id=:id_1:

$sql_bindParam[0] = :id_1:
$sql_bindParam[1] = 1
$sql_bindParam[2] = 1


Si on passe ?id= ; DROP TABLE utilisateurs; --

Code: Tout sélectionner
$sql_prepare = SELECT * FROM utilisateurs WHERE id=:id_1: ; DROP TABLE utilisateurs; --

$sql_bindParam[0] = :id_1:
$sql_bindParam[1] = ''
$sql_bindParam[2] = 2

BOUM


niap
WRInaute discret
WRInaute discret
 
Messages: 137
Enregistré le: 17 Oct 2009

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mer Déc 14, 2016 10:56

Ah oui effectivement, là c'est foutu.

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Mer Déc 14, 2016 12:23

Bonjour

Effectivement $sql_bindParam[2] est le type de données.

Effectivement, j'ai dans ma database des champs entiers du type varchar.

Si je veux changer celà, je peux changer ma fonction : $this->PDO_type($str).

Merci me dire si c'est nécessaire. Mais celà m'obligerait à changer les type de ces champs.

Quant à la sécurisation contre les hacks, c'est la couche d'abstraction ( en amont ) qui le fera.

J'ai rajouté à l'instant les mots-clés : SHOW, CREATE, et DROP.

Merci beaucoup de votre aide.

Respectueusement.

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Jeu Déc 15, 2016 17:08

Bonjour

Maintenant les INSERT avec VALUES sont théoriquement supportés.

J'avais des problèmes avec les valeurs avec espaces.

Merci de tester pour tous les type d'instructions SQL.

Quand ce sera au point, j'indexerai les bindParam par les noms de colonnes au lieu de chiffres.

J'espère que ce sera possible dans tous les cas, avec des structures de queues ou des array.

J'ai l'intention pour la couche d'abstraction, de mettre des set${nom_colonne}[$value) dans la classe Database.

Amicalement.

ortolojf
WRInaute accro
WRInaute accro
 
Messages: 2653
Enregistré le: 14 Aoû 2002

Re: PHP quelle couche d'abstraction MySQL ?

Message le Ven Déc 16, 2016 11:18

Bonjour

Je suis en train de concevoir l'interface d'abstraction de mon soft.

Le problème, est de découpler les prepare() des bindParam() et execute().

Pour mémoriser les paramètres, j'envisage une structure de de pile ( stack ).

En effet, les prepare() ( réels ) sont censés être "nestés".

J'envisage les méthodes suivantes de la classe Database :


1) my_prepare($sql)

2) fill_bindParam($array_values)

3) my_bindParam(void)

4) myExecute(void)

5) delete_bindParam(void)

6) my_queryAll($sql)

Le 1) produira le $sql_prepare, lancera le $conn->prepare($sql_prepare) , et produira en interne une $array_masque contenant le masque à remplir pour la fonction fill_bindParam($array_values).

Ceci, sauf si l'array_masque est non affectée, ce qui peut se produire quand le $sql ne comporte pas de variables ou de constantes PHP ( ç'est-à-dire s'il n'y a aucune value dans le $sql ).

Dans ce cas, appel à ma fonction aquery() de mon interface myPDO.

Sinon, cette méthode incrémentera le compteur servant d'indice pour la stack ( pile ) mémorisant les valeurs des $array_masque ( prévu dans le cas des boucles imbriquées ).

Le 2) aura en argument les values à intégrer dans le masque $array_masque courant, et le modifiera.

Le 3) déclenchera les bindParam() réelles adéquates,

Le 4) déclenchera le $conn->execute(),

Est-il opportun de joindre les 2), 3) et 4) ?

Le 5) déclenchera les unset pour l'indice de pile courant ( dépilera de la stack et donnera accès en interne ( dans la classe ) à l'array_masque de degré inférieur.

Le 6) sera une méthode à part, censée faire tout en un :

Suivant critère ( à définir ) , soit lancement d'un $conn->aquery($sql) classique ( de mon interface
myPDO déjà faite), soit lancera l'équivalent des 1) à 6), sans empilage ni dépilage.

Si SELECT, rendra l'array à deux indices lue en mémoire RAM.

Sinon, code de retour ( autre chose que SELECT ).

Merci me donner vos suggestions sur ce type d'intégration.

Celà vous paraît-il correct ou non ?

Respectueusement.


spout
WRInaute accro
WRInaute accro
 
Messages: 8337
Enregistré le: 14 Mai 2003

Re: PHP quelle couche d'abstraction MySQL ?

Message le Ven Déc 16, 2016 11:33

ortolojf a écrit:1) my_prepare($sql)

2) fill_bindParam($array_values)

3) my_bindParam(void)

4) myExecute(void)

5) delete_bindParam(void)

6) my_queryAll($sql)


PHP n'est pas pas encore assez pourri que t'as pas réussi à te décider entre snake_case et camelCase ? :mrgreen:
Maintenant il y a des coding standards: http://www.php-fig.org/psr/, pour les méthodes c'est au choix mais il faut rester cohérent.

NB: tu ne cesses de réinventer la roue des frameworks qui sont testés unitairement et largement utilisés.


niap
WRInaute discret
WRInaute discret
 
Messages: 137
Enregistré le: 17 Oct 2009

Re: PHP quelle couche d'abstraction MySQL ?

Message le Ven Déc 16, 2016 12:06

spout a écrit:PHP n'est pas pas encore assez pourri que t'as pas réussi à te décider entre snake_case et camelCase ? :mrgreen:

:lol:
C'est clair qu'il faut que tu fasse un choix ortolojf.
Perso j'ai fait les choix suivant :
- tout est nommé en camel case
- les fonctions débutent toujours avec une majuscule
- les fonctions sont nommés dans l'ordre inverse de leur fonctionnalité
- les variables toujours avec une minuscule
- les arguments de fonction débutent toujours avec un a minuscule
- les variables globale toujours avec un g minuscule

C'est quoi la finalité de cette interface d'abstraction ?
Ouvrir ta base de données à d'autres sites ?


Formation recommandée sur ce thème :

Formation SEO spéciale Wordpress : apprenez à optimiser le référencement naturel d'un site fait avec Wordpress... Formation Ranking Metrics animée par un expert SEO / Wordpress.

Tous les détails sur le site Ranking Metrics : programme, prix, dates et lieux, inscription en ligne.

Lectures recommandées sur ce thème :