IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

algorithme de requête


Sujet :

Langage PHP

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2017
    Messages
    337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2017
    Messages : 337
    Points : 61
    Points
    61
    Par défaut algorithme de requête
    Bonjour,

    Dans une interface d'un de mes back-office l'utilisateur doit effectuer une requête. Une requête avec les mots-clés "family" pour famille, "morphological_group" pour groupe morphologique, "taxonomical_group" pour groupe taxonomique, "conditions_of_use" pour conditions d'utilisations, des "=" pour les valeurs (encerclées par des guillemets doubles ("), des ET (majuscule), des OU (majuscule), des parenthèses ouvrantes et fermantes et des espaces, exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (family="tintin" ET conditions_of_use="titi") OU taxonomical_group="toto"
    Il y a deux étapes dans l'algorithme :
    vérifier la syntaxe (attention il peut y avoir des espaces en trop)
    traiter la requête (ça je m'en occuppe)

    Je voudrais donc un algorithme de vérification de la syntaxe de la requête SVP

    Merci

    Bien cordialement

  2. #2
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 888
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 888
    Points : 6 632
    Points
    6 632
    Par défaut
    Et que doit faire cet algorithme en cas d'erreur de syntaxe, doit-il simplement indiquer si la syntaxe est correcte ou pas, ou bien doit-il en plus préciser la nature de l'erreur?

  3. #3
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2017
    Messages
    337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2017
    Messages : 337
    Points : 61
    Points
    61
    Par défaut
    il doit afficher un message d'erreur donc la nature de l'erreur

  4. #4
    Membre expert
    Avatar de cavo789
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2004
    Messages
    1 785
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 785
    Points : 3 048
    Points
    3 048
    Par défaut
    Bonjour

    Tu cherches donc un SQL Linter; tu as cherché sur Ggle ? Voici un lien https://github.com/cweiske/php-sqllint qui semble fonctionner en tant que dépendance composer. Voir ensuite avec la doc comment s'en servir.

  5. #5
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2017
    Messages
    337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2017
    Messages : 337
    Points : 61
    Points
    61
    Par défaut
    non ce n'est pas du tout du SQL mais un langage maison avec seulement 5 mots-clés

  6. #6
    Membre expert
    Avatar de cavo789
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2004
    Messages
    1 785
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 785
    Points : 3 048
    Points
    3 048
    Par défaut
    Ok, le mot requête m'aura probablement laissé croire que c'était une requête SQL.

    Du coup, comme c'est du maison, je pense que tu vas devoir te taper des regex.

  7. #7
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2017
    Messages
    337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2017
    Messages : 337
    Points : 61
    Points
    61
    Par défaut
    non pas des regex car il faut découper la requête je pense à une solution avec des arbres

  8. #8
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 333
    Points : 15 677
    Points
    15 677
    Par défaut
    effectivement, une expression régulière ne suffit parce qu'il s'agit d'un grammaire et donc il faut par exemple utiliser un automate à états finis :
    https://fr.wikipedia.org/wiki/Automate_fini

    en faisant une recherche en anglais "finite-state automaton php" j'ai trouvé ça mais je n'ai pas testé :
    https://github.com/tonix-tuft/status-quo
    https://github.com/the-matrix/finite-state-machine

  9. #9
    Membre expert
    Avatar de cavo789
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2004
    Messages
    1 785
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 785
    Points : 3 048
    Points
    3 048
    Par défaut
    Je serais curieux de voir cela en musique cela a l'air bien mystérieux 😉. En l'état, je me dis que c'est une variable suivie d'un signe égal puis de guillemets avec, dans la zone guillemets, du contenu. Ça, une regex fait le job.

    On connaît la liste des variables possibles et on sait qu'on aura des ET ainsi que des OU.

    La problématique serait de bien jouer sur la position des parenthèses.

    Je serais réellement intéressé de voir une approche arbre.

  10. #10
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2017
    Messages
    337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2017
    Messages : 337
    Points : 61
    Points
    61
    Par défaut
    oui je ne veux pas d'un automate fini ça me semble une massue pour tuer une mouche, je cherche plus un pur algo en PHP fait main

  11. #11
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 888
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 888
    Points : 6 632
    Points
    6 632
    Par défaut
    Citation Envoyé par mathieu Voir le message
    effectivement, une expression régulière ne suffit parce qu'il s'agit d'une grammaire...
    Attention à ne pas confondre la notion d'expression régulière issue des sciences de l'informatique qui est un langage de description de chaînes dont le vocabulaire se limite à des littéraux, des classes, des quantificateurs, des groupes, et les divers outils qu'on appellent toujours "expression régulière" (par abus de langage, de par leur provenance) et qui équipent les divers languages de programmation.

    Certains de ces outils sont tout à fait capable de décrire une grammaire comme c'est le cas en PHP (ou Perl ou Ruby), car les moteurs de regex qu'ils utilisent permettent de faire référence à des sous-patterns , ce qui rend notamment possible la description d'éléments d'un langage de manière récursive (chose qui n'est pas possible avec les expressions régulières "théoriques").

  12. #12
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2017
    Messages
    337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2017
    Messages : 337
    Points : 61
    Points
    61
    Par défaut
    désolé mais finalement je vais aussi avoir besoin du traitement, en fait en entrée de l'algorithme il y a un ensemble de plantes, et pour chaque plante je peux trouver les valeurs booléennes des expressions du type conditions_of_use="titi". Donc une expression régulière ne sera pas suffisante et en plus on ne pourra pas mettre de messages d'erreurs

  13. #13
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 333
    Points : 15 677
    Points
    15 677
    Par défaut
    Citation Envoyé par CosmoKnacki Voir le message
    Certains de ces outils sont tout à fait capable de décrire une grammaire comme c'est le cas en PHP (ou Perl ou Ruby), car les moteurs de regex qu'ils utilisent permettent de faire référence à des sous-patterns , ce qui rend notamment possible la description d'éléments d'un langage de manière récursive (chose qui n'est pas possible avec les expressions régulières "théoriques").
    c'est noté, je n'avais jamais poussé ma réflexion jusqu'à là. merci pour cette information.

  14. #14
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 888
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 888
    Points : 6 632
    Points
    6 632
    Par défaut
    Citation Envoyé par Sylvain255 Voir le message
    oui je ne veux pas d'un automate fini ça me semble une massue pour tuer une mouche, je cherche plus un pur algo en PHP fait main
    Dans ce cas c'est que tu n'as pas bien vu la taille de la mouche car c'est loin d'être évident (même avec un vocabulaire limité comme ton langage de requête). Utiliser un outil dédié n'est donc pas une mauvaise idée.

    Une approche classique consiste à tokenizer la chaîne dans un premier temps en éléments atomiques ( une parenthèse, un signe égal, une chaîne entre guillemets, un ou une succession de caractères blancs, un nom de colonne, autre), pour ensuite vérifier si la succession de ces éléments est conforme à la syntaxe. Par exemple, un nom de colonne (disons family) doit être suivi d'éventuels caractères blancs puis d'un signe égal, lui-même suivi d'éventuels caractères blancs puis d'une chaîne entre guillemets. Bien évidemment ces vérifications se font avec une batterie de if elseif else et autres structures de contrôle. C'est le gros du travail, un travail laborieux.

  15. #15
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 888
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 888
    Points : 6 632
    Points
    6 632
    Par défaut
    Juste une "proof of concept": Une pattern permettant à la fois de vérifier la syntaxe, et en cas de violation de celle-ci, de renvoyer la partie de la chaîne du début jusqu'à l'erreur (exclue). Pour ce faire, je définis d'une part des sous-patterns qui décrivent la syntaxe correcte, et d'autre part les sœurs diaboliques de ces mêmes sous-patterns qui renverront la chaîne partielle jusqu'à l'erreur.
    Afin de connaître la nature de l'erreur, j'utilise des marqueurs ((*MARK:label) ou (*:label) en abrègé) qui à la base sont utilisés pour le débogage des patterns et qui permettent de savoir quel chemin le moteur de regex a empreinté. Il se trouve que preg_match_all renseigne le dernier marqueur rencontré. J'utilise également (*ACCEPT) qui permet la réussite inconditionnelle d'une sous-pattern. La forme (*ACCEPT:label) n'est que la version plus courte de (*MARK:label)(*ACCEPT).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    $pattern = <<<'REGEX'
    ~
    (?(DEFINE)
        (?<lvalue>    family | conditions_of_use | taxonomical_group    )
        (?<rvalue>    " [^\\"]*+ (?s: \\ . [^\\"]* )*+ "                )
        (?<operator>  ET | OU                                           )
        
        (?<operate>   \s+ \g<operator> \s+                              )
        (?<assertion> \g<lvalue> \s* = \s* \g<rvalue>                   )
        (?<subquery>  \g<assertion> (?: \g<operate> \g<assertion> )*+   )
        (?<query>     (?: \g<subquery> | \( \s* \g<query> \s* \) )
                      (?: \g<operate> \g<query> )*+                     )
                      
      # partial matches
        (?<p_operate>
            \s+ \g<operator> (?!\s) (*:ERR_MISSING_WS_AFTER_OPERATOR)
          | (?= \g<operator> ) (*:ERR_MISSING_WS_BEFORE_OPERATOR)    
          | \s+ [OE]                                                    )
        
        (?<p_assertion>
            (?: \g<lvalue> \s* | \b (*ACCEPT:ERR_UNKNOW_LVALUE) )
            (*ACCEPT:ERR_MISSING_EQUAL_SIGN)?? = \s*
            (*ACCEPT:ERR_MISSING_RVALUE)?? \g<rvalue>                   )
                        
        (?<p_subquery>
            \g<subquery>
            (?: \g<operate> \g<p_assertion> | \g<p_operate> )
          | \g<p_assertion>                                             )
            
        (?<p_query>
            (?: \( \s* (?(?=\)) (*ACCEPT:ERR_EMPTY_SUBQUERY) ) )*?
            (?: \g<query> 
                (?: \s* \z (*:ERR_MISSING_CLOSING_PARENTHESIS)
                  | \g<operate> \g<p_query>?
                  | \g<p_operate>
                )?
              | \g<p_subquery>
            )                                                           )
    )
     
    \A \s* (*:ERR_UNEXPECTED_CHARACTER)
    (?: \g<query> \s* \z (*:ERR_NONE) | \g<p_query> | \z (*:ERR_EMPTY_QUERY) )?
    ~x
    REGEX;
     
    $str = ' family="machin" ET taxonomical_group="chose" OU (conditions_of_use="bidule" OU ((((family="truc" E) OU ( )))
             ET family="machin-chouette") OU taxonomical_group="truc-bidule"';
     
    $start = microtime(true);
    preg_match_all($pattern, $str, $matches, PREG_SET_ORDER);
    $end = microtime(true);
     
    var_dump($matches[0]);
     
    printf('%.1e s', $end - $start);

  16. #16
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2017
    Messages
    337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2017
    Messages : 337
    Points : 61
    Points
    61
    Par défaut
    Merci, je vais demander à l'un de mes anciens profs d'algorithmie de fac qui est un ami de m'aider. Je pense qu'il trouvera une solution par arbres. Mais moi je me souviens qu'en fac je n'avais eu que 7 dans sa matière d'algorithmie avancée (ou l'on avait vu des problèmes bien plus compliqués que celui-ci) donc je ne maîtrise pas les arbres qui sont très complexes. Ce qui ne m'empêche pas, je pense, d'être un bon programmeur PHP car c'est très rare qu'on ait besoin d'arbres en programmation PHP.

  17. #17
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2017
    Messages
    337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2017
    Messages : 337
    Points : 61
    Points
    61
    Par défaut
    je vous posterai la solution arbres mais par fichier joint car ça risque d'être long !

  18. #18
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2017
    Messages
    337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2017
    Messages : 337
    Points : 61
    Points
    61
    Par défaut
    j'ai testé le regexp mais j'ai une erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ( ! ) Warning: preg_match_all(): Compilation failed: quantifier does not follow a repeatable item at offset 976 in C:\wamp64\www\test_requete\index.php on line 51
    Call Stack
    #	Time	Memory	Function	Location
    1	0.0006	412232	{main}( )	...\index.php:0
    2	0.0006	412256	preg_match_all ( )	...\index.php:51
     
    C:\wamp64\www\test_requete\index.php:54:null
     
    6.0e-4 s
    ........
    et si je met une requête pas bonne ça ne me dit pas les erreurs
    ........
    car si en effet le regexxp marche je peux me passer des arbres en faisant des str_replace sur la requête maison et en l'injectant dans une requête SQL

  19. #19
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 333
    Points : 15 677
    Points
    15 677
    Par défaut
    Citation Envoyé par Sylvain255 Voir le message
    j'ai testé le regexp mais j'ai une erreur :
    quelle version de php et pcre avez vous ?
    j'ai testé avec php 7.2 (pcre version 8.40) et j'ai une erreur, un avertissement que je n'ai pas compris.
    et ensuite j'ai testé avec php 8.0 (pcre version 10.36) et le code de CosmoKnacki fonctionnait bien.

  20. #20
    Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2017
    Messages
    337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2017
    Messages : 337
    Points : 61
    Points
    61
    Par défaut
    PHP 7.3.21 mais je ne peux changer ma version de PHP, c'est pour une mise en production sur un serveur qui n'accepte que PHP 7.4, mais dans le futur nous pensons le passer en PHP 8, l'idéal serait de mettre "if PHP version=7 alors " "if PHP version = 8 alors"

Discussions similaires

  1. Algorithme pour une requête
    Par Madfrix dans le forum Requêtes
    Réponses: 2
    Dernier message: 11/12/2012, 12h25
  2. Problème de requête (algorithme ?)
    Par darigaaz dans le forum Requêtes
    Réponses: 3
    Dernier message: 07/04/2010, 14h59
  3. Requête sur "algorithme"
    Par Dr_No dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 25/06/2009, 10h06
  4. Algorithme de randomisation ... ( Hasard ...? )
    Par Anonymous dans le forum Assembleur
    Réponses: 8
    Dernier message: 06/09/2002, 14h25
  5. Algorithme génétique
    Par Stephane.P_(dis Postef) dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 15/03/2002, 17h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo