Carnet Wiki

MultiBase

Version 4 — Mars 2007 NicolasR

Déclarer une table SPIP ou non SPIP d’un autre serveur MYSQL

Simple copié collé du message de Emmanuel visible également ici http://article.gmane.org/gmane.comp...

Il est à présent possible, non seulement de lire d’autres tables SQL que celles propres à Spip, mais également d’aller lire des tables présentes sur d’autres serveurs, typiquement d’autres sites sous SPIP mais pas seulement.

Pour ce faire, la syntaxe des types de boucles est étendue avec la notation suivante :

<BOUCLE_EXT(site-annexe:ARTICLES)>#TITRE</BOUCLE_EXT>

qui va lister tous les titres de la table article du serveur site-annexe

<BOUCLE_AUTREXEMPLE(site-pas-mal-non-plus:CATALOGUE)>
</BOUCLE_AUTREXEMPLE>
<br>#TOTAL_BOUCLE au catalogue
</B_AUTREXEMPLE>

[Erreur...3][Erreur...4][Erreur...5]qui va ramener le nombre d’entrées de la table CATALOGUE du server « site-pas-mal-non-plus ».

Pour arriver à ce résultat il faut toutefois déclarer les nouveaux serveurs avec leur identifiant de connexion.
Chacun est déclaré dans un fichier portant son nom, préfixé par « inc_connect- » et suffixé par « .php » ou « .php3 », le fichier étant placé dans ecrire (donc ci-dessus, il faut ecrire/inc_connect-site-annexe.php).
Ce fichier doit contenir 4 fonctions (où NOM est à nouveau le nom du serveur) :

- function spip_NOM_fetch($res, $serveur) équivalente à spip_fetch_array (i.e. mysql_fetch_array) dans le serveur usuel
-  function spip_NOM_count($res, $serveur) équivalente à spip_num_rows (i.e. mysql_num_rows) dans le serveur usuel
-  function spip_NOM_free($res, $serveur) équivalente à spip_free_result (i.e. mysql_free_result) dans le serveur usuel
-  function spip_NOM_select($select, $from, $where, $groupby, $orderby, $limit, $sousrequete, $cpt, $table, $id, $serveur) équivalente à spip_mysql_select dans le serveur actuel (i.e. mysql_query après un pré-traitement non négligeable).

Les 4 fonctions du serveur usuel figurent dans ecrire/inc_db_mysql.php3 et il faut évidemment s’en inspirer pour écrire les 4 nouvelles, ainsi que de inc-connect.php3 pour la gestion des identifiants de connexion.

[Erreur...7][Erreur...8][Erreur...9]Ce fichier sera lu à l’exécution de la première boucle référençant ce serveur, et ne sera plus lu par la suite ; on peut donc y placer l’ouverture de la connexion.

Si le site annexe est sous un Spip de même numéro de version, cela doit suffire car la description des tables dans le inc_serialbase du serveur principal servira à interroger celles du serveur distant.

En revanche, si l’on veut en plus accéder à des tables spécifiques, il faut les ajouter à la globale $tables_principales, par exemple comme je le disais tout à l’heure ainsi :

$spip_title = array(
        "id"        => "bigint(21) NOT NULL",
        "title"        => "text NOT NULL"
);
$spip_title_key = array(
        "PRIMARY KEY"                => "id"
);
$GLOBALS['tables_principales']['title']= array('field' => &$spip_title, 'key' => &$spip_title_key);

Comme il n’est pas question de placer cette affectation directement dans le fichier inc_serialbase qui ne doit décrire que les tables locales d’une part, et qu’on ne peut indéfiniment charger mes_fonctions.php3 avec des déclarations qui ne sont pas systématiquement utiles, Spip_ procède à présent à la lecture d’un fichier spécifique à chaque squelette : si le squellette s’appelle S, Spip lira le fichier S_fonctions.php3 avant chaque éxécution du squelette compilé (et juste avant sa compilation éventuelle).
On peut donc mettre dans ce fichier la description des tables comme ci-dessus, ainsi que les filtres spécifiques au squelette si l’on veut soulager mes_fonctions.php3 (qui reste lu au départ néanmoins). Dans le cas d’un squelette appelant systématiquement une base externe « mabase », on pourra également mettre les fonctions qu’il utilise dans le fichier ecrire/inc_connect-mabase.php qui est lu à la connexion.

[Erreur...13]Ce qui ne marche pas encore :

— -

- les balises formulaires, parce qu’elles appellent des fonctions annexes qu’il faut reprendre une à une : on ne peut donc faire apparaitre sous un site Spip le formulaire de la pétition déclarée sur un autre site ;
-  la seule requête gérée est SELECT, il n’est pas question d’alimenter le forum d’un site distant car cela nécessite un UPDATE ou un INSERT ; en contre-partie, il n’est pas nécessaire d’avoir le ALL PRIVILEGES sur la base lue, un accès en lecture suffit ;
-  l’interface permet a priori d’interroger d’autres serveurs que MySQL ; j’ai procédé à des essais avec Postgres, ça marche pour des boucles sans critères comme celles ci-dessus, mais le compilateur actuel traduit les critères par des idiosyncrasies MySQL qu’il faut retraduire au niveau de spip_postgres_select, il y a encore du travail.
-  le debugger de squelette aura peut-etre besoin d’etre debugé quant à sa gestion de ces nouveaux venus...

[Erreur...16]Bonne expérimentation à tous,

Déclarer une table d’une autre base MySQL

(Phil.Martin@inrialpes.fr)

-  J’ai sur le même serveur MySQL une autre base appelée « basilic ».

- Dans cette base, une table « authors » avec les champs id, first, last et url.

- Rajouter dans /mes_fonctions.php3 :

$basilic_authors = array (
                       "id" => "INTEGER NOT NULL",
                       "first" => "VARCHAR(30) NOT NULL",
                       "last" => "VARCHAR(30) NOT NULL",
                       "url" => "VARCHAR(100) NOT NULL",
                       );
$basilic_authors_key = array(
                          "PRIMARY KEY" => "id"
                          );


global $tables_des_serveurs_sql;
$tables_des_serveurs_sql['basilic']['bauthors'] = array('field' => &$basilic_authors,
                                       'key' => &$basilic_authors_key);
function boucle_BAUTHORS_dist($id_boucle, &$boucles) {
 $boucle = &$boucles[$id_boucle];
 $id_table = $boucle->id_table;
 $boucle->from[] =  "authors AS $id_table";
 return calculer_boucle($id_boucle, $boucles);
}

[Erreur...21][Erreur...22][Erreur...23]- Créer le fichier /ecrire/inc_connect-basilic.php3 :

&lt;?php
if (defined("_ECRIRE_INC_CONNECT_BASILIC")) return;
define("_ECRIRE_INC_CONNECT_BASILIC", "1");


@mysql_connect('mon_serveur','','mon_login','mon_mot_de_passe');
@mysql_select_db("basilic");


function spip_basilic_fetch($res, $serveur) {
 return spip_fetch_array ($res, $serveur);
}


function spip_basilic_count($res, $serveur) {
 return spip_num_rows ($res, $serveur);
}


function spip_basilic_free($res, $serveur) {
 return spip_free_result ($res, $serveur);
}


function spip_basilic_select($select, $from, $where, $groupby, $orderby, $limit, $sousrequete, $cpt, $table, $id, $serveur) {
 return spip_mysql_select ($select, $from, $where, $groupby, $orderby, $limit, $sousrequete, $cpt, $table, $id, $serveur);
}
?>


-  Une boucle :
<BOUCLE_auteur(basilic:BAUTHORS)>#ID #FIRST #LAST</BOUCLE_auteur>

[Erreur...28][Erreur...29]- Le fichier ##inc-compilo-api.php3## nécessite une modification (pour la version du 9 Mai 2005) :

--- $tables_des_serveurs_sql = array('localhost' => &$tables_principales);
+++ $tables_des_serveurs_sql['localhost'] = &$tables_principales;

[Erreur...31]

Déclarer une table d’une autre base MySQL SPIP 1.9

Il y a un bug dans la version stable de la 1.9 il faut appliquer le correctif disponible ici : http://trac.rezo.net/trac/spip/chan...

mes.fonctions.php dans le dossier squelettes :

global $tables_des_serveurs_sql;


&#91;Erreur...34]                                           
$mabase_matable = array (
                                                        "numero" => "INT(11) NOT NULL",
                                                        "prenom" => "CHAR(20)",
                                                        "nom" => "CHAR(20)"
                                                        );                                                       
$mabase_matable_key = array (
                                                        "PRIMARY KEY" => "numero"
                                                        );
$tables_des_serveurs_sql['mabase']['matable'] = array('field' => &$mabase_matable, 'key' => &$mabase_matable_key);

Créer inc_connect-mabase.php dans le dossier ecrire

<?php
if (defined("_ECRIRE_INC_CONNECT_mabase")) return;
define("_ECRIRE_INC_CONNECT_mabase", "1");


@mysql_connect('localhost','login','password');
@mysql_select_db("mabase");


function spip_mabase_fetch($res) {
 return spip_fetch_array($res);
}


function spip_mabase_count($res) {
 return spip_num_rows($res);
}


function spip_mabase_free($res) {
 return spip_free_result($res);
}


function spip_mabase_select($select, $from, $where,
                  $groupby, $orderby, $limit,
                  $sousrequete, $having,
                  $table, $id, $serveur) {
 return spip_mysql_select ($select, $from, $where,
                  $groupby, $orderby, $limit,
                  $sousrequete, $having,
                  $table, $id, $serveur);
}
?>

Example de boucles possibles après ça :

<BOUCLE_example(mabase:MATABLE){numero>50}
#NUMERO #PRENOM #NOM
</BOUCLE_example>

Multi serveur

Depuis la SVN7259, la connexion à plusieurs serveurs est clarifiée. On contrôle exactement comment on lance la requête. Il faut ajouter au fameux fichier ecrire/inc_connect-mabase.php les fonctions base_mabase et spip_query_mabase comme suit :

&lt;?php
  if (defined("_ECRIRE_INC_CONNECT_MABASE")) return;
define("_ECRIRE_INC_CONNECT_MABASE", "1");


global $spip_mabase_link, $spip_mabase_db;	// pour connexions multiples


$spip_mabase_link = @mysql_connect('serveur.sql.distant.fr', 'user_sql', 'mot_de_passe_sql');
$spip_mabase_db = "mabase";
@mysql_select_db($spip_mabase_db);


// Cf base_db_mysql_dist dans ecrire/base/db_mysql.php
// Le nom de la fonction qui requ^ete mabase, false si la connexion a echou'ee
function base_mabase()
{
  return $GLOBALS['spip_mabase_link']? 'spip_query_mabase' : false; 
}


&#91;Erreur...46]&#91;Erreur...47]// http://doc.spip.org/@spip_query_db
function spip_query_mabase($query) {


$query = traite_query($query);


$start = ($GLOBALS['mysql_profile'] AND (($GLOBALS['connect_statut'] == '0minirezo') OR ($GLOBALS['auteur_session']['statut'] == '0minirezo'))) ? microtime() : ;


return spip_mysql_trace($query, 
				$start,
		  mysql_query($query, $GLOBALS['spip_mabase_link']));
}


// http://doc.spip.org/@spip_abstract_select
function spip_mabase_select($select, $from, $where,
                  $groupby, $orderby, $limit,
                  $sousrequete, $having,
                  $table, $id, $serveur) {


$res = spip_mysql_select($select, $from, $where,
			   $groupby, $orderby, $limit,
			   $sousrequete, $having,
			  $table, $id, $serveur);


&#91;Erreur...53]	     return $res;


}


// http://doc.spip.org/@spip_abstract_fetch
function spip_mabase_fetch($res) {
  return spip_fetch_array($res);
}


// http://doc.spip.org/@spip_abstract_count
function spip_mabase_count($res) {
  return spip_num_rows($res);
}


&#91;Erreur...57]// http://doc.spip.org/@spip_abstract_free
function spip_mabase_free($res) {
  return spip_free_result($res);
}


// http://doc.spip.org/@spip_mysql_insert
function spip_mabase_insert($table, $champs, $valeurs) {
	return  spip_mysql_insert($table, $champs, $valeurs);
}


&#91;Erreur...59]// http://doc.spip.org/@spip_abstract_showtable
function spip_mabase_showtable($res) {
  return spip_mysql_showtable($res);
}


?>

Et encore un autre exemple ! version minimale

Fonctionne assurément avec spip >= 7867 soit SPIP 1.9.2 alpha 2
-  créez un répertoire privé du nom de votre choix à la racine dirdemonchoix
-  déclarez le dans config/mes_options.php comme squelettes d’un autre niveau que vos squelettes
$dossier_squelettes="publicsquelettes:dirdemonchoix";
-  dans ce dossier, mettez inc_connect-mabase.php avec ce qui est spécifié plus haut après > (Depuis la SVN7259 , la connexion à plusieurs serveurs est clarifiée. )
-  il est optionnel de créer dedans le fichier dirdemonchoix_mes_fontions.php en déclarant tables et array, sauf si vous souhaitez des jointures entre vos tables (à ce que j’ai compris) et si vous souhaitez que spip sauve le xml avec ses tables et leur contenu

[Erreur...62][Erreur...63]