À l'aide sur les jointures automatiques de SPIP !

J’ai aussi l’impression que si je passais par une table de jointure classique comme du documents_liens, ça fonctionnerait. Question de priorité des jointures peut-être ?

ça c’est facile de le savoir : ?var_mode=debug t’indiquera précisément comment spip comprend et compile ta boucle.

Non, je dis juste que c’est possible de demander à spip de jointer sans faire de déclaration préalable en PHP. Mais il se peut que ça ne soit pas compatible avec ton envie de ne pas devoir expliciter la 2eme table.

Perso, s’il faut galérer pour obtenir une jointure automatique invisible… alors je préfère la beauté d’une jointure visible qui marche direct .

Le plugin La Fabrique est un super outil pour fabriquer des objets… et les déclarations PHP qui vont bien et font ce qu’il faut. Je te conseille vivement de l’essayer car il intègre aussi un paramétrage click and play des jointures… Toute les complexités des situations et projets possibles ne sont pas pris en compte avec autant de facilité, et l’interface et les indications affichées sont un peu simplistes et ça reste donc complexe à fine-tuner au besoin, mais il n’est pas impossible que ça génère pile poil ce qui te convient.

Je te conseillerais donc d’essayer et quand tu auras reproduit ce que tu veux, soit utiliser direct le résultat, soit t’en inspirer pour réintégrer les bouts de code générés dans ton plugin.

Merci @JLuc , effectivement, je vois dans le debug que la requête qui part ne cherche à faire aucune jointure malgré la demande d’un champ externe, le from est juste centré sur l’objet de la boucle, logique qu’il ne trouve rien… :frowning:

Super, j’utilisais la Fabrique a sa sortie, mais je l’ai perdu de vue depuis, je m’y remets :wink:

Dans le debug je peux voir que dans le select, mon champs externe n’est pas présent, et que le paramètre join est vide, mais aussi que le from n’indique que la table de l’objet :

if (!isset($command['table'])) {
16        $command['table'] = 'agences';
17        $command['id'] = '_agence';
18        $command['from'] = array('agences' => 'spip_agences');
19        $command['type'] = array();
20        $command['groupby'] = array();
21        $command['select'] = array("agences.nom");
22        $command['orderby'] = array();
23        $command['join'] = array();
24        $command['limit'] = '';
25        $command['having'] = 
26            array();
27    }

Il me semble donc qu’aucune jointure automatique ou explicite via les déclarations dans les pipelines ne soient tentées.

Les jointures ne se font que via des champs qui sont aussi des clés de la table. La déclaration join est un helper pour les cas ou il faut faire la jointure entre des champs pas homonymes par exemple.

Pour reprendre ton exemple du début, si tu veux qu’une jointure entre spip_chiens et spip_race puisse se faire, il faut que le champ id_race de la table spip_chiens soit déclaré en index de la table, comme ici le champ id_rubrique de la table spip_articles

Bonjour à tous, et merci encore une fois pour vos retours.

Je galère sévère !

J’ai eu quelques résultats en forçant les tables dans les boucles comme le proposait @JLuc.
Néanmoins, j’ai l’impression d’être limité dans mon projet lorsque je veux faire une jointure sur une troisième table ou plus pour récupérer d’autres informations.

Si je reprends les exemples canins avec 3 objets :

spip_chiens
	id_chien (PK)
	nom
	id_race (KEY)

spip_races
	id_race (PK)
	nom
	id_pelage (KEY)

spip_pelages
	id_pelage (PK)
	nom
	type_pelage (KEY)

Est-ce que cela est juste, possible :

<BOUCLE_recuperer_pelage(CHIENS spip_races spip_pelages){id_chien=21}{0,1}{tout}>

		#NOM (chien N°#ID_CHIEN) a le pelage #TYPE_PELAGE

</BOUCLE_recuperer_pelage>

Vous semble t’il intéressant de créer un plugin test/tuto avec plusieurs objets de ce type pour relever ces challenges de jointures et documenter cela ?

Il ya bien longtemps déjà, j’avais rédigé ça sur le sujet Divagations sur les jointures avec SPIP - Le labo

1 « J'aime »

Ah, aussi, une dernière interrogation, au sujet de la déclaration des cles des objets dans le pipeline declarer_tables_objets_sql($tables)

Dans « key » on voit généralement ce format :

'key' => array(
	'PRIMARY KEY'  => 'id_chien',
	'key id_race'  => 'id_race',
),

Mais la doc de MYSQL indique que le terme « key » est propres à MYSQL et est un alias de « INDEX » qui est plus facilement portable.

Est-ce que modifier la déclaration par

'key' => array(
	'PRIMARY KEY'     => 'id_chien',
	'UNIQUE INDEX'  => 'id_race',
),

a une incidence pour SPIP et son mécanisme de jointures ?

Merci beaucoup, ma nouvelle bible à compulser :wink:
Je vais tenter de suivre cela et voir si cela me décoince, merci encore !

Un grand merci à tout le monde et notamment à @b_b dont les divagations sur les jointures m’ont permis d’aboutir.

Je n’explique toujours pas pourquoi je n’arrive pas à joindre des informations en utilisant une deuxième table qui dispose d’une clé égale à la clé primaire de la première table…

Mais la définition d’un critère personnalisé surchargeant le « from » et explicitant dans le « where » la jointure à faire m’ont permis de trouver une issue favorable. Voici pour ceux qui chercherait un exemple simple :

function critere_agence_augmentee_dist($idb, &$boucles, $crit) {
	
	$boucle = &$boucles[$idb];
	
	$boucle->from['agences_details'] = 'spip_agences_details';
	
	$where = array("'='", "'agences.id_agence'", "'agences_details.id_agence'");
	$boucle->where[] = $where;	
	
}

Super. Avec l’ajout de ce code, <BOUCLE(AGENCES){agence_augmentee}> devient équivalent à la <BOUCLE(AGENCES spip_agences_details)> désirée ; c’est ça ?

Bonjour @JLuc, c’est exactement ça, ainsi depuis une boucle <BOUCLE(AGENCES){agence_augmentee}>, je peux accéder à tous les champs (non homonymes) présents dans l’objet AGENCES_DETAILS.

Cool.
De la même manière avec ce critère tu peux certainement créer un vrai JOIN.

Yes, mais pas encore compris les subtilités de l’écriture du join version SPIP :wink:

Je garde ce petit plaisir pour une prochaine fois !

Ouais c’est pas évident, mais je me dis que c’est plus simple à faire dans un critère que dans la table de déclaration d’un objet, car dans le critère on est une étape d’interprétation plus près du MYSQL de base final…

Bon, finalement, j’ai pu aboutir !

Voici pour les suivants, une solution à base de déclaration d’un critère spip, permettant d’effectuer un LEFT JOIN.

Contexte : enrichir une BOUCLE ENTREPRISES (spip_entreprises) en y adjoignant une table ENTREPRISES_DETAILS partageant une même clef primaire (id_entreprise) que la table mère de la boucle :

function critere_entreprise_augmentee_dist($idb, &$boucles, $crit) {
	
	$boucle = &$boucles[$idb];
	
	$boucle->from['entreprises_details'] = 'spip_entreprises_details';
	$boucle->from_type['entreprises_details'] = 'LEFT';
	$boucle->join['entreprises_details']= array(
		"'entreprises'",
		"'id_entreprise'",
		"'id_entreprise'"
	);	
	
}
2 « J'aime »

Super classe du feu de la queue de SPIP !

Hop dans la doc : Créer un critère pour une jointure - Programmer avec SPIP 4
Merci pour ces partages

1 « J'aime »