Nous allons dans cet article aborder une des notions les plus importante quand vous faites du Flex connecté à un service AMF, les ValueObjects
Terminologie
Les ValueObjects ne sont pas spécifiques à Flex dans le cadre des échanges AMF, en fait ils existent depuis qu’un client c’est mis à vouloir communiquer avec un serveur. Si vous en discutez avec un développeur C ou Java, il en parlera surement en terme de Data transfer object aka DTO, ou bien encore data access object aka DAO, mais généralement leurs petit nom chez les Flexeurs c’est VO.
A quoi sert un ValueObject ?
Pour ceux qui ne savent pas encore à quoi sert un ValueObject, c’est en fait assez simple. A échangé des données entre un client (flex) et un serveur (weborb, amfphp, blazeds, etc…) en concervant le type (composite), pour ceux qui ne sont pas familier du jargon, si vous envoyer une donnée typé ‘ObjetQuiDechire’ de Flex vers un serveur, le serveur recevra un ‘ObjetQuiDechire’ et saura vous envoyer le même type d’objet sans avoir à taper une seule ligne de code pour traiter les propriétés de cet ‘ObjetQuiDechire’.
Nous avons survolé ensemble dans la première partie de cette série de tutoriaux la façon dont Weborb PHP transmet les informations vers Flex. Nous avons vu les différents types de données supportés. Et l’envois de ces données ne pose généralement pas de problème majeur. Mais comme vous le savez, coté Flex, nos données sont manipulées sous forme de classe, cela garantit la stabilité de l’application et permet d’éviter au maximum l’utilisation de type mutagène (comme les Object) dont le nom des propriétés varies aux grès des fautes de frappe. Vous avez surement déjà perdu un temps précieux à essayez de comprendre pourquoi votre id (accidentellement tapé ld – avec un L) vous arrivé toujours à NULL…
Abordons maintenant un cas concret.
Mon premier VO
Value object Flex
Dans cette exemple, nous manipulerons un objet contact, voici le code côté Flex :
package vo
{
public class ContactVO
{
public var id:int;
public var nom:String;
public var prenom:String;
public var dateNaissance:Date;
public var actif:Boolean;
}
}
Value object PHP
Coté serveur, nous pouvons imaginer que les informations qui concernent les contacts seront stoquées dans une base de données, l’interrogation de la base suivie d’un fetchObject donnera une donnée de ce type :
// ServiceVO.php
class ServiceVO {
private $CONNECTION_BD;
function __construct(){
// Connection à la base de données
// Ici vous instanciez votre $CONNECTION_BD
// ou vous faites votre mysql_connect()
}
function getContactVO( $idContact ){
// Requète
$query = "SELECT id, nom, prenom, dateNaissance, actif "
."FROM contact "
."WHERE id= $idContact";
// Envois
// Retour
$donneesBD = array(
"id"=>1,
"nom"=>"Bouvry",
"prenom"=>"Stéphane",
"dateNaissance"=>"2009-07-04",
"actif"=>true
);
return $donneesBD;
}
}
Pour l’instant dans la console Weborb, ça devrait vous donner quelque chose dans ce goût là :

Notez que tous les types de données sont conservés à l’exception de la Date, nous verrons cela au moment du Mapping de notre VO, ça va se jouer côté serveur. Mais si vous êtes pressé, utilisez simplement la classe DateTime :
$donneesBD = array(
"id"=>1,
"nom"=>"Bouvry",
"prenom"=>"Stéphane",
"dateNaissance"=>new DateTime("2009-07-04"),
"actif"=>true
);
Attention, si vous êtes sur MAC et que vous utilisez MAMP, vous pouvez oublier la classe DateTime, l’erreur est particulièrement vicieuse car votre script bouzera en silence sans vous avertir des raisons, l’origine de l’erreur laisse une trace dans les logs de MAMP.
Côté flex, la récupération des données est toujours la même :
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
private function recupererContact() :void {
serviceVO.getContactVO(1);
}
private function onResult( result:ResultEvent ) :void {
trace(result.result);
}
private function onFault( fault:FaultEvent ) :void {
trace(fault);
}
]]>
</mx:Script>
<mx:RemoteObject id="serviceVO"
endpoint="http://localhost:8888/weborb.php"
destination="ServiceVO"
source="ServiceVO"
result="onResult(event)"
fault="onFault(event)"
/>
<mx:Button label="Appel méthode" click="recupererContact()" />
</mx:Application>
Si vous placez un point d’arret (breakpoint) dans la méthode onResult, vous devriez obtenir ça :

Le trace nous affiche un [object Object]…
Les plus malins vont se dire : « Y’a plus k’a caster » :
private function onResult( result:ResultEvent ) :void {
var typerContact:ContactVO = result.result as ContactVO;
trace(typerContact);
}
Mais c’est le drame, notre trace nous affiche un NULL sans appel, vous allez devoir mapper
Mappage de VO
La classe côté PHP
Rien à voir avec la patisserie, le mappage, également qualifié « Mapping » va se jouer côté serveur (et un chouilla côté Flex), l’objectif va être de créer une class PHP qui sera (pour le moment) la répique exacte de la classe ContactVO de Flex. Coté PHP, créez un fichier ContactVO.php (forcez vous à utiliser le nom de la classe, ça vous facilitera la vie par la suite) :
<?php
class ContactVO {
public $id;
public $nom;
public $prenom;
public $dateNaissance;
public $actif;
}
?>
Modification du service AMF
Dans notre service, nous allons envoyer un ContactVO, donc modifiez le service ainsi (pensez à importer le fichier du VO) :
<?php
// tutorial_vo/ServiceVO.php
require_once 'ContactVO.php';
class ServiceVO {
private $CONNECTION_BD;
function __construct(){
// Connection à la base de données
// Ici vous instanciez votre $CONNECTION_BD
// ou vous faites votre mysql_connect()
}
function getContactVO( $idContact ){
// Requète
$query = "SELECT id, nom, prenom, dateNaissance, actif "
."FROM contact "
."WHERE id= $idContact";
// Envois
// Retour
$donneesBD = array(
"id"=>1,
"nom"=>"Bouvry",
"prenom"=>"Stéphane",
"dateNaissance"=>new DateTime("2009-07-04"),
"actif"=>true
);
// Mapping
$contact = new ContactVO();
$contact->id = $donneesBD["id"];
$contact->nom = $donneesBD["nom"];
$contact->prenom = $donneesBD["prenom"];
$contact->dateNaissance = $donneesBD["dateNaissance"];
$contact->actif = $donneesBD["actif"];
return $contact;
}
}
?>
Utilisation de RemoteClass dans Flex
Si vous testez à nouveau, la casting ne fonctionne toujours pas, vous devez apporter une dernière modification, cette fois côté Flex. Ajoutez une Metadata RemoteClass à votre VO pour indiquer à la passerelle où se trouve le fichier du VO côté serveur (depuis la racine du dossier /Services) :
package vo
{
[RemoteClass(alias="tutorial_vo.ContactVO")]
public class ContactVO
{
public var id:int;
public var nom:String;
public var prenom:String;
public var dateNaissance:Date;
public var actif:Boolean;
}
}
En testant le casting côté Flex, vous devriez obtenir un beau ContactVO tout frais.

La magie du casting
Attention, dans le cadre de transmission de VO, un phénomène ésotérique singulier se produit. En effet, à l’arrivé dans Flex, nous avans casté le result pour obtenir un ContactVO. Si vous supprimez l’opération de casting. Le contenu de result devrait redevenir un simple Object. Vous aurez beau importer la classe ContactVO explicitement, ca ne changera rien, il faut au moins une instance de ContactVO pour que l’atterisage des données soit automatiquement typées… Jugez plutôt :
// Dans ce cas, le contenu du Result est Object
private function onResult( result:ResultEvent ) :void {
trace(result);
}
Ensuite même manipe mais en instanciant un ContactVO (peu importe l’endroit dans la vue)
// la ça marche
private function onResult( result:ResultEvent ) :void {
var c:ContactVO;
trace(result);
}
Là aussi…
// la ca marche aussi
private var c:ContactVO;
private function onResult( result:ResultEvent ) :void {
trace(result);
}
Et ça fonctionne où que soit votre import (même dans un autre composant dès lors que ce composant est raccordé au fichier principal), et je le rappel : Un simple import ne suffit pas. On peut facilement imaginer que le compilateur n’embarque pas la classe car il estime qu’elle n’est pas utilisée dans l’application, ce qui en soit n’est pas faux, quel interet auriez vous à caster une donnée que vous n’utilisez pas…
Voilà pour l’allez, penchons nous sur l’envois de données typé vers la passerelle Weborb PHP.
Envoyer des VO
Méthode du service PHP
Alors là, c’est du finger in the nooze
, on va ajouter une méthode receptionContactVO à notre service, avec en paramètre un objet typé implicitement de cette manière :
function receptionContactVO( ContactVO $contact ){
$retour = $contact->nom . " "
. $contact->prenom . " né le "
. " (id: " .$contact->id
." / actif: ".$contact->actif.")";
return $retour;
}
Méthode d'envoi Flex
Coté Flex, en appellant le service, passez directement un ContactVO
private function envoyerContact() :void {
var c:ContactVO = new ContactVO();
c.id = 10;
c.nom = "Barba";
c.prenom = "Papa";
c.dateNaissance = new Date();
c.actif = false;
serviceVO.receptionContactVO(c);
}
Traiter les type Date lors de l'échange
Pour la date, vous allez devoir procéder à un traitement préalable. En effet, quand une date en provenance de Flex arrive côté PHP, la passerelle Weborb la transforme en ORBDateTime, (pathWeborb/Weborb/Utils/OrbDateTime.php) .Cette classe fournis par weborb permet justement de traiter les dates. Dans notre exemple, nous destinons la date à une base de donnée où les informations seront enregistrées sous la forme « Y-m-d H:i:s », la classe ORBDateTime fournis pour cela une méthode retournant la date en millisecondes (getTotalMs), cette information va nous permettre via la fonction date d’obtenir une date correctement formatée.
Modifier notre méthode de cette façon :
function receptionContactVO( ContactVO $contact ){
$retour = $contact->nom . " "
. $contact->prenom . " né le "
. date("Y-m-d H:i:s", round($contact->dateNaissance->getTotalMs()/1000))
. " (id: " .$contact->id
." / actif: ".$contact->actif.")";
return $retour;
}
Vous pourrez observer que notre Date est correctement formatée
Vous avez maintenant en main les outils nécessaires pour créer des services AMF avec la passerelle Weborb PHP, j’aborderais sous peu une exemple concret pour syntétiser les 2 tutoriaux, vous y trouverez tous les cas abordées ici dans un contexte pratique avec surtout : Amélioration des ValuesObject avec les Intefaces PHP, Héritage de service, Gestion des Données via PDO.
Infos
Nous allons dans cet article aborder une des notions les plus importante quand vous faites du Flex connecté à un service AMF, les ValueObjects
- Niveau : initié
- Catégorie : Flex 3
- Publié le : 01 octobre 2009
- Dernière Mise à jour : 28 juillet 2011
- Notions abordées :