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 connus.

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}

Il ne faut utiliser qu’une seule fois par boucle l’un 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;amp;mots[0]=1&amp;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
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 :

  1. [(#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); 

Footnotes

[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.

updated on 15 July 2019

Discussion

71 discussions

  • Je ne sais pas si ce plugin est pertinent pour ce que je veux faire?
    Tout se passe du côté public.
    Chaque administrateur restreint possède un groupe de mots-clés ayant exactement le même nom que l’auteur. Le premier mot généré dans son groupe est son nom. Ce mot-clé est attribué à l’auteur. De plus avec MOTUS le groupe de mots clés est lié à la rubrique restreinte de l’auteur.
    Dans son groupe, sur une page mots.html ou auteur.html je voudrais qu’il puisse ajouter des sous-groupes et des mots, puis lorsqu’il est dans un article ou un document ... qu’il puisse assigner le mot clé de son choix. Enfin je voudrais que la recherche se fasse uniquement dans son groupe de mots.
    J’arrive en partie à faire ce que je veux avec spipiculous et choix mots mais les mots-clés générés dans -tag- ne sont pas spécifiques à chaque utilisateur.
    Je pensais qu’une boucle MOTS dans un boucle auteurs ayant {id_auteur=#SESSION{id_auteur}} ferait l’affaire mais non.Dans tous mes essais il n’y a que ce code (trouvé dans spip@rezo.net) permet d’afficher pour chaque auteur son groupe et ses mots-clés utilisés.

    [(#REM) On crée le tableau ]
    #SET{mots, #ARRAY}
    
    [(#REM) On remplit le tableau avec les titres des mots liés à l'auteur connecté ]
    <BOUCLE_mots_auteur(MOTS){id_auteur=#SESSION{id_auteur}}>
        #SET{mots, #GET{mots}|push{#TITRE}}
    </BOUCLE_mots_auteur>
    
    <h3>Le contenu du tableau (pour info)</h3>
    [(#GET{mots}|foreach)]
    
    <hr />
    
    [(#REM) On sort les articles dont le mot est dans le tableau ]
    <h3>Les articles</h3>
    <BOUCLE_articles_mots(ARTICLES){titre_mot IN #GET{mots}}>
        <p>#TITRE</p>      
    </BOUCLE_articles_mots>

    Reply to this message

  • 3
    formatec

    J’ai besoin des conseils de la communauté car plusieurs pistes se dessinent, mais je ne sais pas pour laquelle opter.

    OBJECTIF: les visiteurs peuvent accéder à leur profil et modifier leurs centres d’intérêts. Ceux ci se présentent dans des groupes de mots clés. Les mêmes que ceux attribués aux articles, les boucles articles et evenements seront par la suite adaptées pour que chaque auteur/visiteur recoivent un contenu perso.

    -  j’ai ajouté un champs extra ’mot clé’ sur la table auteur, mais impossible de faire des choix multiples (ai-je mal vu? est ce possible?).

    -  autre possibilité: faut il opter pour un champs extra ’input’ qui recevra une array des choix persos de l’auteur et seront envoyés sur la table via:

           $preferences = implode(',', $preferences);     
          $set = array(
              'preferences ' => $preferences ,
         );
         sql_updateq(
             "spip_auteurs",
             $set,
    (...)

    -  mes recherches m’ont mené sur ce plugin ’critère mot’ , serait il une autre piste exploitable?

    Je cherche le plus simple et efficace, mais j’avoue que je suis un peu perdu....

    Merci de votre aide.

    K
    • Il y a deux points différents:
      -  comment tu stocke les mot clefs pour chaque utilisateur. La piste champ extra est une piste possible, à mon avis la plus pertinente, mais tu pourrais aussi associer des mots clefs aux utilisateurs.
      Inconvénient et avantage des deux solutions:
      L’avantage de champ extra est que l’interface sans doute plus simple à mettre en place côté publique (juste un formulaire), et les données seraient stockées sous forme de tableau, donc plus simple pour ta future requete. L’inconvénient est que pour le moment la saisie “Mot clefs” ne permet pas de saisir plusieurs mot clefs. A priori cela ne devrait pas être hyper compliqué de l’adapter, mais il faut quand même un peu de temps. Je te propose de le faire toi même, ou de poser la question sur le forum du plugin saisies si tu ne t’en sent pas les compétences.-
      -  comment tu t’en sert pour ensuite afficher un contenu personnalisé. Le plugin critères mots te permettra de faire cela.

    • formatec

      Merci pour tes conseils Maïeul, cela m’a provoqué une chouette nuit de code... ;-)

      J’ai donc exploré la piste du champs extra input qui conserve l’array de mes choix.

      J’ai fait une page de récap’ étape par étape. Avec les scripts et boucles utilisées pour ceux que cela intéresse : http://lakesapp.formatec.be/?page=t...

      Je coince sur deux choses:

      -  à l’etape3, comment faire pour que mon tableau de choix soit en statut “checked” si c’est le cas dans mon array de preferences ?

      -  et à l’étape 5, là ont est au coeur du plugin “critere mot” que je ne maitrise pas encore bien. Comment faire pour que cette boucle agenda devienne un agenda perso en fonction de mes mots favoris? Je pense que ton plugin est le meilleur moyen, mais je ne vois pas bien comment mettre en oeuvre.

    • Bon,

      en fait idéalement, il aurait mieux value la saisie (au sens du plugins saisie) mots pour que ton champs extra permette de gérer plusieurs mots. Là tu courcircuite le mecanisme de construction automatique de formulaire par le plugin champ extra. Mais passons.

      Deja, je serais toi je stocker l’identifiant du mot clef, et pas le titre, lequel est susceptible de changer.

      Dans ta boucle auteur, tu dois pouvoir récuperer ce qui est stocké dans le champ preferences, via la balise #PREFERENCES. Comme c’est un tableau, tu peux utiliser le filtre |in_array pour tester si cela correspond au mot courant. Voir exemple ici

      https://www.spip.net/fr_article4009.html

      Ensuite, puisque tu stocke tes id de mots dans un tableau #PREFERENCES d’une boucle auteur, il te suffit pour ta recherche d’avoir le critère {mots_selon_id #PREFERENCES} pour la boucle d’evebnement, elle même intégré dans la boucle d’auteur.

    Reply to this message

  • Bonjour,
    J’utilise ce plugin, mais je rencontre un problème, je m’explique :
    Je travaille avec deux groupes de mots clés : groupe1 et groupe2
    -  Pour groupe1 sont des case a coché et on peut sélectionner un ou plusieurs mots
    -  Pour groupe2 c’est juste une liste déroulant
    Voici mon formulaire :

      <BOUCLE_groupes(GROUPES_MOTS){id_groupe=1}>
             <ul>
             <h4>#TITRE</h4>
               <BOUCLE_mots(MOTS){id_groupe}{par titre}><li>
    <span class="logotheme"> </li><label>#TITRE</label><input type="checkbox" name="mots[0]" value="#ID_MOT" /></span></li>
              </BOUCLE_mots>
             </ul>
             </BOUCLE_groupes>
             
               <select name="mots[1]">
                    <option value=""> Votre choix</option>
                    <BOUCLE_select_grp(GROUPES_MOTS){id_groupe=2}>
                    <BOUCLE_motg(MOTS){id_groupe}{par titre}>     
                    <option value="#ID_MOT">#TITRE </option>
                    </BOUCLE_motg>
                    </BOUCLE_select_grp>
                     </select>

    Si je choisis un mot dans groupe1 et un dans le groupe 2, le résultat s’affiche correctement....Par contre si je choisis plusieurs mots dans le groupe1(case cochet), le résultat est erroné

    Voici la boucle du résultat

    <B_articles>
                                       <h2>#GRAND_TOTAL </h2>
                                    
                                         <ul>
    <BOUCLE_articles(ARTICLES) {recherche?} {!par #ENV{tri,points}} {mots?}>
    <li><a href="#URL_ARTICLE">#TITRE</a></li>
                                            </BOUCLE_articles>
                                            </ul>
                                            </B_articles>
                            <h2><em>Pas de résultat trouvé</em></h2>
                                    <//B_articles>

    En gros sont les case a cochet qui pose probléme
    Merci de votre aide

    Reply to this message

  • 3

    Bonjour,

    Je rencontre un problème de réantrance.
    Je m’explique : je veux :

    • avoir 3 listes de mots sélectionnables (cases à cocher)
    • récupérer les événements qui ont au moins un mot de chaque liste (ou pas de filtre sur cette liste si aucun mot n’est sélectionné dans une liste)

    Autrement dit, un filtre à la LDLC.com

    Côté formulaire, c’est bon !

    Côté boucle, en lisant la doc, j’en ai conclus que

    <BOUCLE_Evt2(EVENEMENTS)
      {par date_debut}
      {mots? 0 #ENV{motstheme}}
      {mots? 0 #ENV{motscible}}
      {mots? 0 #ENV{motszone}}
    >

    devrait marcher.

    Le Code SQL généré est presque bon, à un détail près : il prend en compte 3 fois les mots sélectionnés dans la 3e liste :

    SELECT evenements.id_evenement, evenements.date_debut, evenements.titre
    FROM spip_evenements AS `evenements`
    WHERE (evenements.statut = 'publie')
    	AND evenements.id_evenement IN (
    		SELECT id_objet FROM spip_mots_liens WHERE id_mot=27 and objet='evenement' OR id_mot=31 and objet='evenement' GROUP BY id_objet,objet  HAVING SUM(1) >= 0
    	)
    	AND evenements.id_evenement IN (
    		SELECT id_objet FROM spip_mots_liens WHERE id_mot=27 and objet='evenement' OR id_mot=31 and objet='evenement' GROUP BY id_objet,objet  HAVING SUM(1) >= 0
    	)
    	AND evenements.id_evenement IN (
    		SELECT id_objet FROM spip_mots_liens WHERE id_mot=27 and objet='evenement' OR id_mot=31 and objet='evenement' GROUP BY id_objet,objet  HAVING SUM(1) >= 0
    	)
    ORDER BY evenements.date_debut

    J’ai essayer de regarde le code du critère, mais je ne sais pas pourquoi $quoi n’est pas pris en compte pour différencier les 3 IN (SELECT...

    • salut,
      je viens de voir ton message. Comme cela je ne sais pas. Il me faudrait vraiment une base de test et un formulaire pour y voir plus clair.

    • Quelque chose me dit qu’il faudrait incrémenter dans critere_mots_dist() la variable $mots_where à chaque usage du critère dans une même boucle.

      Si on savait la position du critère dans la boucle, ça suffirait d’ailleurs comme suffixe.

    • Bon, voilà qui devrait résoudre ce point :
      https://zone.spip.org/trac/spip-zone/changeset/104950

      Note : ça marche chez moi.

      <BOUCLE_circuits(XXXS)
      	{id_xxx ?}
      	{mots_selon_id? 100% #ENV{mots}}
      	{mots_selon_id? 1 #ENV{mots_ou_1}}
      	{mots_selon_id? 1 #ENV{mots_ou_2}}
      	{mots_selon_id? 1 #ENV{mots_ou_3}}
      	{recherche ?}
      	{","}
      >

      Où :
      -  mots est une liste optionnelle d’identifiants de mots où je fais des ET systématiques entre eux
      -  mots_ou_n est une liste optionnelle d’identifiants ou je fais des OU entre eux.

    Reply to this message

  • Utilisation de mots dans un include.

    Je souhaite utiliser ce critères mots? dans un fichier include.

    inclusion : [(#INCLUREfond=inc_ressource_mot_and id_rubrique=#ENVidrubriquerechercheid_motid_auteurenvajax)]

    Boucle dans le include :

    -  peut-on mettre un ? comme pour un autre critère optionnel ?
    -  à première vue il ne comprend pas si on ajoute simplement id_mot à l’include. Faut-il refaire le tableau id_mot ?

    Merci de votre aide.
    Julien

    Reply to this message

  • 9
    Spipmalion

    Bonjour,

    Depuis la maj vers plugin SPIP critère mots 3.0.1 le critère !id_mot ne fonctionne plus

    Fait planter le site, erreur SQL :

    1. <BOUCLEa(MONOBJET){!id_mot=5}{mots}>

    Le critère !id_mot n’est pas pris en compte :

    1. <BOUCLEa(MONOBJET){mots}{!id_mot=5}>

    On dirait en revanche que les requêtes SQL sont plus rapides.

    • oui, les requetes SQL sont plus rapides. C’était du reste le but de l’optimisation.

      Faut que je vois pour la question du critère {!id_mot}, mais celui-ci est déjà piègeux dans certains cas.

      Bref, je vais essayer de voir cela ce week-end. N’hésite pas àme relancer si besoin.

    • Spipmalion

      Up up relance urgent, site foutu sans !id_mot= ; normalement il devrait y avoir des centaines de milliers de sites foutus suite à cette maj, avec des boucles qui séléctionnent n’importe quoi

      Une autre manière d’exclure un mot d’une boucle en attendant que celui-ci refonctionne ?

      Merci d’avance

    • mettre

      define ('_CRITERE_MOTS_OPTIMISE',0);

      dans mes_options.php. Cela rebasculera sur l’ancien système, plus lent mais visiblement fonctionnel. Désolé mais je peux pas m’occuper de voir comment utiliser le système optimisé avant dimanche.

    • bon, j’ai pu me dégager du temps. La version 4.0.0 évite ce problème tout en optimisant la requete (ou plus précisement, en contournant un bug de mysql 5)

    • un petit retour sur la version 4.0.0? apparemment ce n’était pas si urgent que cela…

    • Spipmalion

      Bonjour Maïeul,

      J’ai du recoder en urgence le site en utilisant un autre système suite à la défaillance du plugin
      Je vais le réutiliser et te donnerais un retour
      Merci pour la mise à jour

      Bien cordialement

    • pourtant je t’ai donné en 4 heure la réponse pour revenir à l’ancien systeme…

      et franchement ton cas est à mon avis vraiment exceptionnel…

    • Spipmalion

      Les joies de l’informatique !

    • Oui, {!id_mot=XX} est parfois piégeux. Pour des boucles de recherches, notamment, j’ai dû utiliser {!titre_mot=exclure} pour avoir le résultat voulu. Ce n’est pas l’idéal mais ça fonctionne.

    Reply to this message

  • 2

    Bonjour.

    Sur mon site de tests, après passage de la version 3.0.1 à 4.0.0, et sur une page utilisant le critère mots, j’ai le contenu de l’array qui s’affiche au-dessus du doctype (et sur la page !) :

    array(14) {
      [0]=>
      string(5) "13192"
      [1]=>
      string(5) "13210"
      [2]=>
      string(5) "13218"
     
    […]
    
      [12]=>
      string(5) "13365"
      [13]=>
      string(5) "13594"
    }

    Les strings correspondent bien aux articles (publiés ou non) ayant le mot-clé demandé. Je n’ai pas vu d’autre problème : le reste de la page s’affiche correctement.

    SPIP 3.1.3, PHP 5.3.3 (Je sais, je dois demander à notre hébergeur de faire un upgrade…)

    Joyeux décembre !

    1138.

    Reply to this message

  • 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!

    Reply to this 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 `articles`  
      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 `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

      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 `mu_localhost`.spip_articles AS `articles` INNER JOIN `mu_localhost`.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 `mu_localhost`.spip_articles AS `articles` WHERE (articles.statut = 'publie') AND articles.id_article IN ( SELECT id_objet FROM `mu_localhost`.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

    Reply to this 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 2nd 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 ...

    Reply to this message

Comment on this article

Who are you?
  • [Log in]

To show your avatar with your message, register it first on gravatar.com (free et painless) and don’t forget to indicate your Email addresse here.

Enter your comment here

This form accepts SPIP shortcuts {{bold}} {italic} -*list [text->url] <quote> <code> and HTML code <q> <del> <ins>. To create paragraphs, just leave empty lines.

Add a document

Follow the comments: RSS 2.0 | Atom