My.remote : serveur d'objets php5

Description

D'aprés un excellent article parut chez php-france :
http://www.phpfrance.com/tutoriaux/index.php/2008/04/30/51-un-serveur-d-objets-en-php-5-2eme-partie
D'ailleur j'attends avec impatience l'article sur la répartition de charge.

Je me permets de reprendre la description faites chez php-france
http://www.phpfrance.com/tutoriaux/index.php/2008/04/21/49-serveur-objets-php5-1ere-partie

- Nous voulons soulager la charge de notre serveur Web en déléguant un traitement complexe à un autre serveur.
- Notre serveur Web ne dispose pas d'une application spécialisée et propriétaire, mais présente sur un autre serveur.
- Nous avons plusieurs serveurs Web désirant mettre en commun des données et des traitements.
- Nous voulons séparer la gestion de contenu et la gestion des données sur deux serveurs séparés.

En résumé nous voulons exploiter des ressources qui ne se trouvent pas toutes sur le serveur Web. C'est ce que l'on
appelle une architecture distribuée.

Source / Exemple :


<?php
/**

  • Class Remote : Un serveur d'objet en PHP5 (architecture distribuée).
* *
  • En résumé nous voulons exploiter des ressources qui ne se trouvent pas toutes sur le serveur Web. C'est ce que l'on
  • appelle une architecture distribuée.
*
  • Liste des methodes
*
  • __construct(); Constructeur vide
  • start(); Initialise les clients ou serveurs, utilise le design pattern singleton
  • sendQuery; Envois une requête à un serveur
  • setAnswer(); Prépare une réponse d'un serveur
  • get_include_contents(); Mets le résultat d'un script dans une varialbe
  • setPathToScript(); Construit le chemin d'accés au script distant
  • getAnswer(); Récupére le resultat d'un script
  • displayAnswer(); Affiche un résultat distant sur le client
  • save(); Sauvegarde l'etat d'une requête
  • load(); Charge le résultat d'une requête sauvegardée
* *
  • LICENSE: Vous êtes libres de reproduire, distribuer et communiquer cette création au public
  • et de modifier cette création.
  • Selon les conditions de paternité, pas d'utilisation commerciale, partage des cond
  • ions initiales à l'identique.
* /** // Class indispensable pour le fonctionnement du script, doit se trouver au même niveau que la class remote include_once 'inc.class.crypt.php'; class Remote { // Contient l'unique instance de la class private static $_instance = null; // Sauvegarde de la derniere requête executée public static $_query = null; // Sauvegarde de la clef de parité public static $_key = null; // Sauvegarde de la dernière config de serialisation (0 | 1) public static $_serialize = 1; // Sauvegarde de la dernière config de cryptage (0 | 1) public static $_crypt = 1; // Buffer de l'état de l'objet à un moment précis public static $_buffer = null; // Dernier script distant appelé public static $_script = null; // Liste de paramètres utilisateur public static $_param = null; // Gestion des erreurs // public static $_error = array(); /**
  • Constructeur vide
  • @return VOID
  • /
private function __construct() {} /**
  • Méthode qui crée l'unique instance de la classe si elle n'existe pas encore, puis la retourne.
  • @return RESOURCE
  • /
public static function start() { if( is_null( self::$_instance ) ) { self::$_instance = new Remote(); } return self::$_instance; } /**
  • Méthode côté client
  • Préparation du tableau $param à soumettre à sendQuery().
  • Voir la documentation : http://php.net/manual/fr/function.http-build-query.php
  • @arguments ARRAY $paramUser Liste de parametres utilisateur à transmettre
  • au serveur d'objet. Attention $paramUser doit
  • être un tableau associatif !
  • @return BOOL TRUE en cas de succés de la préparation de la requête
  • @throws EXCEPTION Si paramUser n'est pas un tableau
  • /
private static function setQuery( $paramUser ) { if( !is_array( $paramUser ) ) { throw new Exception('L\'argument <b>$param</b> n\'est pas un tableau.'); } else { $param = array(); $param['Key'] = Crypt::Crypte( self::$_key, KEY_CRYPT ) ; $param['Serialize'] = self::$_serialize; $param['Crypt'] = self::$_crypt; $param['Script'] = self::$_script; foreach( $paramUser as $key => $value ) { $param[$key] = $value ; } self::$_query = http_build_query( $param ); return 1; } } /**
  • Méthode côté client
  • Envois d'une requête vers notre serveur d'objet (serveur distant).
  • @arguments STRING $key Clef de parité commune au deux serveurs
  • @arguments STRING $url Url d'accès à notre serveur d'objet
  • @arguments CONST $methode Methode de notre requete sur le serveur.
  • POST : Pour une requete POST
  • GET : Pour une requete, comment dire... GET
  • @arguments BOOL $serialize La communication entre les deux serveurs doit elle être
  • linearisée (recommandée), par defaut 1
*
  • @arguments BOOL $crypt La communication entre les deux serveurs doit elle être
  • cryptée (recommandée), par defaut 1
*
  • @arguments ARRAY $param Tableau de paramètres utilisateur à transmettre à notre serveur
  • d'objet.
*
  • @arguments STRING $script Script à exécuté sur notre serveur distant
  • @return BOOL 1 si le serveur et joignable sinon 0
  • /
public static function sendQuery( $key, $url, $methode = POST, $serialize = 1, $crypt = 1, $param = array(), $script = '' ) { self::$_script = $script; self::$_key = $key; ( $serialize === 0 ) ? self::$_serialize = 0 : self::$_serialize = 1 ; ( $crypt === 0 ) ? self::$_crypt = 0 : self::$_crypt = 1 ; self::setQuery( $param ); switch ( $methode ) { case POST : $opts = array( 'http' => array( 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => self::$_query, ) ); self::$_param = serialize($param); $context = stream_context_create($opts); if( ( self::$_buffer = @file_get_contents( $url, false, $context ) ) === FALSE ) { self::$_error = 'Accés sur <strong><a href="'.$url.'" target="_blank">'. $url . '</a></strong> impossible'; throw new Exception('Accés sur <strong><a href="'.$url.'" target="_blank">'. $url . '</a></strong> impossible'); } if(self::$_buffer !== false) { return 1; } break; case GET : $final = $url . '?' . self::$_query ; // TEST si le serveur hote est disponible if( ( self::$_buffer = @file_get_contents( $final ) ) === FALSE ) { self::$_error = 'Accés sur <strong><a href="'.$final.'" target="_blank">'. $final . '</a></strong> impossible'; throw new Exception('Accés sur <strong><a href="'.$final.'" target="_blank">'. $final . '</a></strong> impossible'); } if(self::$_buffer !== false) { return 1; } else { return 0; } break; } } /**
  • Méthode côté serveur
  • Préparation de la réponse à envoyée, vérifie la clef de parité, et inclu la réponse
  • du script distant pour affichage.
  • @arguments VOID
  • @return BOOL 1 si le script est exécuté correctement
  • @throws EXCEPTION Si le script n'est pas disponible sur le serveur d'objet
  • /
private static function setAnswer() { static $getCrypt = null; static $getSerialize = null; static $getScript = null; if( !empty( $_POST ) ) { if( Crypt::DeCrypte( $_POST['Key'], KEY_CRYPT ) !== KEY_PARITY ) { throw new Exception('Client inconnu'); } self::$_crypt = $_POST['Crypt']; self::$_serialize = $_POST['Serialize'] ; self::$_script = $_POST['Script'] ; $getScript = self::setPathToScript( $_POST['Script'] ) ; } if( !empty( $_GET ) ) { $getMethode = GET; if( Crypt::DeCrypte( $_GET['Key'], KEY_CRYPT ) !== KEY_PARITY ) { throw new Exception('Client inconnu'); } self::$_crypt = $_GET['Crypt']; self::$_serialize = $_GET['Serialize'] ; self::$_script = $_GET['Script'] ; self::$_param = $_GET['Parametres']; $getScript = self::setPathToScript( $_GET['Script'] ) ; } if( !file_exists( $getScript ) ) { throw new Exception('Script inconnu'); } else { $answer = self::get_include_contents( $getScript ); self::$_buffer = $answer; return 1 ; } } /** *
  • @arguments STRING $filename Le script distant à executé
  • @return STRING $content La retour du script distant
  • BOOL false Si le script est injoignable
  • /
private static function get_include_contents( $filename ) { if ( is_file( $filename ) ) { ob_start(); include $filename; $contents = ob_get_contents(); ob_end_clean(); return $contents; } return false; } /**
  • Méthode côté serveur
  • Construction du chemin d'accés au script distant.
*
  • @arguments STRING $name Le nom du script
  • @return STRING $name Le chemin d'accés au script
  • /
private static function setPathToScript( $name ) { return $name = REMOTE_DIR_PATH . SCRIPT_PREFIX . $name . SCRIPT_SUFFIX ; } /**
  • Méthode côté serveur
  • Construction et affichage et mise en mémoire de la réponse du script distant
  • Linéarise et crypte éventuellement la réponse
*
  • @arguments VOID
  • @return STRING La chaine réponse du script distant
  • /
public static function getAnswer() { self::setAnswer(); $parametres = array(); if( self::$_serialize == 1 ) { self::$_buffer = serialize( self::$_buffer ); } if( self::$_crypt == 1 ) { self::$_buffer = Crypt::Crypte( self::$_buffer, KEY_CRYPT ) ; } print self::$_buffer; } /**
  • Méthode côté client
  • Affichage de la réponse du script distant
*
  • @arguments VOID
  • @return STRING La chaine réponse du script distant
  • /
public static function displayAnswer() { if( self::$_crypt == 1 ) { self::$_buffer = Crypt::DeCrypte( self::$_buffer, KEY_CRYPT ) ; } if( self::$_serialize == 1 ) { self::$_buffer = unserialize( self::$_buffer ); } echo self::$_buffer; } /**
  • Méthode côté client | serveur
  • Sauvegarde de la réponse à une requête dans un fichier texte.
*
  • @arguments STRING $name Le nom du fichier accueillant la sauvegarde
*
  • @arguments STRING $separator Le separateur entre chaque données.
*
  • @arguments STRING $extension L'extension du fichier de sauvegarde
  • @return BOOL 1 Si la sauvegarde s'est correctement déroulée
  • BOOL 0 Si impossible de sauvegardée
  • /
public static function save( $name, $separator = "\r\n", $extension = '.ini' ) { $dump = 'serialize = ' . self::$_serialize . $separator . 'crypt = ' . self::$_crypt . $separator . 'key = "' . self::$_key . '"' . $separator . 'script = "' . self::$_script . '"' . $separator . 'parametres = "' . self::$_param . '"' . $separator . 'query = "' . self::$_query . '"' . $separator . 'buffer = "' . self::$_buffer . '"' ; $inF = @fopen( REMOTE_SAVE_PATH . $name . $extension, "w" ); if( $inF == false ) { return 0; } fputs($inF,$dump); fclose($inF); return 1; } /**
  • Méthode côté client | serveur
  • Charge une sauvegarde, càd récupère l'état d'une requête et replace le tout
  • en mémoire.
*
  • @arguments STRING $name Le nom du fichier accueillant la sauvegarde
  • @return BOOL 1 Si le chargement du fichier s'est correctement déroulé
*
  • @throws EXCEPETION Si la sauvegarde est introuvable
  • /
public static function load( $name ) { $ini = @parse_ini_file( REMOTE_SAVE_PATH . $name . '.ini') ; if( !$ini == false ) { self::$_serialize = $ini['serialize']; self::$_crypt = $ini['crypt']; self::$_key = $ini['key']; self::$_script = $ini['script']; self::$_param = $ini['parametres']; self::$_query = $ini['query']; self::$_buffer = $ini['buffer']; return 1; } else { throw new exception('Sauvegarde introuvable'); } } /**
  • Méthode côté client | serveur
  • Affichage de l'état de l'objet remote à un moment précis de son execution
*
  • @arguments VOID
  • @return STRING $dump Etat complet de l'objet
  • /
public function __toString() { $buffer = chunk_split( self::$_buffer, 65, '<br /> '); $query = chunk_split( self::$_query, 64, '<br/> ' ); $dump = '<code><pre>' . '<strong title="1 => True | 0 => False"><u>Résultat sérialisés</u></strong> : ' . self::$_serialize . '<br /><br />' . '<strong title="1 => True | 0 => False"><u>Résultat cryptés</u></strong> : ' . self::$_crypt . '<br /><br />' . '<strong title="Clef de paritée, nécessaire pour autorisée la communication entre les serveurs"><u>Clef paritée</u></strong> : ' . self::$_key . '<br /><br />' . '<strong title="Script lancé sur le serveur distant"><u>Script</u></strong> : ' . REMOTE_DIR_PATH . SCRIPT_PREFIX . self::$_script . SCRIPT_SUFFIX . '<br /><br />' . '<strong title="Paramètres utilisateur à transmettre au script distant"><u>Paramètres</u></strong> : ' ; $param = unserialize(self::$_param); $spacer = ' '; $i = 0; $number = count($param); if( !empty($param) ) { foreach( $param as $key => $value ) { if($i == 0 ) { $dump .= '['. $key .'] => ' . $value . '<br />'; } else { $dump .= $spacer.'['. $key .'] => ' . $value ; } ++$i; } } $dump .= '<br /><br /><strong title="Requête construite utilisée avec la methode GET ou POST"><u>Requête</u></strong> : ' . $query . '<br />' . '<strong title="La réponse du script distant"><u>Buffer</u></strong> : ' . $buffer . '<br />' . '<strong title="Version du projet"><u>Version</u></strong> : ' . VERSION . '</pre>
';
return $dump;
}

}

?>
</code>

Conclusion :


Nécessite PHP5 pour fonctionner.
Attention sur certain serveurs pour des raisons de sécurité la fonction file_get_content() est désactivée

Code commenté, documentation fournie dans remote/documentation/readme.html

Codes Sources

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.