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

PHP & Base de données Discussion :

Eviter les balises HTML dans une requête SQL


Sujet :

PHP & Base de données

  1. #1
    Membre actif
    Eviter les balises HTML dans une requête SQL
    Bonjour à tous,

    J'ai un petit moteur de recherche interne qui va chercher le contenu texte d'une colonne, mais je souhaiterais qu'il ne tienne pas compte des balises HTML.
    Exemple : si je cherche le mot "target", il va faire ressortir les textes contenant un lien du type <a href="url" target="_blank">.
    Existe-t-il un moyen pour que la recherche ne s'effectue pas sur du texte contenu entre ces balises ?

    Merci d'avance pour vos pistes éclairées !
    Le mieux n'est pas forcément l'ennemi du bien.

  2. #2
    Membre expert
    Bonjour, ceci semble répondre à ta demande ?

    https://www.php.net/strip-tags

    edit :

    Ou plus exactement, cette fonction faite par un développeur (commentaire 40, si elle fonctionne, elle donne exactement ce que tu cherches).
    https://www.php.net/manual/fr/functi...ags.php#110280
    Mes billets de blog : un billet = une problématique précise
    It's easier to be friends with lots of people online than one person in person!

  3. #3
    Membre actif
    Merci Dendrite mais strip_tags empêche l'affichage du code html. Ce que je cherche à éviter, c'est que la requête balaie le texte compris dans des balises.
    Je vais regarder plus attentivement la fonction envoyée, mais a priori, c'est la même chose, elle modifie l'affichage en supprimant les balises html.
    Le mieux n'est pas forcément l'ennemi du bien.

  4. #4
    Invité
    Invité(e)
    Bonjour,

    Je ne vois pas ce qui t'empêche de :
    • Faire la recherche sur le texte sans balises (strip_tags)
    • Afficher le texte formaté (avec balises) concerné

  5. #5
    Invité
    Invité(e)
    Bon,
    après moult tentatives infructueuses, il semble qu'on puisse s'en sortir directement dans la requête SQL :

    Code SQL :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT *
    FROM ma_table
    WHERE
    	le_texte_html LIKE '%le_mot%'
    AND
    	le_texte_html NOT REGEXP '.*<[^>]*le_mot[^>]*>.*'
    ;


    [EDIT] Argh...
    Ça ne va pas fonctionner comme voulu si le mot est à la fois dans et en dehors des balises.
    ex. <a href="le_mot.php">le_mot</a>.

  6. #6
    Membre actif
    Faire la recherche sur le texte avec strip_tags, je ne vois pas comment.
    En revanche, je retiens ta proposition de code avec NOT REGEXP.

    EDIT :
    Argh également : en effet, ça ne trouve pas les mots répétés dans et hors balise.
    Le mieux n'est pas forcément l'ennemi du bien.

  7. #7
    Invité
    Invité(e)
    Alors on passe en mode "bourrin", à la "RAMBO" :

    Code sql :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SELECT *
    FROM ma_table
    WHERE
    (
    	le_texte_html LIKE '%le_mot%'
      AND
    	le_texte_html NOT REGEXP '.*<[^>]*le_mot[^>]*>.*'
    )
    OR
    (
    	le_texte_html LIKE '%le_mot%le_mot%'
      AND
    	le_texte_html REGEXP '.*<[^>]*le_mot[^>]*>.*'
    )
    ;

    re-Arghhh....
    Non plus... si le mot est DANS DEUX balises !
    ex. : <a href="le_mot.php?var=1">truc</a>...<a href="le_mot.php?var=2">machin</a>.


    Sinon, j'ai trouvé ça : How to remove HTML tag using SQL?
    Code SQL :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
    CREATE FUNCTION dbo.RemoveTag (@String VARCHAR(MAX))
    RETURNS VARCHAR(MAX) AS
    BEGIN
        DECLARE @Start INT
        DECLARE @End INT
        DECLARE @Length INT
     
    SET @Start = CHARINDEX('&lt;',@String)
    SET @End = CHARINDEX('&gt;',@String,CHARINDEX('&lt;',@String))
    SET @Length = (@End - @Start) + 1
     
    WHILE @Start &gt; 0 AND @End &gt; 0 AND @Length &gt; 0
        BEGIN
            SET @String = STUFF(@String,@Start,@Length,'')
            SET @Start = CHARINDEX('&lt;',@String)
            SET @End = CHARINDEX('&gt;',@String,CHARINDEX('&lt;',@String))
            SET @Length = (@End - @Start) + 1
        END
     
        RETURN LTRIM(RTRIM(@String))
    END)

    Mais là, ça dépasse mes compétences.

  8. #8
    Membre actif
    En effet, c'est un peu "bourrin" (c'était pas ma guerre...)
    Je ne rejette pas l'idée mais je vais essayer de creuser un truc un peu plus propre, surtout que ce n'est pas la seule condition (il y a recherche sur plusieurs colonnes), le tout pour plusieurs mots (recherche découpée en mots clés).
    Ca risque de faire une requête de 2 km de long...

    Pour la fonction Removetag, là, j'avoue que c'est en dehors de mes compétences, je ne comprends pas le code.
    Le mieux n'est pas forcément l'ennemi du bien.

  9. #9
    Invité
    Invité(e)
    Autre axe de recherche :

    1- créer une nouvelle colonne le_texte_txt.
    2- boucler sur toutes les lignes,
    3- et tester (en PHP) sur OU faire un UPDATE de la table (et tester sur la colonne colonne le_texte_txt)
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    $le_texte_txt = strip_tags($row['le_texte_html']);

    Mais là, c'est du "bourrin 2ème Dan".


    J'avais aussi cherché du coté des REGEX en SQL, mais il semble que ça manque cruellement de fonctions avec REGEX...

    Ça aurait pourtant pu faire la farce.

  10. #10
    Membre actif
    Merci infiniment pour tous tes efforts, mais en effet, ça me semble un peu poussif...
    Le mieux n'est pas forcément l'ennemi du bien.

  11. #11
    Expert confirmé
    Citation Envoyé par jreaux62 Voir le message
    Autre axe de recherche :

    1- créer une nouvelle colonne le_texte_txt.
    2- boucler sur toutes les lignes,
    3- et tester (en PHP) sur OU faire un UPDATE de la table (et tester sur la colonne colonne le_texte_txt)
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    $le_texte_txt = strip_tags($row['le_texte_html']);

    Mais là, c'est du "bourrin 2ème Dan".
    Moi, je ne trouve pas ça bourrin du tout et ajouter une colonne avec le texte brut est pour moi la seule méthode qui vaille (à part peut-être en allant encore plus loin et en créant une table de mots-clés et une table pour associer les ids des mots-clefs avec ceux des textes, c'est plus performant mais moins souple).

    Citation Envoyé par Freedolphin
    Merci infiniment pour tous tes efforts, mais en effet, ça me semble un peu poussif...
    Ça n'a rien de poussif, c'est clairement la bonne façon de faire.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  12. #12
    Membre actif
    En effet, "poussif" n'est peut-être pas le bon mot, disons plutôt "contraignant".
    Cela m'oblige à dupliquer tous les textes dans une nouvelle colonne, et à prévoir l'incrémentation de cette nouvelle colonne pour les prochaines pages.
    C'est faisable, mais je pensais qu'une petite fonction sql pouvait exister.
    Le mieux n'est pas forcément l'ennemi du bien.

  13. #13
    Invité
    Invité(e)
    1-
    Citation Envoyé par CosmoKnacki Voir le message
    Moi, je ne trouve pas ça bourrin du tout....
    @CosmoKnacki
    Là où c'est "bourrin", c'est de faire l'UPDATE de toute la table à chaque recherche !

    La bonne méthode serait :
    • de remplir la colonne le_text_txt au moment du TRAITEMENT d'AJOUT/MODIFICATION de l'"article" !
    • tout en mettant le texte formaté dans la colonne le_texte_html, qui servira pour l'affichage

    De fait, au moment de la recherche, on utilise directement cette colonne le_text_txt.

    Donc, techniquement, il suffit de :
    • modifier les scripts INSERT / UPDATE des "articles"
    • faire un UPDATE de la table (1 seule fois), pour les "articles" déjà créés.


    2-
    Citation Envoyé par Freedolphin Voir le message
    ...mais je pensais qu'une petite fonction sql pouvait exister.
    Comme je l'ai dit, il manque de fonction SQL avec REGEX.

    On pourrait, avec une telle fonction SQL, obtenir un équivalent strip_tags() (donc, le texte "nettoyé" des balises HTML), sur lequel faire la recherche, SANS avoir besoin de l'enregistrer en BDD.

    3- Pour ma part, j'ai fini par..... ignorer ce problème.

  14. #14
    Membre actif
    En effet, cette méthode est propre et efficace, elle demande juste un peu de temps et d'organisation, mais c'est une bonne solution.
    Merci à vous deux.

    Quant à ignorer le problème, c'est une option, mais ce n'est pas le genre de la maison, j'aime perfectionner la pertinence des résultats d'un moteur.

    Au moins, j'ai maintenant la certitude que la fonction que j'avais en tête n'existe pas. Etonnant à notre époque, mais comme quoi, il reste des trucs à inventer.
    Le mieux n'est pas forcément l'ennemi du bien.

  15. #15
    Invité
    Invité(e)
    De toute façon, avec une fonction comme REGEXP_REPLACE() dans une requête SQL, ça risque de réduire fortement les performances (d'autant plus si ça doit s'appliquer à plusieurs colonnes).

    Alors, que CONCEVOIR correctement la table (avec le_text_html et le_text_txt) est tout-à-fait performant, puisque tout a été prévu en amont.

  16. #16
    Expert confirmé
    Citation Envoyé par jreaux62 Voir le message
    La bonne méthode serait :
    • de remplir la colonne le_text_txt au moment du TRAITEMENT d'AJOUT/MODIFICATION de l'"article" !
    • tout en mettant le texte formaté dans la colonne le_texte_html, qui servira pour l'affichage

    De fait, au moment de la recherche, on utilise directement cette colonne le_text_txt.

    Donc, techniquement, il suffit de :
    • modifier les scripts INSERT / UPDATE des "articles"
    • faire un UPDATE de la table (1 seule fois), pour les "articles" déjà créés.
    Je croyais que c'était ce que tu suggérais dans ton précédent post (et ce que j'avais en tête).
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus