Plugin « Critère {mots} »

Permettre de sélectionner facilement des objets SPIP ayant un ou des mots clefs en communs.

Présentation

Il peut arriver parfois de vouloir sélectionner des objets SPIP (articles, rubriques, sites etc.), ayant un certains nombre de mot clefs communs.

Par exemple, je voudrais sélectionner les articles ayant les mots clefs « fruits » et « desserts », mais pas ceux qui n’ont que « desserts » ou que « fruits ».

Une telle opération, bien que possible, est assez difficile en SPIP ... sauf si vous utilisez ce plugin.

Il s’installe comme n’importe quel plugin.

Il propose trois critères :
-  {mots}
-  {mots_selon_id}
-  {mots_selon_titre}

Dans une boucle, il ne faut utiliser qu’un seul de ces critères.

Le critère {mots}

Prenons un exemple :

<BOUCLE_art(ARTICLES){mots}>
#TITRE
</BOUCLE_art>

Cette boucle sélectionnera les articles ayant tous les mots clefs passés en paramètres d’environnement dans un tableau « mots ».

Comment passer ces mots-clefs en paramètres d’environnement ?

Typiquement, sur une page principale (non incluse), via des paramètres dans l’url. Par exemple : http://www.toto.fr/?page=toto&amp;mots[0]=1&amp;mots[1]=2.

Ici, j’ai passé dans le tableau ’mots’ les valeurs 1 et 2. Les articles associés, à la fois au mot dont l’id est 1 et à celui dont l’id est 2 seront sélectionnés [1].

Les valeurs du tableau ’mots’ peuvent être des identifiants de mots (1, 2) ou des titres de mots (« fruits », « desserts »).

Attention au cas où des mots clefs sont uniquement sous forme de nombre ...

Le critère {mots_selon_id}

Il fonctionne exactement comme le critère {mots}, à ceci près que les valeurs du tableau ’mots’ sont forcément des identifiants de mots (1,2).

Le critère {mots_selon_titre}

Il fonctionne exactement comme le critère {mots}, à ceci près que les valeurs du tableau ’mots’ sont forcément des titres de mots (« fruits »,« desserts »).

Les paramètres supplémentaires

Les trois critères {mots},{mots_selon_id} et {mots_selon_titre} peuvent prendre trois paramètres : ’score’, ’tableau’, ’tri’. Sous la forme {mots score tableau}.

Le paramètre ’score’.

Par défaut, le critère {mots} prend les objets ayant tous les mots passés en paramètre. On peut décider de vouloir prendre ceux ayant au moins un certain nombre de mots passés paramètre, mais pas nécessairement tous. C’est à cela que sert le paramètre ’score’.

-  Si score est compris entre 0 et 1 (exclus), alors SPIP sélectionnera les objets ayant au moins ce pourcentage de mots [2] sur le total des mots passés en paramètre. Par exemple si j’écris {mots 0.5}, et que je passe 10 mots en paramètre, alors SPIP sélectionnera les objets ayant au moins 10*0.5 = 5 des mots passés en paramètre.
-  Si score est supérieur ou égale à 1 et suivi du signe « % », alors SPIP sélectionnera les objets ayant au moins ce pourcentage sur le total des mots passés en paramètre. Par exemple si j’écris {mots 50%}, et que je passe 10 mots en paramètre, alors SPIP sélectionnera les objets ayant au moins 50% de 10 = 5 des mots passés en paramètre.
-  Si score est supérieur ou égale à 1, mais n’est pas suivi du signe « % », alors SPIP sélectionnera les objets ayant au moins ’score’ mots passés en paramètres. Par exemple {mots 5} sélectionnera les objets ayant au moins 5 mots passés en paramètre.

Le paramètre ’tableau’.

Par défaut, SPIP prend comme tableau la variable d’environnement ’mots’. Mais on peut lui dire, via ce paramètre, de prendre un autre tableau.

Ce peut être un tableau :
-  calculé via #GET et #SET
-  inscrit en dur via #ARRAY
-  passé en variable d’environnement, et appelé via #ENV.

Ex : {mots 100% #ARRAY{0,2,1,1}} sélectionnera les objets ayant les mots clefs 2 et 1. Notez qu’il est obligatoire de donner une valeur au paramètre ’score’ pour utiliser ’tableau’, sinon SPIP les confond.

Le paramètre ’tri’

Ce paramètre, existant depuis la version 2.1 (sous SPIP 3) ou 1.3 (sous SPIP 2.1 et 2.0) peut prendre deux valeurs :
-  tri pour trier la boucle en fonction du nombre de mots du tableau associés, en commençant par le plus petit nombre.
-  !tri pour trier la boucle en fonction du nombre de mots du tableau associés, en commençant par le plus grand nombre.

Exemple  :

L’article 1 est associé aux mots 1,2,3 ; l’article 2 est associé aux mots 2,3,4,5,6.

{mots 2 #LISTE{1,2,3} !tri} affichera d’abord l’article 1, puis l’article 2.
En effet, l’article 1 est associé à 3 mots dans la liste (1,2,3), tandis que l’article 2 n’est associé qu’à 2 mots dans la liste (2,3).

Formulaire de sélection

Avec la version 1.1 de ce plugin, une nouvelle possibilité s’offre à vous : faire appel à un formulaire bâtissant pour vous les critères dans l’url pour filtrer selon plusieurs mots clefs.

Connecté en tant que webmestre, vous pouvez tester avec la page de démonstration : /?page=demo/parmots.

Le formulaire présente dans un premier temps la liste de vos groupes de mots clefs.

Dès que vous en choisissez un dans la liste, automatiquement [3], la liste des mots clefs de ce groupe est affichée juste à côté.

Choisissez un mot clef, et ce dernier et ajouté à l’URL pour ne vous présenter que les articles ayant ce mot clef.

Et le processus peut être répété autant de fois que nécessaire.

Bonus : la liste des mots clefs déjà choisis est affichée sous le formulaire. Chaque mot est cliquable. Un clic le supprime de l’URL et de la liste.

Le formulaire critère mots en action

Usage du formulaire

-  Sur une seule page

  • en affichant tous les groupes de mots :
    <div class="ajax">
    [(#FORMULAIRE_RECHERCHE_PAR_MOTS)]
    </div>
  • en n’affichant que certains groupes de mots :
    #SET{FiltreGroupes,#ARRAY}
    <BOUCLE_FiltreGroupes(GROUPES_MOTS){titre==^[^_]}>
    #SET{FiltreGroupes,
           #GET{FiltreGroupes}|push{#ID_GROUPE}}
    </BOUCLE_FiltreGroupes>
    <div class="ajax">
    [(#FORMULAIRE_RECHERCHE_PAR_MOTS{#GET{FiltreGroupes}})]
    </div>

    Ici, on a choisi de ne pas afficher les groupes de mots commençants par « _ ».

-  On peut aussi utiliser le formulaire sur toute les pages du site pour renvoyer sur une page de résultats :

[(#FORMULAIRE_RECHERCHE_PAR_MOTS{'',#URL_PAGE{pagederesultats}})]

NB :

  • le premier paramètre est un tableau d’identifiants de groupes, ou la chaine vide
  • le deuxième paramètre est l’URL de la page qui affiche les résultats.

Usage avec le plugin Mots arborescents

Par défaut, seul le mot-clé demandé est recherché.

Mais il est possible de trouver via n’importe quel mot-clé de la branche du mot-clé demandé en mettant dans mes_options.php :

if (!defined('_CRITERE_MOTS_ARBO_BRANCHE'))
    define('_CRITERE_MOTS_ARBO_BRANCHE', true); 

Notes

[1Pour des pages incluses, il suffit de passer {mots} comme paramètre d’inclusion.

[2Car un nombre entre 0 et 1 est un pourcentage

[3Si vous n’avez pas désactivé javascript

NOTA SPIP branche 2.*

Attention : la partie formulaire de ce plugin ne fonctionnera pas avec la version 2.0.10 de SPIP. Il faut :

On pourra utiliser le plugin pour, par exemple afficher les articles connexes.

Discussion

74 discussions

  • 15

    Bonjour,

    La mise à jour de la version 2.1.6 à 3.0.0 sur un spip 3.1.3 plante complètement le site (obligé de supprimer le répertoire du plugin en ftp ...)

    Le problème se produit sur le site en production, en revanche, la mise à jour ne me pose aucun problème sur une copie locale.

    Je n’ai aucune traces dans les logs. Problème version PHP, MySQL ???

    Merci pour vos lumières ... et pour ce plugin.

    • A priori cette mise à jour devrait plutôt être bénéfique. Il faudrait voir quelle est la boucle qui pose souci. Vider le cache aussi. Et activer les logs détaillés pour plus de détails. Voir le dernier paragraphe de cet article : http://www.spip.net/fr_article4453.html

    • Merci pour la rapidité de la réponse !
      Je vais attendre une heure de moindre activité pour reprendre calmement cette tentative.
      Quoiqu’il arrive, je reviens vers vous pour le bilan.

    • J’ai eu exactement le même problème que Vero avec un Spip 3.0.24, et je l’ai corrigé de la même manière qu’elle.

      J’essayerai après ce long weekend sur le site de dev (3.1.3).

    • Vero n’indique pas comment elle a corrigé…

    • En effet, ce n’est pas vraiment corrigé : elle a viré la version 3.0.0 par FTP 😉. J’ai fait pareil et remis la 2.1.6…

    • J’ai refait une tentative :

      1. Désinstaller la version 2.6
      2. Vider les caches
      3. Logs détailles
      4. Installer version 3.0

      Rien à faire : tout plante, le site devient totalement inaccessible côté public et côté privé.

      Je n’ai rien trouvé dans les logs ... ceci étant, SPIP plante dès l’activation.

    • il faudrait voir s’il y a pas de conflit avec d’autres plugins. Chez moi aucun souci pour activer.

    • il faudrait voir si le fait de mettre

      define('_INTERDIRE_COMPACTE_HEAD_ECRIRE', 1);
      define('SPIP_ERREUR_REPORT',E_ALL);
      error_reporting(E_ALL^E_NOTICE);

      dans mes_options.php affiche des messages d’erreurs spécifiques.

    • Le problème se produit sur un site en production.

      La même configuration SPIP (version, plugins installés) sur mon serveur local ne pose aucun problème.

      Activer toutes les erreurs sur le site en production et le planter est un peu délicat ...

      En revanche, les 2 configurations APACHE sont différentes.
      Je peux vous donner le détails.

      Url en ligne : http: // www . enviroboite . net

    • effectivement des details serait pas mal.

      Mais sinon installer spip dans un sous dossier le temps des tests ?

    • Oui, j’y ai pensé ... mais il faut que je trouve la fenêtre de temps.

      En attendant, j’ai les 2 phpinfos en version html, comment vous les faire parvenir ?

      Faire un zip des 2 et le renommer en png ? C’est peut-être moyen pour le fil si cela passe ...

    • imprimer en PDF et m’envoyer un courriel monprenom@monprenom.net

    • Je vous ai envoyé les phpinfo par mail ... et je viens de tester sur une nouvelle installation, sans autre plugin, histoire de trouver l’éventuel « coupable », et avec tous les reports activés.

      Il se passe exactement la même chose : plantage puis rien.

       ???

      En scannant les logs, j’ai trouvé ceci dans spip.log

      Activer le plugin « @plugin@ » (version : @version@) : variables inutilisees version_maj

      Suivi de

      redirige 302 : http://www.enviroboite.net/test/ecrire/?exec=admin_plugin&action=actionner&redirect=http%3A%2F%2Fwww.enviroboite.net%2Ftest%2Fecrire%2F%3Fexec%3Dadmin_plugin

      Je ne sais pas si cela peut aider ?

      Je vous envoie les logs par mail.

    • lA version 3.0.1 corrige ce bug, qui concerne uniquement les versions de PHP < 5.4

    • Ça marche au poil. 👍

      Merci !

    Répondre à ce message

  • 11
    Michaël

    Bonjour !

    J’utilise une navigation exclusivement par mots clés, avec beaucoup de mots clés attribués à chaque article (près de 100 mots en tout en en moyenne 10 à 15 mots par article).

    Plus le temps passe et plus la boucle avec le critère mots devient lente.

    J’ai donc fait un test et constaté que si le tableau mots contient les valeurs 1,2,3,
    <Ma_boucle (articles) {mots}>#TITRE </Ma_boucle>
    est 2 à 3 fois plus lente (plus de 20s) que
    <Ma_boucle (articles) {id_mot=1}{id_mot=2}{id_mot=3}> #TITRE </Ma_boucle>

    C’est encore pire si on augmente encore le nombre de mots.

    J’ai donc tenté de monter ma boucle sur ce modèle, en php :

    <?php
            
            echo "<BOUCLE_articles(ARTICLES)";
            echo "{id_mot=1}{id_mot=2}{id_mot=3}>";
            echo "#TITRE</BOUCLE_articles>";
    ?>

    Ca marche très bien mais le problème c’est que ça coince lorsque je généralise le code :

    <?php
            $mots = array(); 
            $mots = $_GET["mots"];
            echo "<BOUCLE_articles(ARTICLES)";
                    foreach($mots as $mot) {echo "{id_mot=$mot} ";}
            echo ">";
            echo "#TITRE</BOUCLE_articles>";
    
    
    ?>

    Le problème semble vraiment venir de cette ligne :
    echo ">";
    mais je ne vois pas pourquoi ! Le PHP et moi ne sommes pas très copains ;)

    Quelqu’un aurait-il une idée, une explication, une piste pour soit utiliser le critère mots de manière plus rapide soit pour modifier mon code erroné !

    Merci d’avance !

    Michaël

    • Michaël

      Bon ça ne peut pas marcher comme ça car le php n’est interprété qu’apès les boucles !

      Un coup pour rien ! Comment faire alors ?

    • malheureusement quelque soit la solution le problème sera le même : faire des requete avec beaucoup de mot. Il faudrait avoir le code de la requete pour voir ce que ca donne et où est le problème exactement.

    • Michaël

      Je comprends bien que le nombre de mots fait que les requetes sont lourdes.

      Mais malgré tout, si la tableau « mots » contient les mots (1,2,3) les deux boucles suivantes devraient s’executer à la meme vitesse :

      <BOUCLE_articles(ARTICLES){id_mot=1}{id_mot=2}{id_mot=3}>
      #TITRE
      </BOUCLE_articles>
      <BOUCLE_articles(ARTICLES){mots}>
      #TITRE
      </BOUCLE_articles>

      Or la première est très nettement plus rapide et ce même lorsque l’on utilise la page démo. C’est ça qui m’interpelle !

    • non car la requete généré n’a rien à voir

    • Michaël

      D’accord !

      Par contre, le résultat est bien le même non ?

    • var_mode=debug pour comparer permettra de voir que dans un cas, c’est un OU entre les id_mot, alors que {mots} fait un ET

    • Michaël

      Je confirme que non !

      Je confirme que les résultats sont les mêmes et sont différents de ce que j’aurais obtenu avec un ou genre id_mot IN 1,2,3

    • Michaël

      Réponse apportée par « var_mode=debug »

      Voici ma boucle :

      <BOUCLE_articles(articles){id_mot=(#ENV{mots}|table_valeur{0})}{id_mot=(#ENV{mots}|table_valeur{1})}{id_mot=(#ENV{mots}|table_valeur{2})}{!par #ENV{tri,date}}{notation}{!par date}{pagination 10 }>

      et voici le début de la requete

      SELECT articles.id_article, articles.id_secteur, rand() AS hasard, COUNT(notations.note) AS nombre_votes, ROUND(AVG(notations.note),2) AS moyenne, ROUND(AVG(notations.note)*(1-EXP(-5*COUNT(notations.note)/20)),2) AS moyenne_ponderee, articles.date, articles.id_rubrique, articles.titre, articles.descriptif, articles.id_rubrique, articles.lang
      FROM spip_articles AS articles
      LEFT JOIN spip_notations AS notations ON ( notations.id_objet = articles.id_article AND notations.objet=’article’)
      INNER JOIN spip_mots_liens AS L3 ON ( L3.id_objet = articles.id_article AND L3.objet=’article’)
      INNER JOIN spip_mots_liens AS L2 ON ( L2.id_objet = articles.id_article AND L2.objet=’article’)
      INNER JOIN spip_mots_liens AS L1 ON ( L1.id_objet = articles.id_article AND L1.objet=’article’)
      WHERE (articles.statut = ’publie’)
      AND (L1.id_mot = 14)
      AND (L2.id_mot = 22)
      AND (L3.id_mot = 18)
      GROUP BY articles.id_article,articles.id_article
      ORDER BY articles.date DESC, articles.date DESC

      Il s’agit bien d’un & !

      En attendant de trouver une manière plus intelligente (que je ne suis pas capable de trouver tout seul), j’ai donc fait ça à la main ! Si ça peut aider quelqu’un.

      1) J’ai pris pour hypothèse que sur mon site, personne ne voudra plus de 10 mots.
      2) J’ai ensuite testé le nombre d’entrées de la variable MOTS crées par le formulaire. En fonction de cette valeur, j’appelle une noisette différente pour afficher les résultats.

      #SET{filtre,0}
      [(#ENV{mots}|table_valeur{0}|oui)#SET{filtre,1}]
      [(#ENV{mots}|table_valeur{1}|oui)#SET{filtre,2}]
      [(#ENV{mots}|table_valeur{2}|oui)#SET{filtre,3}]
      [(#ENV{mots}|table_valeur{3}|oui)#SET{filtre,4}]
      [(#ENV{mots}|table_valeur{4}|oui)#SET{filtre,5}]
      [(#ENV{mots}|table_valeur{5}|oui)#SET{filtre,6}]
      [(#ENV{mots}|table_valeur{6}|oui)#SET{filtre,7}]
      [(#ENV{mots}|table_valeur{7}|oui)#SET{filtre,8}]
      [(#ENV{mots}|table_valeur{8}|oui)#SET{filtre,9}]
      [(#ENV{mots}|table_valeur{9}|oui)#SET{filtre,10}]
      
      
      #INCLURE{fond=inclure/mots_result/page_mot_mots_result#GET{filtre},env,ajax,tri=#GET{valeur},}

      Enfin, sur les différents fichiers résultats, je modifie mes boucles en fonction du nombres de mots clés

      <BOUCLE_articles(ARTICLES) {id_mot=#ENV{mots}|table_valeur{0}} {id_mot=#ENV{mots}|table_valeur{1}} ........etc

      Un lien pour voir le résultat : http://www.librairie-interactive.com/spip.php?page=mot&mots[]

    • Michaël

      Si ça peut faire avancer, voici les deux requetes avec les 3 mêmes mots clés sélectionnés.

      1) Avec {mots}, qui s’execute en 26 s

      SELECT articles.id_article, articles.id_secteur, COUNT(notations.note) AS nombre_votes, ROUND(AVG(notations.note),2) AS moyenne, ROUND(AVG(notations.note)*(1-EXP(-5*COUNT(notations.note)/20)),2) AS moyenne_ponderee, articles.date, articles.id_rubrique, articles.titre, articles.descriptif, articles.id_rubrique, articles.lang
      FROM spip_articles AS <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+YXJ0aWNsZXM8L2NvZGU+"></span>  
      LEFT JOIN spip_notations AS notations ON ( notations.id_objet = articles.id_article AND notations.objet='article')
      WHERE (articles.statut = 'publie')
      	AND articles.id_article IN (
      		SELECT id_objet FROM spip_mots_liens WHERE id_mot=14 and objet='article' OR id_mot=22 and objet='article' OR id_mot=18 and objet='article' GROUP BY id_objet,objet  HAVING SUM(1) >= 3
      	)
      GROUP BY articles.id_article
      ORDER BY articles.date DESC

      2) En remplaçant {mots} par {id_mot=...}{id_mot=...}{id_mot=...} qui s’execute en 1,5s

      SELECT articles.id_article, articles.id_secteur, rand() AS hasard, COUNT(notations.note) AS nombre_votes, ROUND(AVG(notations.note),2) AS moyenne, ROUND(AVG(notations.note)*(1-EXP(-5*COUNT(notations.note)/20)),2) AS moyenne_ponderee, articles.date, articles.id_rubrique, articles.titre, articles.descriptif, articles.id_rubrique, articles.lang
      FROM spip_articles AS <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+YXJ0aWNsZXM8L2NvZGU+"></span>  
      LEFT JOIN spip_notations AS notations ON ( notations.id_objet = articles.id_article AND notations.objet='article') 
      INNER JOIN spip_mots_liens AS L3 ON ( L3.id_objet = articles.id_article AND L3.objet='article') 
      INNER JOIN spip_mots_liens AS L2 ON ( L2.id_objet = articles.id_article AND L2.objet='article') 
      INNER JOIN spip_mots_liens AS L1 ON ( L1.id_objet = articles.id_article AND L1.objet='article')
      WHERE (articles.statut = 'publie')
      	AND (L1.id_mot = 14)
      	AND (L2.id_mot = 22)
      	AND (L3.id_mot = 18)
      GROUP BY articles.id_article,articles.id_article
      ORDER BY articles.date DESC, articles.date DESC

      Je ne suis pas très doué en php et en sql mais ne serait-il pas possible d’utiliser cette requete directement avec le plugin ?

      Amicalement !

      Michaël

    • bon, je viens de retomber sur cette comparaison.
      La différence tient principalement à la question de SUM(1) >= 3. Ceci est lié au paramètre de boucle qui permet de faire la recherche y compris s’il n’y a pas 100 % des mots qui sont affecté à l’objet.

      Etant donné que ce cas est facilement detectable, on pourrait effectivement mettre un comportement différent pour gagner en vitesse.

    • il n’est techniquement pas possible d’avoir un critère qui produise ta requete, du à des limites du compilateur de SPIP (ou alors à mes propres limite), mais la version 3.0.0 du plugin produit une requete qui contourne le bug de mysql.

      SELECT articles.titre, articles.id_article, articles.lang FROM <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+bXVfbG9jYWxob3N0PC9jb2RlPg=="></span>.spip_articles AS <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+YXJ0aWNsZXM8L2NvZGU+"></span> INNER JOIN <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+bXVfbG9jYWxob3N0PC9jb2RlPg=="></span>.spip_mots_liens AS mots_liens ON ( mots_liens.id_objet = articles.id_article AND mots_liens.objet='article') WHERE (articles.statut = 'publie') AND ((mots_liens.id_mot=1) OR (mots_liens.id_mot=2) OR (mots_liens.id_mot=3) OR (mots_liens.id_mot=4) OR (mots_liens.id_mot=5) OR (mots_liens.id_mot=6) OR (mots_liens.id_mot=7) OR (mots_liens.id_mot=8) OR (mots_liens.id_mot=9) OR (mots_liens.id_mot=10)) GROUP BY articles.id_article HAVING COUNT(mots_liens.id_objet) >= 10

      à la place de

      SELECT articles.id_article, articles.titre, articles.lang FROM <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+bXVfbG9jYWxob3N0PC9jb2RlPg=="></span>.spip_articles AS <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+YXJ0aWNsZXM8L2NvZGU+"></span> WHERE (articles.statut = 'publie') AND articles.id_article IN ( SELECT id_objet FROM <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+bXVfbG9jYWxob3N0PC9jb2RlPg=="></span>.spip_mots_liens WHERE id_mot=1 and objet='article' OR id_mot=2 and objet='article' OR id_mot=3 and objet='article' OR id_mot=4 and objet='article' OR id_mot=5 and objet='article' OR id_mot=6 and objet='article' OR id_mot=7 and objet='article' OR id_mot=8 and objet='article' OR id_mot=9 and objet='article' OR id_mot=10 and objet='article' GROUP BY id_objet,objet HAVING SUM(1) >= 10 )

      La première requete est cent fois plus rapide que la seconde.

      A noter que la lenteur est du à un bug de mysql, résolu dans les nouvelles versions (6.x) https://bugs.mysql.com/bug.php?id=32665

    Répondre à ce message

  • 5

    Bonjour,
    un mixte des 2 cas précédents : sélection selon 2 groupes de mots clés avec des cases à cocher. Pour le 1er groupe un seul mot peut être choisi, pour le 2d on peut en choisir plusieurs. recherche_blocs . cool ! merci Maïeul

    Le critére {mot} se traduit donc par des & sur les mots clés sélectionnés
    Dois-je abandonner son utilisation pour essayer de faire des « ou » ? comme le ferait :
    <BOUCLE_objets(OBJETS) {id_mot IN gpe1} {id_mot IN gpe2}>
    (avec {mot} selectionner Enfant + Caramel abouti à 0 résultat car un circuit ne peut pas être les 2 . J’ai vainement longuement essayé de faire sortir ceux qui était l’un ou l’autre, l’idée me semblait de renvoyer 2 #GET, un pour le gpe1 et un pour le gpe2 , mais je m’en sors pas, (et c’est déjà pas si mal comme ça ! ) mais si vous avez des suggestions, doc plus concrète que programmer.spip , des exemples plus simple à décrypter que page=demo/parmots (qui ne marche pas), je suis preneur.

    • Bonjour,
      m’agace, ça marche (liens ci-dessus, code ci-dessous) mais, pourquoi ?!
      (et toute mes tentatives de faire autrement, de décomposer le pb, se solde par des échecs. Pourtant ça devrait pas marcher avec name=mots[] pour tous les checkbox ?...)
      le code (qui marche) :

      <form class="form-inline" role="form" method="get" action="#SELF">
      	[(#SELF|parametre_url{mots,''}|form_hidden)]
      <BOUCLE_mots1(MOTS){id_groupe=1} {par num titre} {2,11} >
      <label class="checkbox-inline" for="mot#ID_MOT">
      <input type="radio" class="checkbox" name="mots[]" id="mot#ID_MOT"
       value="#ID_MOT"[(#ENV{mots}|find{#ID_MOT}|oui) checked="checked"] />
        #TITRE</label>
      </BOUCLE_mots1>
      <!-- type="checkbox" type="radio" -->
      <BOUCLE_mots4(MOTS){id_groupe=4} {par num titre}{", "}>
      <label class="checkbox-inline" for="mot#ID_MOT">
      <input type="checkbox" class="checkbox" name="mots[]" id="mot#ID_MOT"
       value="#ID_MOT"[(#ENV{mots}|find{#ID_MOT}|oui) checked="checked"] />
        #TITRE</label> 
      </BOUCLE_mots4>
      <p class="boutons">
      <input type="submit" class="submit" value="<:bouton_chercher:>" /></p>
      </form>
      
      [(#REM) Albums trouves ]
      <BOUCLE_albums(ALBUMS) {mots} {branche?} {0,100} {pagination 10}>
      ...
    • Bonjour,
      oui pourquoi ? je me suis plongé calmement dans cet ardu code, avec la doc officiel, et des infos glanées sur le net (d’autres tournent sur le pb), et beaucoup de persévérance je commence à y comprendre un petit peu qcq chose. Je propose cette article pour les débutants (je l’ai publié, comme ébauche wiki de contribution pédagogique, il m’’a été personnellement utile de le faire, mais je ne me vexerai pas si on juge que c’est trop simple et succin)

    • je ne saisi pas le rapport entre votre problème et l’article. L’un parle de {mots} l’autre de CVT.

    • Bonjour Maïeul,
      je ne suis pas parvenu à faire fonctionner le formulaire CVT demo/parmots, aussi je n’ai pu utiliser {mots} que grâce à tes explications dans ce forum. Donc oui mon article pour « débutant CVT », n’a pas de rapport exclusif avec {mots}, mais ce serait bien d’avoir (et j’espère parvenir à) un ou des formulaires CVT fonctionnelles pour {mots}, non ?

    • il y a le formulaire deja proposé, mais ce n’est pas mois l’auteur ... je ne sais pas je n’ai pas trop le tps en ce moment ...

    Répondre à ce message

  • 7

    Bonjour,

    J’ai besoin de ce plugins pour insérer un formulaire de recherche sur un site que je suis en train de réaliser.
    Voilà un bon moment que je me casse les dents dessus.

    Mon objectif :
    Sur une page réunissant plusieurs brèves, je souhaite que les visiteurs puissent effectuer un trie de ces brèves selon les mots clefs qu’ils auront choisie.
    J’ai 3 groupes de mots clefs et je souhaite que le trie soit effectué selon deux de ces groupes (le troisième me servant ailleurs, mais pas dans ce cas présent).
    Mes deux groupes comportes chacun plusieurs mots clefs :
    Il y a le groupe « Age » qui a pour mots clefs : « chaton », « junior », « adulte », « senior ».
    Et le groupe « Sexe » qui a pour mots clefs : « mâle » et « femelle »

    Les visiteurs peuvent ne choisir que l’un des deux groupes s’il le souhaite (par exemple il recherche un chaton, mais n’ont pas de préférence sur le sexe), ou les deux (si par exemple ils recherchent précisement un chat adulte femelle).

    Je veux donc que sur un même page, par défaut toutes les brèves s’affichent, et que si le visiteur le désire, un tri soit effectué selon ses critères et que cela recharge la liste des brèves sur cette même page.

    Pour afficher mes brèves j’ai ce code :

    <B_breves>
    <ul>
    <BOUCLE_breves(BREVES) {id_rubrique} {!par date}}>
    <li class="adoption">
    <div class="breveleft">
    <a href="#URL_BREVE">[(#LOGO_BREVE|image_reduire{190,0}|image_recadre{140,140,center})]</a>
    </div>
    <div class="breveright">
    [<a href="#URL_BREVE"><span class="titre_chat">(#TITRE)<span></a>]
    [<span><strong>Sexe :</strong> (#LISTER_VALEURS{sexe})</span>]
    [<span><strong>Date de naissance :</strong> (#DATE_NAISSANCE|date_relative)</span>]
    [<span><strong>Lieu :</strong> (#LIEU)</span>]
    [<span>(#COURT_DESCRIPTIF)</span>]
    </div>
    <div class="nettoyeur"></div>
    </li>
    </BOUCLE_breves>
    </ul>
    </B_breves>

    Et mon formulaire ressemblerait à quelque chose comme ça (il n’est pas fonctionnel pour le moment) :

    Vous recherchez...
    <div class='ajax'>
    <form>
    <select>
    <BOUCLE_triesexe(MOTS) {type=sexe} ><option>#TITRE</option></BOUCLE_triesexe>
    </select>
    <select>
    <BOUCLE_trieage(MOTS) {type=age}><option>#TITRE</option></BOUCLE_trieage>
    </select>				
    <input type='submit' name='ok' value='ok' />
    </form>
    </div>

    J’ai essayée toute sorte de chose pour faire fonctionner le plugin critère mot, sans résultat.
    Juste pour info j’utilise SPIP 3.

    Et après vérification sur la page de démo du plugins, je peux choisir parmi mes 3 groupes de mots clefs (Age, Sexe et Date adoption - ce dernier groupe ne m’étant pas utile sur cette page -), mais ensuite, une fois un groupe sélectionné, je ne peux pas choisir de mot clef y correspondant (j’ai juste un « mot clef même groupe » affiché).

    Donc voilà ou j’en suis, si vous pouvez apporter de l’aide (et des explications) je suis preneuse, parce que là, je suis complètement bloquée et désespérée. Snif !

    Merci par avance.

    • Commençons par le formulaire. Je te conseille très fortement de lire une documentation sur comment fonctionnent les formulaires en HTML, parce que là ton formulaire, en l’état, ne peux rien faire.

      deja, virons le ajax, pour le moment. On verra cela plus tard.

      Ensuite, il faut que le formulaire poste quelque part, donc

      <form method="get" action="#SELF">

      On va repasser également tous les paramètres de la page, sauf mots qui change d’une fois sur l’autre. Pour cela on utilise le filtre |form_hidden appliqué sur un #SELF (url de la page) lui même filtré du paramètre « mots » :

      [(#SELF|parametre_url{mots,''}|form_hidden)]

      Il faut enfin préciser la variable où sera transmis la valeur de chaque menu déroulant, en l’occurance « mots[] » : <select name="mots[]">. Reste ensuite à indiquer la valeur passé pour chaque option du select : <option value="#ID_MOT">#TITRE</option>.

      En affinant un peu pour permettre que le formulaire propose de ne pas choisir dans un mot et utilise les précédentes valeurs comme valeurs par défaut, on obtient le formulaire suivant :

      <form method="get" action="#SELF">
      Vous recherchez...
      [(#SELF|parametre_url{mots,''}|form_hidden)]
      <B_triesexe>
      <select name="mots[]">
      	<option value=""></option>
      	<BOUCLE_triesexe(MOTS) {type=sexe} >
      		<option [(#ENV{mots}|find{#ID_MOT}|oui) selected="selected"] value="#ID_MOT">#TITRE</option>
      	</BOUCLE_triesexe>
      </select>
      </B_triesexe>
      
      <B_trieage>
      <select name="mots[]">
      	<option  value=""></option>
      	<BOUCLE_trieage(MOTS) {type=age}>
      		<option [(#ENV{mots}|find{#ID_MOT}|oui) selected="selected"]  value="#ID_MOT">#TITRE</option>
      	 </BOUCLE_trieage>
      </select>	
      </B_trieage>			
      <input type='submit' />
      </form>

      (Bon, il faudrait affiner pour avoir une structure html correcte. Voir http://www.spip.net/fr_article3791.html.

      Reste ensuite à passer le critère {mots} :

      <B_breves>
      <ul>
      <BOUCLE_breves(BREVES) {id_rubrique} {!par date}{mots}>
      <li class="adoption">
      <div class="breveleft">
      <a href="#URL_BREVE">[(#LOGO_BREVE|image_reduire{190,0}|image_recadre{140,140,center})]</a>
      </div>
      <div class="breveright">
      [<a href="#URL_BREVE"><span class="titre_chat">(#TITRE)<span></a>]
      [<span><strong>Sexe :</strong> (#LISTER_VALEURS{sexe})</span>]
      [<span><strong>Date de naissance :</strong> (#DATE_NAISSANCE|date_relative)</span>]
      [<span><strong>Lieu :</strong> (#LIEU)</span>]
      [<span>(#COURT_DESCRIPTIF)</span>]
      </div>
      <div class="nettoyeur"></div>
      </li>
      </BOUCLE_breves>
      </ul>
      </B_breves>
    • Un grand Merciiii Maïeul pour ton aide ! (En plus tu es super réactif !)

      Du coup si je comprends bien, avec ta solution on utilise pas le plugin enfin de compte ? En tout cas je ne vois pas la balise qui s’y rapporte ?

      Concernant mon formulaire, effectivement en l’état il n’était pas fonctionnel, je l’avais fais juste pour voir ce que ça donnerait sur la page web en question. Puis, de toute façon, je n’aurais pas su qu’il fallait utiliser la boucle SELF, les formulaires c’est effectivement pas ma spécialité comme tu peux constater. lol

      En gros, moi je me cassais les dents sur ça « [(#FORMULAIRE_RECHERCHE_PAR_MOTS)] » pensant que ce serait la clé de mon problème.

      Du coup encore merci pour le code, car non seulement il fonctionne mais en plus c’est bien expliqué pour que je comprenne (et puisse le réutiliser si besoin).

      J’aurais encore une question, comment afficher sur ma page par défaut toutes les brèves ?
      En gros, ce que je souhaite, c’est que si l’utilisateur n’utilise pas le formulaire (et donc ne passe pas de mot clef en URL), toutes les brefs soient par défaut afficher sur la page.
      Le formulaire ayant pour but juste de faire une sélection pour facilité les recherches de l’utilisateur, mais il reste facultatif.

    • C’est encore moi.

      J’ai trouvée la réponse à ma dernière question.

      Pour afficher par défaut toute les brèves j’ai utilisées un code alternatif avec la balise /B_nom_de_ma_boucle>, j’ai juste retirée le critère « mots » sur cette boucle qui est strictement identique à la première.
      Par contre, du coup, si je n’obtiens aucun résultat (imaginons que l’utilisateur cherche un chaton mâle et qu’il n’y en a pas, du coup le résultat affiche toutes les brèves).

      Du coup je ne pense pas que ce soit la solution idéale, car il faudrait que par défaut cela affiche toutes les brèves, mais que si le formulaire ne donne aucun résultat, cela affiche toutes les brèves, mais en affichant aussi un message du type « Aucun résultat » pour que l’utilisateur ne pense pas que le formulaire ne fonctionne pas.

      Du coup je ne sais pas comment procéder. Une idée ?

    • a ben si mon code utilise le plugin : c’est le critère {mots}. je ne suis pas responsable de la création du formulaire en question, et j’ignore comment il fonctionne.

      Pour ta question, les critères de spip peuvent avoir un ?, ce qui signifie qu’ils sont optionnels : si les paramètres nécessaires sont passés en environnement, alors le critère est utilisé, sinon non. Voir http://programmer.spip.net/Criteres-optionnels.

      Donc dans ton cas : {mots?}

    • Bonsoir,

      Alors j’ai testée le critère optionnel en remplaçant mots par mots ? cela semble fonctionner, mais je n’ai pas le résultat attendu.
      En faite, je veux afficher par défaut toutes les brèves, puisque le formulaire reste optionnel (sinon les visiteurs ne vont pas comprendre pourquoi ils arrivent sur une page vide).

      Or, si j’utilise le critère mots ? vu qu’aucun paramètre n’est passé en environnement quand on arrive sur la page, et bien je me retrouve effectivement avec une page vide.
      Par contre ça fonctionne bien, si jamais je lance une recherche sur le formulaire pour sélectionner par exemple des « chatons » « mâles » et qu’il y en a pas cela ne rend aucun résultat. Cependant, j’aimerais alors afficher toutes les brèves, mais en précisant que la recherche n’a pas donnée de résultat (histoire que les visiteurs ne pensent pas qu’il y a un problème avec le formulaire).

      Avec le code alternatif de la balise /B>, j’arrive à afficher par défaut l’ensemble de mes brèves, le formulaire est fonctionnel, cependant, si je lance une recherche qui ne donne aucun résultat, j’ai alors toutes mes brèves qui s’affichent (jusque là c’est ce que je veux) MAIS je n’ai pas possibilité de laisser un message pour dire que la recherche n’a aboutie sur aucun résultat (car si je mets ce message dans mon code alternatif, alors il apparaît aussi quand les visiteurs arrivent sur la page, sans même avoir utiliser le formulaire).

      Je sais pas si je suis claire dans mes explications, mais je ne vois pas tellement comment solutionner ce soucis.

    • si j’ai bien compris ton besoin, alors dans la parti optionell utilise

      [(#ENV{mots}|oui) texte à afficher si le formulaire a bien été rempli mais ne fournit pas de résultat].

    • Merci Maïeul, c’est exactement ce qu’il me fallait, ça marche niquel. Encore merci !

    Répondre à ce message

  • 20

    Le FORMULAIRE_RECHERCHE_PAR_MOTS permet de sélectionner les mots clés d’un groupe de mot.

    Cette sélection se fait assez lentement car il faut d’abord choisir 1 mot, le calcul se fait... les résultats s’affichent.

    Ensuite on peut choisir un autre mot, etc.

    Est il possible plutot qu’un menu déroulant d’afficher la liste des mots clés sous forme de liste à cocher afin d’effectuer une recherche multicritère en une seule fois ?

    ou à défaut permettre de sélectionner plusieurs mots clés dans le menu déroulant ?

    Pouvez vous m’aider à réaliser cela ?

    • tu connais les boucles de SPIP ou pas ? pour savoir quel degrees d’explication je dois fournir …

    • oui je connais le fonctionnement général.
      à mon sens il s’agirait de modifier la page recherche_par_mot.html ou d’en créer une autre à partir de celle ci recherche_par_mot2.html que je rangerais dans mon dossier squelette/formulaires ?

      ensuite suffit t’il de modifier le type de select ?

    • c’est ca. tu peux opter pour l’une ou l’autre des solutions, du moment que tu place tout cela dans ton dossier squelettes.

      Il suffit de modifier le squelette du formulaire et celui qui affiche les mots à la sortie du formulaire. Normalment la doc permet à une personne qui connaît les boucles de faire les modifs. Si tu bloque envoie moi ton code.

    • Bonjour, petit up pour ce post.
      Je souhaiterais moi aussi pouvoir avoir une liste à cocher plutôt qu’un/deux menu(s) déroulant et pouvoir choisir en même temps dans deux listes de mots clés. Les explications fournies ne suffisent pas à mon niveau !
      Pourrais-je avoir plus d’explications ?

      Et pour ajouter une difficulté, je souhaiterais que d’abord tous les articles (de la rubrique concernée par ma recherche) apparaissent dans la page et qu’ensuite en sélectionnant les mots clés, la sélection devienne plus restrictive. Alors qu’actuellement seule la sélection de mots fait apparaitre une liste d’articles, en commençant par une page vide.

      J’espère être assez claire.
      Merci d’avance.

    • quelles connaissances SPIP avez vous ?

    • Plutôt débutante !
      J’arrive à faire quelques boucles simples pour appeler des articles ou des documents dans mes squelettes mais je me base souvent sur les codes fournis pour essayer de les comprendre.

    • Bon, alors on va faire une chose simple : je vous donne un code qui marche. Ce qu’il fait :

      -  lister les mots clefs avec case à cocher
      -  afficher les articles avec ces mots clefs, sauf si aucun mot clefs n’a été choisi, dans ce cas il affiche tout.

      Vous testez ce code, et ensuite vous me faite un retour en m’indiquant lignes par lignes ce que fait le code. Comme cela je vous fournis un code déjà prêt ET en plus vous vous formez.

      Avec la doc de base de SPIP + du plugins + notions de HTML vous devrez le comprendre. Et sinon vous posez des questions.

      <B_mots>
      <div class="formulaire_spip formulaire_recherche_mot">
      <form method="post" action="#SELF">
      	[(#SELF|form_hidden)]
      	<ul>
      	<BOUCLE_mots(MOTS){par titre}{objet=article}>
      		<li>
      			<label for="mot#ID_MOT">#TITRE</label>
      			<input type="checkbox" class="checkbox" name="mots[]" id="mot#ID_MOT" value="#ID_MOT"[(#ID_MOT|in_array{#ENV{mots}}|oui) checked="checked"] />
      		</li>
      	</BOUCLE_mots>
      	</ul>
      
      <p class="boutons"><input type="submit" class="submit" value="<:bouton_enregistrer:>" /></p>
      </form>
      </div>
      </B_mots>
      
      <B_articles>
      	<ul>
      	<BOUCLE_articles(ARTICLES){mots?}{par titre}>
      		<li><a href="#URL_ARTICLE">#TITRE</a></li>
      	</BOUCLE_articles>
      	</ul>
      </B_articles>
    • Aie... déjà erreur à la 1e ligne !
      Spip m’indique :

      1 Erreur(s) dans le squelette (...)
      Critère inconnu = _mots

      Et sinon, tous les articles de mon site apparaissent.

    • heu, je vous assure que j’ai testé cela avant de vous envoyé.

      Quelle config de SPIP avez vous ? où avez vous mis le code ?

    • SPIP 2.1.23

      Et j’ai mis le code dans le fichier « recherche_par_mots.html » dans mon dossier squelettes. J’ai même testé de le mettre dans le dossier plugin directement. Rien à faire. J’ai l’impression que le critère « mots » n’est pas accepté ! A chaque fois ça me renvoi un bug !

    • ne surtout jamais modifié le dossier squelette.

      A tout hasard, le plugin est bien activé ?

      Sinon pour SPIP 2.1, il faut mettre

      <B_mots>
      <div class="formulaire_spip formulaire_recherche_mot">
      <form method="post" action="#SELF">
      	[(#SELF|form_hidden)]
      	<ul>
      	<BOUCLE_mots(MOTS spip_mots_articles){par titre}{id_article>0}>
      		<li>
      			<label for="mot#ID_MOT">#TITRE</label>
      			<input type="checkbox" class="checkbox" name="mots[]" id="mot#ID_MOT" value="#ID_MOT"[(#ID_MOT|in_array{#ENV{mots}}|oui) checked="checked"] />
      		</li>
      	</BOUCLE_mots>
      	</ul>
      
      <p class="boutons"><input type="submit" class="submit" value="<:bouton_enregistrer:>" /></p>
      </form>
      </div>
      </B_mots>
      
      <B_articles>
      	<ul>
      	<BOUCLE_articles(ARTICLES){mots}{par titre}>
      		<li><a href="#URL_ARTICLE">#TITRE</a></li>
      	</BOUCLE_articles>
      	</ul>
      </B_articles>
    • videz le cache le cas échéant ...

    • Ca y est presque !
      Juste ceci apparait au dessus de ma liste a choix multiple :

      Warning: in_array() [function.in-array]: Wrong datatype for second argument in /home/<toto>/www/ecrire/public/composer.php(69) : eval()'d code on line 45

    • quelle version de PHP (allez dans http://urldusite/ecrire/?exec=info pour savoir).

    • Excusez moi de la réponse tardive...
      PHP Version 5.2.17

      ne surtout jamais modifié le dossier squelette.

      Pas d’inquiétude, je ne modifie pas le dossier squelette dist, mais j’insère mes squelettes dans un dossier squelettes personnels :)

    • J’ai trouvé ceci dans cet article spip sur #ARRAY (dans les notes de bas de page) :

      « |find correspond à la fonction PHP in_array, à la différence que ce filtre ne produit pas le message d’erreur "Warning : in_array() [function.in-array] : Wrong datatype for second argument." si la variable n’est finalement pas un tableau. En effet, lorsqu’une variable est générée dynamiquement, on ne sait pas toujours si elle existera et s’il s’agira bien d’un tableau. »

      Ca parle de mon problème, mais par contre, ça dépasse mes compétences là !

    • a mais oui,

      c’est le code

      [(#ID_MOT|in_array{#ENV{mots}}|oui) checked="checked"]

      qui est mauvais. Le but c’est de tester si le mot courant se trouve dans la liste des mots du précédent formulaire. Si oui, on coche la case.

      Mais sauf que ca va pas.

      Et donc la doc sur #ARRAY que vous avez trouvé donne la solution. Désolé un peu fatigué (et chez moi les messages d’erreurs sont désactivés.

      La solution est de remplacer par :

      [(#ENV{mots}|find{#ID_MOT}|oui) checked="checked"]
    • Super ! Plus de message d’erreur !

      Une fois le mot clé sélectionné, la liste apparait bien.
      Par contre, vous disiez plus haut que ce code doit faire apparaitre tous les articles si aucun mot clé n’est sélectionné, ce n’est pas le cas.

    • oui, parce que dans mes testes suite au fait que le plugin n’était pas activé, j’ai oublié le ? dans {mots?}.

      Ca devrait aller mieux comme cela.

      Et maintenant, la réponse de l’exercice ;-)

    • C’est super !!

      J’ai ajouté {id_rubrique} pour permettre de faire la recherche uniquement dans la rubrique que je souhaite et le tour est joué.

      Un grand merci ! :D

    Répondre à ce message

  • 5

    Pour ceux qui ont des problemes de performance avec ce plugin j’ai mis au point un systeme de boucles recursives qui fait le travail, mais au lieu d’une requete complexe ca decompose le probleme en requetes simples, ce qui evite les lenteurs pour certains, voire les crashs SQL pour ceux qui comme moi travaillent sur une base de donnees de grande taille. Ce systeme ne permet pas de specifier des pourcentages ou autres options de tri, ca affiche simplement les articles associes a TOUS les mots cles de la liste. Le principe est assez simple, j’ai decompose le code par etapes en mettant des commentaires pour que vous saisissiez facilement le principe. Nous avons un tableau #KW qui contient la liste des id_mots, un compteur « n » qui nous permet de progresser dans ce tableau, un tableau « tab2 » qui sert aux traitements, et un tableau « tab » qui contiendra la liste finale des articles. Vous noterez que le tableau #KW peut directement provenir d’un tableau specifie dans l’URL de la sorte : ?kw[]=id_mot1&kw[]=id_mot2&kw=...

    • tu pourrais proposer un article ? là les infos sont coupées ...

    • le code :

      #SET{n,0}
      [(#SET{next_kw,[(#KW|table_valeur{#GET{n}})]})]
      #SET{tab,#ARRAY{0,0}}
      <BOUCLE_test_rec(MOTS){id_mot=#GET{next_kw}}{0,1}>	
      				
          [(#REM) 
          --- on remplit tab2 avec tous les articles du mot en cours 
          ---]
          #SET{tab2,#ARRAY}	
          <BOUCLE_articles(ARTICLES){id_mot}>
              [(#SET{tab2,[(#GET{tab2}|array_merge{#ARRAY{0,#ID_ARTICLE}})]})]
          </BOUCLE_articles>
      				
          [(#REM) 
          --- si c'est la premiere passe, on copie tab2 vers tab 
          --- sinon on place dans tab l intersection entre les deux tableaux 
          ---]
          [(#GET{n}|=={0}|?{
              #SET{tab,#GET{tab2}},
      	[(#SET{tab,[(#GET{tab}|array_intersect{#GET{tab2}})]})]
          })]
      				
          [(#REM) 
          --- on incremente le compteur et recupere le prochain mot cle 
          ---]
          #SET{n,#GET{n}|plus{1}}
          [(#SET{next_kw,[(#KW|table_valeur{#GET{n}})]})]
      				
          [(#REM) 
          --- on apelle a nouveau la boucle en passant en parametre le nouveau id_mot
          --- c est ici que se fait la recursivite de la fonction
          ---]
          <BOUCLE_test_rec1(BOUCLE_test_rec){id_mot=#GET{next_kw}}{0,1}>
          </BOUCLE_test_rec1>
      </BOUCLE_test_rec>

      Ensuite il suffit d’utiliser le tableau « tab » dans une boucle article basique, cette fois ci avec un tri si on le souhaite car ca ne prend plus autant de ressources :

      <BOUCLE_page(ARTICLES){par date}{inverse}{id_article IN #GET{tab}}....
    • Mon code est vieux, et a l’epoque je n’avais pas connaissance de la boucle DATA sur les tableaux. On peut transformer cette solution en faisant une boucle sur le tableau de mots directement au lieu d’une boucle recursive. L’important c’est la decomposition de la requete faite par le plugin en requetes simples : les jointures se font principalement en PHP lors de l’intersection des tableaux, et les criteres de tri ne s’appliquent qu’a la fin, une fois la liste des articles bien etablie (plus de jointures dans la requete des lors).

    • Salut,

      Je lis ton message un peu tardivement...

      Tu trouveras une ancienne technique similaire (ancienne aussi) ici : article 1538 et qui est détaillée pour un usage similaire au critère mots ici : http://thread.gmane.org/gmane.comp.....

      Pour moi, ça s’est avéré environ 10x plus rapide à l’exécution que critère mots... Toutefois c’est moins souple (ou plus difficile à manipuler).

      Voici le code :

      [
      (#REM)
      	Une première boucle qui prépare
      	une pile avec doublons nommée liste_0
      	(Ici on peut rajouter des critères si on veut
      	choisir des articles en particulier à filtrer avec des mots)
      
      	Ça peut marcher aussi pour d'autres boucles que ARTICLES...
      ]
      <BOUCLE_Une_pile(ARTICLES){doublons liste_0} ></BOUCLE_Une_pile>
      [
      (#REM)
      	Ensuite pour chaque mot de mon tableau...
      	"ma_liste_de_mots" contient une liste de mots
      	qui servent de filtres
      ]
      <BOUCLE_Les_mots(MOTS){id_mot IN #GET{ma_liste_de_mots}}>
      [(#SET{moinsun,[(#_Les_mots:COMPTEUR_BOUCLE|moins{1})]})]
      	[
      	(#REM)
      		on choisi parmi les articles de la pile précédente
      		(liste_x où x est compteur_boucle-1) 
      		les articles qui sont rattachés au mot. Et on
      		les empile avec un doublons dans la pile suivante
      		(liste_y où y=compteur de boucle)
      	]
      	<BOUCLE_les_articles_du_mot(ARTICLES){id_mot}
      				{!doublons liste_#GET{moinsun}}
      				{doublons liste_#_Les_mots:COMPTEUR_BOUCLE} ></BOUCLE_les_articles_du_mot>
      </BOUCLE_Les_mots>
      [
      (#REM)
      	Au final, on a une pile
      	(nommée liste_z où z=nombre de tour de boucle "Les_mots")
      	qui contient bien seulement les articles qui ont
      	tous les mots du tableau
      
      	C'est ce que liste la boucle d'après.
      	(ça peut être l'occasion de les trier d'une
      	façon ou d'une autre...)
      ]
      <BOUCLE_Articles_empile(ARTICLES){!doublons
      liste_#_Les_mots:COMPTEUR_BOUCLE}>
      	#TITRE<br>
      </BOUCLE_Articles_empile>
    • Oups petite erreur de lien dans mon commentaire précédent : Afficher les articles connexes, triés par pertinence...

    Répondre à ce message

  • 3

    Bonjour,

    Je rencontre un problème très étrange de pagination erratique sur boucle imbriquée avec critère_mots.

    Je suis sur une page mot.html
    revue pour lister tous les articles d’une certaine rubrique, classés par familles.

    Mes familles sont dans un autre groupe de mot-clé

    Une première boucle récupère le nom d’une famille,
    Une seconde boucle imbriquée, récupère les article tagué à la fois par l’id_mot sur lequel on se trouve ET l’id_mot de la famille remontée par le premier niveau.

    Tout fonctionne sauf la pagination. Si j’essaie d’utiliser la pagin sur un des blocs de résultats, en fait elle affecte TOUS les blocs de résultats.

    Le code :

    <BOUCLE_mot_principal(MOTS){id_mot}>
    <h1>#TITRE</h1>
      <BOUCLE_familles(MOTS){id_groupe = 19}{par num titre}>
        
        <BOUCLE_affiche_famille(ARTICLES){id_rubrique=2}{mots 100% #ARRAY{0,#_mot_principal:ID_MOT,1,#_familles:ID_MOT}}{0,1}>
        <h3 class="header">#_familles:TITRE</h3>
        </BOUCLE_affiche_famille>
        
        [(#REM) Listes des formations mot + famille <!-- INCLURE{fond=liste/formations-resume,env}/ --> ]
        [(#REM) Articles de la rubrique Formations lies au mot-cle ]
        <B_list_formations>
          #ANCRE_PAGINATION
                <BOUCLE_list_formations(ARTICLES){id_rubrique=2}{mots 100% #ARRAY{0,#_mot_principal:ID_MOT,1,#_familles:ID_MOT}}{par num titre}{pagination 4}>
    
                      [<div class="h3"><a rel="bookmark" href="[(#URL_ARTICLE|url_absolue)]">(#TITRE)</a></div>]
    
                  </BOUCLE_list_formations>
    
            <p class="pagination">#PAGINATION{page_precedent_suivant}</p>
    
          </B_list_formations>
          	<p>Pas de formation disponible</p>
          <//B_list_formations>
          <div class="clear"></div> 
        
      </BOUCLE_familles>  	
      
    
      </BOUCLE_mot_principal>

    Si quelqu’un a une idée de où ca merdoie...

    Merci d’avance ;)

    Répondre à ce message

  • 10

    Bonjour,

    Est-il possible de limiter le résultat de la recherche à une rubrique ? La solution donnée sur le post du 27 mai 2011 à 15:59 ne semble pas fonctionner.

    • le critère s’appliquant à une boucle, il suffit de mettre le critère classique {id_rubrique=XXX} sur cette boucle.

    • Voici le formulaire :

      <form action="spip.php?page=recherche3" method="post" name="mot" >
      
      <select name="mots[0]">
      <BOUCLE_gr1(GROUPES_MOTS){id_groupe=4}>
      [<option>#TITRE</option>]
      <BOUCLE_mots4(MOTS){id_groupe}>
      <option value="#ID_MOT">#TITRE</option>
      </BOUCLE_mots4>
      </BOUCLE_gr1>
      </select>
      
      <select name="mots[1]">
      <BOUCLE_gr2(GROUPES_MOTS){id_groupe=5}>
      [<option>#TITRE</option>]
      <BOUCLE_mots5(MOTS) {id_groupe}>
      <option value="#ID_MOT">#TITRE</option>
      </BOUCLE_mots5>
      </BOUCLE_gr2>
      </select>
      
      <select name="mots[2]">
      <BOUCLE_gr3(GROUPES_MOTS){id_groupe=6}>
      [<option>#TITRE</option>]
      <BOUCLE_mots6(MOTS) {id_groupe}>
      <option value="#ID_MOT">#TITRE</option>
      </BOUCLE_mots6>
      </BOUCLE_gr3>
      </select>
      
      <input type="submit" value="chercher" name="ok">
      </form>

      Et voici la page de résultats :

      <BOUCLE_mot(MOTS){id_mot in #ENV{mots}}>#TITRE </BOUCLE_mot>
      
      <B_recherche_par>
      <div classe="liste">
      	<h3><:resultats_recherche:></h3>
      	
      	<ul class="liste-items">
      	<BOUCLE_recherche_par(ARTICLES){mots}{pagination 5}>
      		<li class="item">
      			<a href="#URL_ARTICLE">#TITRE</a>
      		</li>
      	</BOUCLE_recherche_par>
      	</ul>
      <p id="pagination" class="clearfix pagination nettoyeur">
      	#PAGINATION
      </p><!-- #pagination -->
      </div>
      
      </B_recherche_par>
         

      J’ai deux problèmes :

      1. Le formulaire passe les mots via #ENV à la page de résultats (et les mots sont affichés sur cette page) mais les articles ne s’affichent pas, sauf si j’écris dans l’URL "&mot[]=10&mot[1]=3...

      2. Si j’ajoute {id_rubrique=XXX} à ma boucle « recherche_par », il n’ a plus de résultat.

      Merci de toute lumière !

    • 1. Sans être expert en la question, je pense que tu devrait remplacer method="post" par method="get". Cela passera correctement les variables à l’URL.
      2. {id_rubrique=XXX} tu as bien remplacé XXX par la rubrique où tu veux limiter ?

    • Merci du retour rapide.

      La méthode get me renvoie à la page d’accueil car l’url créée donne ceci :

      spip.php ?mots%5B0%5D=12&mots%5B1%5D=17&mots%5B2%5D=2&ok=chercher

      Sinon oui, j’ai bien mis le numéro de rubrique.
      Petite précision, le site fonctionne avec zpip, cela peut éventuellement expliquer ces problèmes ?

    • Pour la rubrique, cela fonctionne, erreur d’étourderie ma part, il fallait mettre id_secteur=XXX, car les articles étaient dans des sous rubrique de la rubrique en question. Mais pour le passage des variables à l’URL, je ne vois pas comment faire...

    • il faut que tu mette l’url de page en hidden

      <input type="hidden" name="page" value="recherche3" />

      le fait d’être en zpip ne change rien à la question.

      (bon dans l’idéal faudrait faire un vrai form propre sous la forme de CVT)

    • Merci, cela appelle en effet la bonne page mais les crochets restent transformés dans l’URL ( &mots%5B2%5D=1), du coup la page résultats ne donne toujours rien.

    • les crochets ne sont pas responsables du problème. Ils sont normaux.

      Le pb doit venir d’ailleurs. Exemple là sur une page toto.html

      <form method="get">
      <input type="hidden" name="page" value="toto" />
      <B_mots>
      <select name="mots[1]">
      <BOUCLE_mots(MOTS){par titre}>
      	<option value="#ID_MOT">#TITRE</option>
      </BOUCLE_mots>
      </select>
      </B_mots>
      
      <BOUCLE_articles(ARTICLES){mots}{par titre}>
      #TITRE
      </BOUCLE_articles>	
      <input type="submit" value="chercher" name="ok">
      </form>

      Fonctionne parfaitement.

    • J’ai essayé avec cet exemple. Les crochets ne passent pas plus. Il sont systématiquement encodé en %5B et %5D dans l’Url. Test fait en local et sur serveur. Si quelqu’un a une piste....

    • je confirme avoir essayé cet exemple chez moi avant de te l’envoyer. Et même si les crochets sont encodés dans l’URL cela n’empêche pas le bon fonctionnement du critère.

      Du reste tu n’a qu’à vérifer en faisant [(#ENV{mots}|var_dump)] > tu verra que tu a bien affaire à un tableau.

      Ton pb doit venir d’ailleur, mais de quoi ?

    Répondre à ce message

  • ce plugin de fou...

    J’ai passé des centaines d’heures pour réaliser divers moteurs multicritères ces dernières années. Et ce soir je tombe sur ce plugin, tout fait, tout simple, tout bête et en 5mn j’ai un moteur qui fonctionne...

    Pourquoi j’avais jamais cherché avant ??? Pourquoi ???

    Merci !!!!

    Répondre à ce message

  • 6

    Hello ! :)

    Bon... plus j’utilise ce plugin et plus je le trouve génial.

    Mais là j’ai un cas de conscience. Sur une page rubrique, je liste un *très* grand nombre d’articles paginés par 15 que je souhaite pouvoir trier par mot clés, lesquels appartiennent à 2 groupes. Le premier exemple me parait approprié :

    http://www.toto.fr/?page=toto&amp;amp;mots[0]=XX&amp;amp;mots[1]=YY.

    Mais je cherche à savoir si l’on peut obtenir la même transmission de variable au contexte avec des paramètres ajax (donc passés avec des !# plutôt que des ? et des &) ?

    soit une écriture du style

    http://www.toto.fr/ma-rubrique#!mots[0]=XX&amp;amp;mots[1]=YY.

    Dans le but d’éviter des duplications de contenus malheureuse, ce qui arrive quasi systématiquement dès que l’on joue avec les paramètres d’url

    Une idée ?

    Merci d’avance ;)

    • heu, je vois pas en quoi ajax change quoique ce soit à ce pb. L’ajax made in spip passe automatiquement les params get...

    • L’ajax made in spip passe automatiquement les params get...

      C’est à dire ?

      je vois pas en quoi ajax change quoique ce soit à ce pb

      En fait, si, ca change quand même pas mal de chose à mon niveau :)

      En substance, quand Google croise page.html, page.html ?plop=pwet et page.html ?truc=machin&bidule=schmurtz, pour lui ca fait 3 pages distinctes à indexer même si chaque paramètre ne change réellement que 2 mots dans la page (donc contenu dupliqué à plus de 99% pour autant de page qu’il y a de valeur à chaque paramètre = pas bon pour ton ref !

      Alors que page.html, page.html# !plop=pwet etc... ne seront bien reconnue que comme une seule et même page (les fragments indépendants s’affichant en mode noJS pouvant alors être facilement non indexés

      Je ne sais pas si je suis clair là ? :D )

    • oui tu es clair, mais alors c’est un pb plus général à l’ajaxation, pas spécifique ici. A mon avis tu devrais en discuter sur user.

    • Bah en fait non c’est vraiment pas un problème lié à l’ajax. Moi le fonctionement ajax me convient bien mieux que des params d’url classiques.

      Là justement, je cherche à savoir si on peut ajaxer un peu le fonctionnement de ce plugin en fait ?

    • je comprend rien à tes propos...

      c’est pas compliqué l’ajax avec spip : <INCLURE{toto}{ajax}{env}>. Il suffit juste que ton form de select des mots clef soit dans toto et ca roule ...

    • OK je vais creuser par là alors. Je sais pas pourquoi je m’étais immaginé un truc plus compliqué. Je vais voir ça, merci :)

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom