Spip allergique aux JOIN ?

Hello à tous,

J'ai mis en place un pseudo forum basé sur une structure par article spip
pour les têtes de topics et message forum spip pour les posts dans les
topics.

Si la structure fonctionne au niveau fonctionalités, j'ai quelques problèmes
dans les requetes que je fait pour aller checher ce dont j'ai besoin.
A coup de multiples boucles imbriquées, j'arrive à extraire ce que je veux,
mais ca génère des multiples requetes qui ne servent à rien.

En particulier pour le besoin suivant:
Sur la page de chaque partie du forum, je liste les topics, en cherchant à
les trier par date de dernier message posté, ou si il n'y en a aucun par
date de publication de l'article.
A l'heure actuelle, je ne peux pas faire ca, je fais donc deux listes:
- liste des topics avec réponses.
- liste des topics sans réponses.

Hors, j'ai un moyen de sortir mes infos via une requete SQL (un peu tordue,
je l'admets):

SELECT spip_articles.id_article, GREATEST(spip_articles.date,
COALESCE(forum.date_heure,0)) AS date_thread FROM spip_articles LEFT JOIN
spip_forum ON spip_forum.id_article = spip_articles.id_article WHERE (
spip_forum.statut = "publie" or spip_forum.statut IS NULL) AND
spip_articles.id_rubrique = 'ID_RUBRIQUE'
GROUP BY spip_articles.id_article
ORDER BY date_thread DESC

En dehors du fait que le LEFT JOIN me permet de lister TOUS les articles de
la rubrique, même ceux sans message dans le forum, je ne vais pas rentrer
plus dans les détails de la requete, et elle me sort ce dont j'ai besoin.

Vu que la requete se base sur un SELECT FROM spip_articles, je me suis dis,
essayons de rajouter un critère pour gérer tout celà.

Voici donc ce que j'ai rajouté comme critère dans mes_fonctions.php

function critere_topics($idb, &$boucles, $param, $not) {
$boucle = &$boucles[$idb];
$boucle->select[] = "GREATEST(spip_articles.date,
COALESCE(spip_forum.date_heure,0)) AS date_thread";
// $boucle->from[] = "LEFT JOIN spip_forum ON spip_forum.id_article =
spip_articles.id_article";
$boucle->where[] =
array("'OR'",array("'='","'spip_forum.statut'","'publie'"),array("'IS'","'spip_forum.statut'","'NULL'"));
$boucle->groupby[] = "spip_articles.id_article";
}

Et voilà mon problème:
Le from est commenté car j'ai BESOIN de faire une requete via un LEFT JOIN
et pas un WHERE + condition de jointure. C'est en effet la seule solution
qui me permet de récupérer les topics (articles) sans post (message de forum
avec statut publie)
J'ai essayé d'autres solutions, mais:
- Utiliser un $boucle->join ne me fait pas du tout ce dont j'ai besoin
- Utiliser les jointures automatiques via un <boucle_b(ARTICLES
spip_forum){topics}{id_rubrique}>#ID_ARTICLE #ID_THREAD</boucle_b> ne me
fait pas un left join mais une jointure via WHERE

Bref, impossible d'arriver à faire une LEFT JOIN via un critère et/ou une
boucle.
Et dans les recherches que j'ai pu faire, je ne trouve que des jointures
effectuées par conditions WHERE jamais de LEFT JOIN.
Sachant qu'il est impératif que la boucle déclanche un recyclage en cas de
message sur le forum (faut que j'arrive à trouver ce qui déclanche le
recyclage du cache et qu'est-ce qui se fait recycler mais ca c'est une autre
histoire je pense :D)

Anyway, SPIP est-il allergique aux bon vieux JOIN ?

Oxy a écrit :

Anyway, SPIP est-il allergique aux bon vieux JOIN ?

et pourquoi ne pas faire une vue SQL ?

--
Jean-Max Reymond
Eruption de l'Etna: Eruption de l'Etna 2002

Jean-Max Reymond <jmreymond <at> hotmail.com> writes:

Oxy a écrit :
>
> Anyway, SPIP est-il allergique aux bon vieux JOIN ?
>

et pourquoi ne pas faire une vue SQL ?

Alors effectivement via une view ca marche (je n'y
avait pas pensé).

Sauf que:
- les champs sont déterminés dans la view que je
génère
- les infos des champs doivent être rajoutés dans
la liste des $tables_principales
- impossible de modifier après coup les champs sous
peine de devoir tout refaire

Bref, c'est clairement un mieux par rapport à ce que
c'est à l'heure actuelle, mais c'est pas encore
exactement le top (qui reste de faire un vrai join
propre :))

Jean-Max Reymond <jmreymond <at> hotmail.com> writes:

Oxy a écrit :
>
> Anyway, SPIP est-il allergique aux bon vieux JOIN ?
>

et pourquoi ne pas faire une vue SQL ?

Snif, la requete ci-dessus avait encore un manque, les forums avec contributions
refusées (donc passées en statut off)

Je me vois donc contraint à faire ca via une union:
---
SELECT spip_articles . * , spip_forum.date_heure AS date_post,
spip_forum.statut AS statut_total FROM `spip_articles`
LEFT JOIN spip_forum ON spip_forum.id_article = spip_articles.id_article
WHERE spip_forum.statut = "publie" AND spip_articles.id_rubrique = "42"
GROUP BY spip_articles.id_article

UNION

SELECT spip_articles . * , spip_articles.date AS date_post,
group_concat( DISTINCT spip_forum.statut ) AS statut_total
FROM spip_articles
LEFT JOIN spip_forum ON spip_forum.id_article = spip_articles.id_article
WHERE spip_articles.id_rubrique = "42"
GROUP BY spip_articles.id_article
HAVING statut_total IS NULL OR statut_total NOT LIKE '%publie%'

ORDER BY date_post DESC
---
Et là pour le coup je pense que c'est peine perdue pour faire
ca via une boucle traditionnelle.

Reste donc la solution du plugin ou de la fonction spéciale.

Merci en tous cas pour l'idée de la view ca me sera peut-être utile

Pour ceux que ca intéresse, j'ai fait un truc pas super propre, mais j'avoue
sécher pour l'intégrer mieux via les abstractions de spip.

L'énorme ennui que j'ai c'est le passage des paramètres mais ca me fait ce
que je veux donc je vais pas aller couiner :wink:
Passer de 5 secondes de calcul de la page (via 150 requetes SQL) à quelques
milisecondes, c'est quand même pas du luxe.

<BOUCLE_1(TOPICSFORUM){id_rubrique}>
#ID_ARTICLE : #TITRE (#DATE_POST ref: #ID_POST par #POSTEUR) [Total:
#TOTAL_POST]<br/>
</BOUCLE_1>

Avec la boucle en question qui donne ca:

$topics = array(
"id_rubrique" => "int(11)",
"id_article" => "int(11)",
"id_post" => "int(11)",
"titre" => "varchar(255)",
"date_post" => "varchar(255)",
"total_post" => "int(11)",
"posteur" => "varchar(255)"
);
$topics_key = array(
"PRIMARY KEY" => "id_article"
);

global $tables_principales;
$tables_principales['topicsforum'] =
array('field' => &$topics, 'key' => &$topics_key,
'join' => "");

spip_log("OK");

function boucle_TOPICSFORUM ($id_boucle, &$boucles) {

$query = "\n\n\t\$result = spip_query(\"SELECT spip_articles.id_article as
id_article, spip_articles.titre as titre, spip_forum.auteur as posteur,
spip_forum.id_forum as id_post, spip_forum.date_heure as date_post,
count(id_forum) as total_post, spip_forum.statut as statut_total FROM
`spip_articles` LEFT JOIN spip_forum on spip_forum.id_article =
spip_articles.id_article WHERE spip_articles.statut = 'publie' AND
spip_articles.id_rubrique = \"._q(\$Pile[\$SP]['id_rubrique']).\" AND
spip_forum.statut = 'publie'
group by spip_articles.id_article
UNION
SELECT spip_articles.id_article as id_article, spip_articles.titre as titre,
'0' as id_post, '' as posteur, spip_articles.date as date_post, 0 as
total_post, group_concat(distinct spip_forum.statut) as statut_total FROM
spip_articles LEFT JOIN spip_forum on spip_forum.id_article =
spip_articles.id_article WHERE spip_articles.statut = 'publie' AND
spip_articles.id_rubrique = \"._q(\$Pile[\$SP]['id_rubrique']).\"
GROUP BY spip_articles.id_article
HAVING statut_total IS NULL OR statut_total NOT LIKE '%publie%'

ORDER BY date_post desc\");";

$corps = calculer_boucle_nonrec($id_boucle, $boucles);

$req = $query;

$notrace = (_request('var_mode_affiche') != 'resultat');
return $req . $corps . ($notrace ? "" : "boucle_debug_resultat('$id_boucle',
'resultat', \$t0);") . "\n return \$t0;";

}

"Oxy" <oxygen@metro-pole.net> a écrit dans le message de news:
loom.20070807T145811-143@post.gmane.org...
Jean-Max Reymond <jmreymond <at> hotmail.com> writes:

Oxy a écrit :
>
> Anyway, SPIP est-il allergique aux bon vieux JOIN ?
>

et pourquoi ne pas faire une vue SQL ?

Snif, la requete ci-dessus avait encore un manque, les forums avec
contributions
refusées (donc passées en statut off)

Je me vois donc contraint à faire ca via une union:
---
SELECT spip_articles . * , spip_forum.date_heure AS date_post,
spip_forum.statut AS statut_total FROM `spip_articles`
LEFT JOIN spip_forum ON spip_forum.id_article = spip_articles.id_article
WHERE spip_forum.statut = "publie" AND spip_articles.id_rubrique = "42"
GROUP BY spip_articles.id_article

UNION

SELECT spip_articles . * , spip_articles.date AS date_post,
group_concat( DISTINCT spip_forum.statut ) AS statut_total
FROM spip_articles
LEFT JOIN spip_forum ON spip_forum.id_article = spip_articles.id_article
WHERE spip_articles.id_rubrique = "42"
GROUP BY spip_articles.id_article
HAVING statut_total IS NULL OR statut_total NOT LIKE '%publie%'

ORDER BY date_post DESC
---
Et là pour le coup je pense que c'est peine perdue pour faire
ca via une boucle traditionnelle.

Reste donc la solution du plugin ou de la fonction spéciale.

Merci en tous cas pour l'idée de la view ca me sera peut-être utile

Oxy a écrit :

Avec la boucle en question qui donne ca:

Bravo !

BoOz