Interaction entre Odoo et PHP via XML-RPC

Les Web Services avec Odoo (OpenERP)

Thierry Godin

Ceci est une petite présentation de l'utilisation des Web Services pour permettre à PHP de lire et écrire dans la base de données de Odoo, mais aussi de déclencher n'importe quelle fonction d'un module.

Commentez

- Titre : Interaction entre Odoo et PHP via XML-RPC

- Auteur : Thierry Godin

- Parution : 30 juillet 2014

- Mise à jour : 13 février 2020

- Public visé :

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2014 Thierry Godin. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Présentation de XML-RPC

- II. Prérequis

- III. Installation

- IV. Rappel

- V. Connexion à Odoo

- VI. xmlprcval()

- VII. Exécution de la méthode create()

- VIII. Le script create() complet

- IX. Les méthodes search() et read()

- X. Explication du résultat

- XI. Le script search() et read() complet

- XII. Les méthodes search() et unlink()

- XIII. Le script search() and unlink() complet :

- XIV. La méthode write()

- XV. Et après ???

- XVI. Téléchargement

- XVII. Documentation

- XVIII. Remerciements

I - Présentation de XML-RPC

English version of the tutorial here :
Odoo Tutorial: Interaction between Odoo and PHP via XML-RPC

Pour faire simple, le Web Service XML-RPC est un ensemble d'outils et de spécifications qui permettent aux logiciels fonctionnant sur différents systèmes d'exploitation, en cours d'exécution dans des environnements différents, de faire des appels de procédure sur Internet.

C'est l'appel de procédure à distance via le protocole HTTP comme transport et XML comme encodage. XML-RPC est conçu pour être aussi simple que possible, tout en permettant à des structures de données complexes d'être transmises, traitées et renvoyées.

II - Prérequis

Pour pouvoir utiliser le protocole XML-RPC avec PHP, vous aurez besoin de la bibliothèque PHPXML-RPC.

Le site officiel :XML-RPC for PHP

Pour se plonger dans ce tutoriel, il faut une bonne connaissance des langages de programmation suivants :

- PHP ;

- Python ;

- XML.

Et il faut assurément être bien familiarisé avec l'ORM d'OpenERP.

III - Installation

Téléchargez la bibliothèque, puis décompressez l'archive.

Copiez les fichiers qui se trouvent dans le répertoire « lib » sur votre serveur.

Astuce

Pour plus de clarté et pour faciliter la maintenance, je vous recommande de créer un répertoire « xmlrpc_lib » (par exemple) sur votre serveur et d'y placer les fichiers.

IV - Rappel

Nous allons agir sur Odoo depuis un site Web en utilisant le langage de programmation PHP. Pour le tutoriel, j’ai installé OpenERP 7 (7.0-20140627-231127) avec les données de démo sur un serveur Debian 7 (Wheezy). J'ai créé un hôte virtuel Apache sur un serveur Suse Linux 10, déjà configuré pour le Web (PHP, MySQL, etc.).

Donc, Odoo est sur le serveur Debian, et les scripts PHP seront exécutés sur le serveur Suse. Ces tests sont réalisés sur mon réseau local, donc, il faudra bien sûr modifier les URL dans les scripts.

Également, je vous montre les différentes connexions HTTP/HTTPS, mais les tests sont réalisés en local en HTTP.

V - Connexion à Odoo

Pour exécuter des fonctions dans Odoo, il est nécessaire en premier lieu, de se connecter, puis d'appeler ensuite une fonction d'un module.

Pour établir la connexion, nous allons créer un client XML-RPC :

Création du client XMLRPC

$server_url = 'https://www.mon-serveur-openerp.com:8069'; //connexion sécurisée
$sock = new xmlrpc_client($server_url . "/xmlrpc/common");
$sock->setSSLVerifyPeer(0);

Astuce

Si vous utilisez une connexion sécurisée, vous pouvez outrepasser la vérification du certificat SSL avec setSSLVerifyPeer(0);

La connexion peut échouer dans le cas d'un certificat autosigné, par exemple.

Nous allons ensuite envoyer une commande XML-RPC, c'est à dire : nous appelons une fonction Python de Odoo. Ici, nous appelons la fonction « login »

Pour passer des paramètres à cette fonction, nous utiliserons la fonction addParam() en créant un objet xmlrpcval() (valeur au format XML-RPC) :

Connexion à Odoo

$user = 'admin';
$password = 'mY5up3rPwd';
$dbname = 'test';

$server_url = 'https://www.monsite.com:8069'; //connexion sécurisée
$connexion = new xmlrpc_client($server_url . "/xmlrpc/common");
$connexion->setSSLVerifyPeer(0);

$c_msg = new xmlrpcmsg('login');
$c_msg->addParam(new xmlrpcval($dbname, "string"));
$c_msg->addParam(new xmlrpcval($user, "string"));
$c_msg->addParam(new xmlrpcval($password, "string"));
$c_response = $connexion->send($c_msg);

Info

Nous utilisons l'URL /xmlrpc/common pour les méthodes suivantes :

'login', 'about', 'timezone_get', 'get_server_environment', 'login_message','get_stats', 'check_connectivity', 'list_http_services', 'version', 'authenticate'

Il suffit ensuite de récupérer la réponse pour vérifier si la connexion a bien été établie.

En cas d'erreur on affiche un message

if ($c_response->errno != 0){
echo  '<p>error : ' . $c_response->faultString() . '</p>';
}
else{
//… on continue le script
}

Ici, si errno!= 0, il y a donc un message d'erreur et la connexion a été refusée. Sinon, on a bien établi la connexion, on pourra alors récupérer l'UID de l'utilisateur. C'est cet UID qui sera ensuite envoyé à chaque requête XML-RPC.

Si vous vous rappelez bien, la majeure partie des fonctions Python de Odoo nécessitent l'ID de l'utilisateur :

def function(self, cr, uid, …)

Récupérer l'uid de l'utilisateur

$uid = $c_response->value()->scalarval();

VI - xmlprcval()

On l'a vu, pour passer des paramètres aux fonctions nous formatons les données avec l'objet xmlrpcval(valeur, type).

Les différents types acceptés sont : string, i4, int, double, boolean, dateTime.iso8601, base64, null, array et struct.

struct permet de passer des noms de champs et leur valeur au format xmlprcval().

Dans l'exemple ci-dessous, on va créer un client (partner) :

$val = array (
"name"    => new xmlrpcval("Godin", "string"),
"city" => new xmlrpcval("Marne la Vallée", "string"),
"zip" => new xmlrpcval("77000", "string"),
"website" => new xmlrpcval("http://www.lapinmoutardepommedauphine.com", "string"),
"lang"   => new xmlrpcval("fr_FR", "string"),
"tz"   => new xmlrpcval("Europe/Paris", "string"),
);

VII - Exécution de la méthode create()

Nous allons maintenant établir une autre connexion pour appeler directement la méthode execute() sur l'objet res.partner.

Info

Nous utilisons l'URL /xmlrpc/object pour les méthodes suivantes :

'execute', 'execute_kw', 'exec_workflow'.

$client = new xmlrpc_client($server_url . "/xmlrpc/object");
$client->setSSLVerifyPeer(0);

$msg = new xmlrpcmsg('execute');
$msg->addParam(new xmlrpcval($dbname, "string"));
$msg->addParam(new xmlrpcval($uid, "int"));
$msg->addParam(new xmlrpcval($password, "string"));
$msg->addParam(new xmlrpcval("res.partner", "string"));
$msg->addParam(new xmlrpcval("create", "string"));
$msg->addParam(new xmlrpcval($val, "struct"));
$response = $client->send($msg);

Il suffit d'afficher ensuite la réponse avec :

Réponse

echo 'Partner created - partner_id = ' . $response->value()->scalarval();

Pour rappel, la méthode create() renvoie l'ID de l'enregistrement créé.

VIII - Le script create() complet

xml-rpc-create.php

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php
echo '<h2>XML-RPC AVEC OPENERP/ODOO ET PHP</h2>';

include("xmlrpc_lib/xmlrpc.inc.php");
include("xmlrpc_lib/xmlrpcs.inc.php");
$GLOBALS['xmlrpc_internalencoding']='UTF-8';

$user = 'admin';
$password = 'mY5up3rPwd';
$dbname = 'test';

$server_url = 'http://192.168.1.120:8069';
$connexion = new xmlrpc_client($server_url . "/xmlrpc/common");
$connexion->setSSLVerifyPeer(0);

$c_msg = new xmlrpcmsg('login');
$c_msg->addParam(new xmlrpcval($dbname, "string"));
$c_msg->addParam(new xmlrpcval($user, "string"));
$c_msg->addParam(new xmlrpcval($password, "string"));
$c_response = $connexion->send($c_msg);

if ($c_response->errno != 0){
echo  '<p>error : ' . $c_response->faultString() . '</p>';
}
else{

$uid = $c_response->value()->scalarval();

$val = array (
"name"    => new xmlrpcval("Godin Thierry", "string"),
"street"  => new xmlrpcval("Au fond à gauche", "string"),
"city"    => new xmlrpcval("Marne la Vallée", "string"),
"zip"     => new xmlrpcval("77000", "string"),
"website" => new xmlrpcval("http://www.lapinmoutardepommedauphine.com", "string"),
"lang"    => new xmlrpcval("fr_FR", "string"),
"tz"      => new xmlrpcval("Europe/Paris", "string"),
);

$client = new xmlrpc_client($server_url . "/xmlrpc/object");
$client->setSSLVerifyPeer(0);

$msg = new xmlrpcmsg('execute');
$msg->addParam(new xmlrpcval($dbname, "string"));
$msg->addParam(new xmlrpcval($uid, "int"));
$msg->addParam(new xmlrpcval($password, "string"));
$msg->addParam(new xmlrpcval("res.partner", "string"));
$msg->addParam(new xmlrpcval("create", "string"));
$msg->addParam(new xmlrpcval($val, "struct"));
$response = $client->send($msg);

echo 'Partner created - partner_id = ' . $response->value()->scalarval();
}
?>

IX - Les méthodes search() et read()

Nous avons vu comment créer un enregistrement par le biais de la méthode create(), nous allons maintenant voir les méthodes search() et read().

Nous utilisons la méthode search() en utilisant un filtre de domaine pour récupérer la liste des ID des enregistrements que nous voulons lire avec la méthode read().

En effet, rappelez-vous, la méthode read() nécessite plusieurs arguments, dont l'ID de l'enregistrement à lire.

Filtre de domaine

$domain_filter = array (
new xmlrpcval(
array(new xmlrpcval('is_company' , "string"),
new xmlrpcval('!=',"string"),
new xmlrpcval('True',"string")
),"array"
),
);

Comme on le voit dans le code ci-dessus, on recherche tous les clients qui ne sont pas des sociétés.

Ce filtre se traduirait en Python dans Odoo à :

domain

[('is_company', '!=', True)]

On établit donc une nouvelle connexion puis on exécute la méthode search() comme ci-dessous :

$client = new xmlrpc_client($server_url . "/xmlrpc/object");
$client->setSSLVerifyPeer(0);

$msg = new xmlrpcmsg('execute');
$msg->addParam(new xmlrpcval($dbname, "string"));
$msg->addParam(new xmlrpcval($uid, "int"));
$msg->addParam(new xmlrpcval($password, "string"));
$msg->addParam(new xmlrpcval("res.partner", "string"));
$msg->addParam(new xmlrpcval("search", "string"));
$msg->addParam(new xmlrpcval($domain_filter, "array"));
$response = $client->send($msg);

$result = $response->value();
$ids = $result->scalarval();

Ensuite, nous formatons les ID pour les passer à la méthode read() comme ci-dessous :

Formater les ID

$id_list = array();

for($i = 0; $i < count($ids); $i++){
$id_list[]= new xmlrpcval($ids[$i]->me['int'], 'int');
}

Puis, on crée la liste des champs que l'on veut lire :

Liste des champs

$field_list = array(
new xmlrpcval("name", "string"),
new xmlrpcval("email", "string"),
new xmlrpcval("street", "string"),
new xmlrpcval("city", "string"),
new xmlrpcval("zip", "string"),
);

Puis, on exécute la méthode read() :

Exécution de la méthode read()

$msg = new xmlrpcmsg('execute');
$msg->addParam(new xmlrpcval($dbname, "string"));
$msg->addParam(new xmlrpcval($uid, "int"));
$msg->addParam(new xmlrpcval($password, "string"));
$msg->addParam(new xmlrpcval("res.partner", "string"));
$msg->addParam(new xmlrpcval("read", "string"));
$msg->addParam(new xmlrpcval($id_list, "array"));
$msg->addParam(new xmlrpcval($field_list, "array"));

$resp = $client->send($msg);

if ($resp->faultCode()){
echo $resp->faultString();
}

$result = $resp->value()->scalarval();

Et enfin, on affiche les clients :

Affichage du résultat

for($i = 0; $i < count($result); $i++){
echo '<h1>' . $result[$i]->me['struct']['name']->me['string'] . '</h1>'
. '<ol>'
. '<li><strong>Email</strong> : ' . $result[$i]->me['struct']['email']->me['string'] . '</li>'
. '<li><strong>Street</strong> : ' . $result[$i]->me['struct']['street']->me['string'] . '</li>'
. '<li><strong>City</strong> : ' . $result[$i]->me['struct']['city']->me['string'] . '</li>'
. '<li><strong>Zip code</strong> : ' . $result[$i]->me['struct']['zip']->me['string'] . '</li>'
. '</ol>'
. '<hr />';
}

X - Explication du résultat

Si on fait un print_r($result)  on obtient ceci :

print_r($result)

Array ( [0] => xmlrpcval Object ( [me] => Array ( [struct] => Array ( [city] => xmlrpcval Object ( [me] => Array ( [boolean] => ) [mytype] => 1 [_php_class] => ) [name] => xmlrpcval Object ( [me] => Array ( [string] => Administrator ) [mytype] => 1 [_php_class] => ) [zip] => xmlrpcval Object ( [me] => Array ( [boolean] => ) [mytype] => 1 [_php_class] => ) [email] => xmlrpcval Object ( [me] => Array ( [string] => admin@example.com ) [mytype] => 1 [_php_class] => ) [street] => xmlrpcval Object ( [me] => Array ( [boolean] => ) [mytype] => 1 [_php_class] => ) [id] => xmlrpcval Object ( [me] => Array ( [int] => 3 ) [mytype] => 1 [_php_class] => ) ) ) [mytype] => 3 [_php_class] => ) [1] => xmlrpcval Object ( [me] => Array ( [struct] => Array ( [city] => xmlrpcval Object ( [me] => Array ( [string] => Wavre ) [mytype] => 1 [_php_class] => ) [name] => xmlrpcval Object ( [me] => Array ( [string] => Michel Fletcher ) [mytype] => 1 [_php_class] => ) [zip] => xmlrpcval Object ( [me] => Array ( [string] => 1300 ) [mytype] => 1 [_php_class] => ) [email] => xmlrpcval Object ( [me] => Array ( [string] => m.fletcher@agrolait.com ) [mytype] => 1 [_php_class] => ) [street] => xmlrpcval Object ( [me] => Array ( [string] => 69 rue de Namur ) [mytype] => 1 [_php_class] => ) [id] => xmlrpcval Object ( [me] => Array ( [int] => 31 ) [mytype] => 1 [_php_class] => ) ) ) [mytype] => 3 [_php_class] => ) [2] => xmlrpcval Object ( [me] => Array ( [struct] => Array ( [city] => xmlrpcval Object ( [me] => Array ( [string] => Wavre ) [mytype] => 1 [_php_class] => ) [name] => xmlrpcval Object ( [me] => Array ( [string] => Thomas Passot ) [mytype] => 1 [_php_class] => ) [zip] => xmlrpcval Object ( [me] => Array ( [string] => 1300 ) [mytype] => 1 [_php_class] => ) [email] => xmlrpcval Object ( [me] => Array ( [string] => p.thomas@agrolait.com ) [mytype] => 1 [_php_class] => ) [street] => xmlrpcval Object ( [me] => Array ( [string] => 69 rue de Namur ) [mytype] => 1 [_php_class] => ) [id] => xmlrpcval Object ( [me] => Array ( [int] => 30 ) [mytype] => 1 [_php_class] => ) ) ) [mytype] => 3 [_php_class] => ) [3] => xmlrpcval Object ( [me] => Array ( [struct] => Array ( [city] => xmlrpcval Object ( [me] => Array ( [string] => Taipei ) [mytype] => 1 [_php_class] => ) [name] => xmlrpcval Object ( [me] => Array ( [string] => Joseph Walters ) [mytype] => 1 [_php_class] => ) [zip] => xmlrpcval Object ( [me] => Array ( [string] => 106 ) [mytype] => 1 [_php_class] => ) [email] => xmlrpcval Object ( [me] => Array ( [string] => joseph.walters@asustek.com ) [mytype] => 1 [_php_class] => ) [street] => xmlrpcval Object ( [me] => Array ( [string] => 31 Hong Kong street ) [mytype] => 1 [_php_class] => ) [id] => xmlrpcval Object ( [me] => Array ( [int] => 29 ) [mytype] => 1 [_php_class] => ) ) ) [mytype] => 3 [_php_class] => ) [4] => xmlrpcval Object ( [me] => Array  …....

$result est donc un tableau d'objets xmlrpcval().

Si on veut par exemple récupérer la valeur du champ name du premier enregistrement retourné, il faudra écrire ceci :

// Array ( [0] => xmlrpcval Object ( [me] => Array ( [struct] => Array
// ( [city] => xmlrpcval Object ( [me] => Array ( [boolean] => )
// [mytype] => 1 [_php_class] => ) [name] => xmlrpcval Object (
// [me] => Array ( [string] => Administrator )

echo $result[0]->me['struct']['name']->me['string'] // = Administrator

XI - Le script search() et read() complet

xml_rpc_search_and_read.php

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php

echo '<h2>XML-RPC AVEC OPENERP/ODOO ET PHP</h2>';

include("xmlrpc_lib/xmlrpc.inc.php");
include("xmlrpc_lib/xmlrpcs.inc.php");
$GLOBALS['xmlrpc_internalencoding']='UTF-8';

$user = 'admin';
$password = 'mY5up3rPwd';
$dbname = 'test';

$server_url = 'http://192.168.1.120:8069';
$connexion = new xmlrpc_client($server_url . "/xmlrpc/common");
$connexion->setSSLVerifyPeer(0);

$c_msg = new xmlrpcmsg('login');
$c_msg->addParam(new xmlrpcval($dbname, "string"));
$c_msg->addParam(new xmlrpcval($user, "string"));
$c_msg->addParam(new xmlrpcval($password, "string"));
$c_response = $connexion->send($c_msg);

if ($c_response->errno != 0){
echo  '<p>error : ' . $c_response->faultString() . '</p>';
}
else{

$uid = $c_response->value()->scalarval();

$domain_filter = array (
new xmlrpcval(
array(new xmlrpcval('is_company' , "string"),
new xmlrpcval('!=',"string"),
new xmlrpcval('True',"string")
),"array"
),
);

$client = new xmlrpc_client($server_url . "/xmlrpc/object");
$client->setSSLVerifyPeer(0);

$msg = new xmlrpcmsg('execute');
$msg->addParam(new xmlrpcval($dbname, "string"));
$msg->addParam(new xmlrpcval($uid, "int"));
$msg->addParam(new xmlrpcval($password, "string"));
$msg->addParam(new xmlrpcval("res.partner", "string"));
$msg->addParam(new xmlrpcval("search", "string"));
$msg->addParam(new xmlrpcval($domain_filter, "array"));
$response = $client->send($msg);

$result = $response->value();
$ids = $result->scalarval();

$id_list = array();

for($i = 0; $i < count($ids); $i++){
$id_list[]= new xmlrpcval($ids[$i]->me['int'], 'int');
}

$field_list = array(
new xmlrpcval("name", "string"),
new xmlrpcval("email", "string"),
new xmlrpcval("street", "string"),
new xmlrpcval("city", "string"),
new xmlrpcval("zip", "string"),
);

$msg = new xmlrpcmsg('execute');
$msg->addParam(new xmlrpcval($dbname, "string"));
$msg->addParam(new xmlrpcval($uid, "int"));
$msg->addParam(new xmlrpcval($password, "string"));
$msg->addParam(new xmlrpcval("res.partner", "string"));
$msg->addParam(new xmlrpcval("read", "string"));
$msg->addParam(new xmlrpcval($id_list, "array"));
$msg->addParam(new xmlrpcval($field_list, "array"));

$resp = $client->send($msg);

if ($resp->faultCode()){
echo $resp->faultString();
}

$result = $resp->value()->scalarval();

echo '<h2>Resultat brut de la requête avec print_r($result) :</h2>';
print_r($result);
echo '<hr />';
echo '<h2>Liste des partners qui ne sont pas des sociétés:</h2>';

for($i = 0; $i < count($result); $i++){
echo '<h1>' . $result[$i]->me['struct']['name']->me['string'] . '</h1>'
. '<ol>'
. '<li><strong>Email</strong> : ' . $result[$i]->me['struct']['email']->me['string'] . '</li>'
. '<li><strong>Street</strong> : ' . $result[$i]->me['struct']['street']->me['string'] . '</li>'
. '<li><strong>City</strong> : ' . $result[$i]->me['struct']['city']->me['string'] . '</li>'
. '<li><strong>Zip code</strong> : ' . $result[$i]->me['struct']['zip']->me['string'] . '</li>'
. '</ol>'
. '<hr />';
}

}
?>

XII - Les méthodes search() et unlink()

De la même façon que précédemment, nous allons maintenant utiliser la méthode search() pour rechercher tous les clients dont le nom comporte le terme « godin » (ce sont les clients que nous avons créés au début de ce tutoriel) puis nous allons tous les supprimer avec la méthode unlink().

On va donc reformuler le filtre de domaine comme ceci :

Filtre de domaine

$domain_filter = array (
new xmlrpcval(
array(new xmlrpcval('name' , "string"),
new xmlrpcval('ilike',"string"),
new xmlrpcval('godin',"string")
),"array"
),
);

Puis, on exécute la méthode search() :

Exécuter la méthode search()

$msg = new xmlrpcmsg('execute');
$msg->addParam(new xmlrpcval($dbname, "string"));
$msg->addParam(new xmlrpcval($uid, "int"));
$msg->addParam(new xmlrpcval($password, "string"));
$msg->addParam(new xmlrpcval("res.partner", "string"));
$msg->addParam(new xmlrpcval("search", "string"));
$msg->addParam(new xmlrpcval($domain_filter, "array"));
$response = $client->send($msg);

$result = $response->value();
$ids = $result->scalarval();

Et finalement, on reformate la liste des ID et on exécute la méthode unlink() pour supprimer tous les clients dont le nom contient « godin » :

Exécution de la méthode unlink()

$id_list = array();

for($i = 0; $i < count($ids); $i++){
$id_list[]= new xmlrpcval($ids[$i]->me['int'], 'int');
}

$msg = new xmlrpcmsg('execute');
$msg->addParam(new xmlrpcval($dbname, "string"));
$msg->addParam(new xmlrpcval($uid, "int"));
$msg->addParam(new xmlrpcval($password, "string"));
$msg->addParam(new xmlrpcval("res.partner", "string"));
$msg->addParam(new xmlrpcval("unlink", "string"));
$msg->addParam(new xmlrpcval($id_list, "array"));

$resp = $client->send($msg);

if ($resp->faultCode()){
echo $resp->faultString();
}

XIII - Le script search() and unlink() complet :

xml_rpc_search_and_unlink.php

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php

echo '<h2>XML-RPC AVEC OPENERP/ODOO ET PHP</h2>';

include("xmlrpc_lib/xmlrpc.inc.php");
include("xmlrpc_lib/xmlrpcs.inc.php");
$GLOBALS['xmlrpc_internalencoding']='UTF-8';

$user = 'admin';
$password = 'mY5up3rPwd';
$dbname = 'test';

$server_url = 'http://192.168.1.120:8069';
$connexion = new xmlrpc_client($server_url . "/xmlrpc/common");
$connexion->setSSLVerifyPeer(0);

$c_msg = new xmlrpcmsg('login');
$c_msg->addParam(new xmlrpcval($dbname, "string"));
$c_msg->addParam(new xmlrpcval($user, "string"));
$c_msg->addParam(new xmlrpcval($password, "string"));
$c_response = $connexion->send($c_msg);

if ($c_response->errno != 0){
echo  '<p>error : ' . $c_response->faultString() . '</p>';
}
else{

$uid = $c_response->value()->scalarval();

$domain_filter = array (
new xmlrpcval(
array(new xmlrpcval('name' , "string"),
new xmlrpcval('ilike',"string"),
new xmlrpcval('godin',"string")
),"array"
),
);

$client = new xmlrpc_client($server_url . "/xmlrpc/object");
$client->setSSLVerifyPeer(0);

$msg = new xmlrpcmsg('execute');
$msg->addParam(new xmlrpcval($dbname, "string"));
$msg->addParam(new xmlrpcval($uid, "int"));
$msg->addParam(new xmlrpcval($password, "string"));
$msg->addParam(new xmlrpcval("res.partner", "string"));
$msg->addParam(new xmlrpcval("search", "string"));
$msg->addParam(new xmlrpcval($domain_filter, "array"));
$response = $client->send($msg);

$result = $response->value();
$ids = $result->scalarval();

$id_list = array();

for($i = 0; $i < count($ids); $i++){
$id_list[]= new xmlrpcval($ids[$i]->me['int'], 'int');
}

$msg = new xmlrpcmsg('execute');
$msg->addParam(new xmlrpcval($dbname, "string"));
$msg->addParam(new xmlrpcval($uid, "int"));
$msg->addParam(new xmlrpcval($password, "string"));
$msg->addParam(new xmlrpcval("res.partner", "string"));
$msg->addParam(new xmlrpcval("unlink", "string"));
$msg->addParam(new xmlrpcval($id_list, "array"));

$resp = $client->send($msg);

if ($resp->faultCode()){
echo $resp->faultString();
}

echo '<h2>Liste des id des partners qui ont été supprimés:</h2>';

for($i = 0; $i < count($id_list); $i++){
echo '<li><strong>ID</strong> : ' . $id_list[$i]->me['int'] . '</li>';
}

}
?>

Évidemment, on n'est pas obligé d'utiliser la méthode search() si on connaît les ID des enregistrements à lire/modifier/supprimer.

XIV - La méthode write()

Voici maintenant la méthode write().

Dans l'exemple ci-dessous, je n'utilise pas la méthode search(), on part du principe que je connais l'ID de l'enregistrement que je veux modifier.

xml_rpc_write.php

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php

echo '<h2>XML-RPC AVEC OPENERP/ODOO ET PHP</h2>';

include("xmlrpc_lib/xmlrpc.inc.php");
include("xmlrpc_lib/xmlrpcs.inc.php");
$GLOBALS['xmlrpc_internalencoding']='UTF-8';

$user = 'admin';
$password = 'mY5up3rPwd';
$dbname = 'test';

$server_url = 'http://192.168.1.120:8069';
$connexion = new xmlrpc_client($server_url . "/xmlrpc/common");
$connexion->setSSLVerifyPeer(0);

$c_msg = new xmlrpcmsg('login');
$c_msg->addParam(new xmlrpcval($dbname, "string"));
$c_msg->addParam(new xmlrpcval($user, "string"));
$c_msg->addParam(new xmlrpcval($password, "string"));
$c_response = $connexion->send($c_msg);

if ($c_response->errno != 0){
echo  '<p>error : ' . $c_response->faultString() . '</p>';
}
else{

$uid = $c_response->value()->scalarval();

$id_list = array();
$id_list[]= new xmlrpcval(89, 'int');

$values = array (
'street'=>new xmlrpcval('Rue de la gare' , "string"),
'city'=>new xmlrpcval('Fontainebleau',"string"),
'zip'=>new xmlrpcval('77120',"string")
);

$client = new xmlrpc_client($server_url . "/xmlrpc/object");
$client->setSSLVerifyPeer(0);

$msg = new xmlrpcmsg('execute');
$msg->addParam(new xmlrpcval($dbname, "string"));
$msg->addParam(new xmlrpcval($uid, "int"));
$msg->addParam(new xmlrpcval($password, "string"));
$msg->addParam(new xmlrpcval("res.partner", "string"));
$msg->addParam(new xmlrpcval("write", "string"));
$msg->addParam(new xmlrpcval($id_list, "array"));
$msg->addParam(new xmlrpcval($values, "struct"));
$response = $client->send($msg);

if ($response->faultCode()){
echo $response->faultString();
}

echo '<h2>Mise à jour effectuée</h2>';

}
?>

XV - Et après ???

Eh bien après, il ne vous reste plus qu'à appeler n'importe quelle méthode de n'importe quel module en faisant attention à passer les paramètres attendus.

Lorsque vous appelez une méthode via XML-RPC , celles-ci sont exécutées dans les mêmes conditions que lorsqu'elles sont appelées depuis l'interface d'Odoo. Ainsi une méthode peut échouer si l'utilisateur n'a pas les droits suffisants.

Ici, pour le tutoriel, j'ai utilisé l'utilisateur « admin », mais, pour des raisons de sécurité, je vous recommande de créer un utilisateur spécifique auquel vous aurez attribué seulement les droits suffisants pour exécuter les méthodes dont vous avez besoin et rien d'autre.

XVI - Téléchargement

Téléchargez les scripts ci-dessus : odoo_xmlrpc_php_files.zip

XVII - Documentation

Vous trouverez de la documentation sur le site officiel.

Odoo: XML-RPC Web services

Cette documentation semble avoir été écrite pour OpenERP 6.2, mais elle fonctionne avec la version 7. Je n'ai pas encore testé avec la version 8 d'Odoo.

XVIII - Remerciements

Remerciements à OpenERP SA pour leur logiciel Odoo.

Remerciements à Philippe Duval pour ses conseils et corrections.