jointure de table non conventionnelles

Bonjour,

j’essaie de créer une connection entre spip et des tables de dolibarr. Hors dans celui-ci les tables n’ont pas la même logique que dans spip.
La table principale à laquelle j’eccède est la table product dont la clé est le champs ‹ rowid ›. Jusque là tout va bien.
Avec le pipeline declarer_tables_interfaces je crée un alias:

$interfaces['table_des_tables']['product'] = 'product';
$interfaces['exceptions_des_tables']['product']['id_product'] = array('product','rowid');

Là où celà se complique c’est que cette table est complété par une table product_extrafields pour laquel la clé est aussi rowid et le lien entre les 2 tables est le champs fk_object (qui se réfère à rowid de la table product).

$interfaces['exceptions_des_tables']['product_extrafields']['id_product'] = array('product_extrafields','fk_object');

et j’aimerai faire une jointure entre les 2 tables, avec le champs fk_object de la table product_extrafields et le champs rowid de la table product.

Comment faire ?

j’ai trouvé une solution ! J’écris un plugin pour faire cette connections (entre autre).
et en utilisant le pipeline pre_boucle (en cours d’écriture, y a sûrement des trucs qui vont bouger) :

function dolibarr_pre_boucle($boucle){
    
    if( $boucle->sql_serveur == 'dolibarr' ){ // acccès à une table de dolibarr
        if( in_array($boucle->id_table , ['product', 'commande', 'commandedet', 'facture', 'facturedet', 'expedition', 'expeditiondet', 'propal', 'propaldet']) ){    // table pour lesquels ajouter des jointure
            
            // si aucun critère de la boucle ne provienne de la table jointe alors spip ne fera pas la jointur automatiquement,
            // et ceci même si des balises proviennent de cette table.
            // le code de cette fonction a donc 2 buts
            //      * 1. forcer la jointure
            //      * 2. ajouter des critères obligatoires
            //      * 3. parametrer la jointure entre object.rowid et object_extrafields.fk_object


            /* 1. forcer la jointure
            * =======================
            */

            $nom="";    // alias de la table
            if( ! in_array ("spip_".$boucle->id_table."_extrafields",$boucle->from) ){ // table object_extrafields non présente dans le tableau 'from'

                // recherche d'un alias Lx non utilisé
                $n=1;
                while( in_array("L$n", array_keys($boucle->from))){
                    $n++;
                }
                $nom="L$n"; // alias trouvé

                // ajout de la table object_extrafields dans la liste des 'from'
                $boucle->from[$nom]="spip_".$boucle->id_table."_extrafields";
                if(! isset($boucle->show['table_jointures']) ){ // si pas de jointure (cas ou aucun critère ne viens de la table jointe)
                    $boucle->show["tables_jointures"]=[];   // on ajoute la table des jointures
                }
                $boucle->show["tables_jointures"][""]="spip_".$boucle->id_table."_extrafields"; // on y met la table object_extrafields
                
            } else {    // table object_extrafields présente dans le tableau 'from'
                $t=array_flip($boucle->from);
                $nom=$t["spip_".$boucle->id_table."_extrafields"];  // on récupère son alias
            }
            // recherche des alias
            $listeAS=[];
            foreach($boucle->select as $champs){
                if( preg_match('/(AS)[ ]+([a-zA-Z_]+$)/', $champs, $matches)){
                    $listeAS[]=$matches[2];
                }
            }

            
            // parcours de toutes les balises et vérification si elle sont présente.
            $i=0;
            foreach( array_merge($boucle->preaff, $boucle->avant, $boucle->milieu, $boucle->apres, $boucle->altern, $boucle->postaff) as $elt ){
                if( $elt->type == "champ" ){    // parcours de toutes les balises
                    if( ! in_array(strtolower($elt->nom_champ),$listeAS) && ! in_array(strtolower($elt->nom_champ),array_keys($boucle->show['field']))){    // si ce n'est pas un alias (listeAS) et que'elle est absente de show['field'] (champs de la table principale)

                        
                        if( ! in_array("$nom.".strtolower($elt->nom_champ), $boucle->select)) $boucle->select[]="$nom.".strtolower($elt->nom_champ); // ajout dans 'select' (si pas déjà présent)

                        if( ! isset($boucle->index_champ[$elt->nom_champ])) $boucle->index_champ[$elt->nom_champ]=$boucle->id_boucle; // ajout dans 'index_champ'

                        // correction du code pour extraction du champs
                        $elt->code='$Pile[$SP][\''.strtolower($elt->nom_champ)."']"; 
                        // et du code de retour de la boucle
                        $boucle->return = str_replace('@$Pile[0][\''.strtolower($elt->nom_champ)."']", '$Pile[$SP][\''.strtolower($elt->nom_champ)."']", $boucle->return);
                    }
                }
            }

            // ajout de la table object_extrafield dans la liste des table jointe 'join'
            if( ! isset($boucle->join[$nom]) ) $boucle->join[$nom]=array("'".$boucle->id_table."'","'rowid'");

            if( ! isset($boucle->modificateur["lien"])) $boucle->modificateur["lien"]=true;


            /* 2. ajout de critères obligatoire
            * ==================================
            */ 
            // A FAIRE
            if( $boucle->id_table == 'product' ){
                // ajouter critère permanent sur id_rubrique_xxx NOT NULL
                //$boucle->where[]=array("'>'", "'$nom.fk_object'", "'0'");
            }
            

            /* 3. correction du paramétrage de la jointure
            * ===============================
            */
            // jointure entre le champs object.rowid (object étant la table sur laquelle on boucle product/commande/facture ....) et le champs object.extrafields.fk_object

            // $boucle->join=array( 'table_jointe' (ici object_extrafields) => ( 'table_base' (ici "object"), 'colonne dans table jointe' (ici fk_object), 'colonne dans table origine' (ici rowid) ))
            $boucle->join=array($nom=>array("'".$boucle->id_table."'","'fk_object'","'rowid'"));    
        }
    }
    return $boucle;
}
1 « J'aime »

C’est une problématique intéressante et qui peut concerner d’autres sites
alors merci pour ce bout de code.
Tu crées un plugin dédié à cette connexion, écris tu ?
Ce serait bien de le déposer sur le repo collectif des contrib git.spip.net
ou déjà de communiquer ici la version finale de ton code, s’il a évolué…

1 « J'aime »