Imaginons que nous souhaitions récupérer une liste de données pour les afficher dans un datagrid.

Voici ce que nous pourrions faire :

Côté PHP, nous aurions quelque chose comme ceci :

function getOpsList() {
$sql = new mysql();
$sql->requete("SELECT * FROM operations", 0);
$OpList = array();
 
	         while($data = $sql->resultat(0))
		{
			$opCode = $data[opCode];
			array_push($OpList, $opCode );
		}
	return $OpList;
	}

et côté Flex :

import mx.collections.ArrayCollection;
import mx.utils.ArrayUtil;		
 
public var opList:ArrayCollection; 
 
private function getOpsList_resultHandler( evt:ResultEvent ) : void
{
	 opList = new ArrayCollection( ArrayUtil.toArray(evt.result) );
}

Puis avec un datagrid d'id 'myDG' :

myDG.dataProvider = opList;

On voit que l'on envoie un Array et cet Array est transformé en ArrayCollection côté Flex.

opList = new ArrayCollection( ArrayUtil.toArray(evt.result) );

Mais grâce au RecordSet, nous allons pouvoir recevoir directement depuis AMFPHP une ArrayCollection !

Voici un exemple :

Côté PHP :

function getOpsList()
{
 
return new RecordSet(mysql_query("SELECT * FROM operations"));
 
}

Côté Flex :

private function getOpsList_resultHandler( evt:ResultEvent ) :void
{
	opList = evt.result
}

Et l'on reçoit alors directement une arrayCollection On pourra donc trier, ou formater notre arrayCollection avant son utilisation (affichage dans un datagrid).

Enfin, pour terminer, voyons rapidement le type ByteArray.

Nous allons créer une image côté Flex, l'encoder en JPG et la sauver côté serveur.

J'utiliserai ici la classe d'encodage en jpg de la corelib disponible ici

Côté Flex:

public function saveImage():void
{
	var bmd:BitmapData = new BitmapData(80, 40, true);
	var seed:int = int(Math.random() * int.MAX_VALUE);
	bmd.noise(seed);
				
	var Encoder:JPGEncoder = new JPGEncoder( 75 );
	var BinaryImage:ByteArray = Encoder.encode ( bmd );
			
	BinaryImage.compress();
			
	svc.saveBitmap(BinaryImage);
}

Et pour le service:

public function saveBitmap(p:ByteArray):void
{
        services.getOperation('saveBitmap').send(p);
}

Et côté PHP :

function saveBitmap($ba)
{
    $data = $ba->data;
    $data = gzuncompress($data);
    file_put_contents("Image.jpg", $data);
    return true;
}

Pour envoyer une image depuis php, nous ferions :

function getImage()
{  
 
  return new ByteArray(file_get_contents("monImage.jpg")); 
 
}

Voilà pour le type ByteArray.

Voyons maintenant quelques astuces pour l'organisation d'un projet amfphp. C'est ce dernier point qui avait été la cause de plusieurs incompréhensions pour nombre d'entre vous dans la première version de ce tutorial. Je vais tenter d'être plus clair.

Si vous avez suivi pas à pas mon tutorial, vous devriez avoir l'arborescence suivante pour notre projet :

Personnellement, elle ne me plait pas beaucoup. Je ne la trouve pas très claire. Je préfère avoir un dossier 'php' qui contient tout ce qui concerne php (libs,services,classes,etc...). Voici un exemple :

Avec une telle arborescence, il va falloir configurer quelques trucs.

Tout d'abord, dans le fichier gateway.php, nous devons modifier :

//Include things that need to be global, for integrating with other frameworks
include "globals.php";
 
//Include framework
include "core/amf/app/Gateway.php";

en

//Include things that need to be global, for integrating with other frameworks
include "amfphp/globals.php";
 
//Include framework
include "amfphp/core/amf/app/Gateway.php";

Puis, pour le fichier globals.php, nous modifions :

$servicesPath = "services/";
$voPath = "services/vo/";

en

$servicesPath = "../../services/amfphpServices/";
$voPath = "../../common/vo/";

Pour le fichier ServiceClass.php, afin d'éviter de se retrouver avec un fichier de plusieurs centaines de lignes, on pourra faire :

<?php
//on inclut nos classes principales
require "../../common/CommonClass.php";
 
class ServiceClass
{
	var $op;
 
	function ServiceClass()
	{
		//on instancie notre classe commune
		$this->op = new CommonClass();
	}
 
	function Login_service($login)
        {
 
	return $this->op->CheckLogin($login);
 
        }
}
?>

et la classe CommonClass ressemblera à ça :

<?php
//on inclut notre objet 'login'
require_once "vo/com/phiphou/application/User.php";
 
class CommonClass
{
	 //constructeur
         function CommonClass()
         {
 
         }
 
	function CheckLogin($user)
        {
        //
        //Traitement
        //
	return $user;
    	}
}
?>

Cela peut paraitre un peu compliqué au premier abord mais au final cela permet de mieux organiser nos projets.

Sachez enfin pour finir qu'une extension en C , à installer sur le serveur Apache et qui permet de décupler la vitesse de sérialisation/désérialisation côté php, a été développée par Emanuele Ruffaldi et est disponible ici

Plus d'infos sur cette extension et des tests de vitesse ici.

Rappel : Cette version est une version beta. La version 2.0 ne devrait pas trop tarder. En effet, suite au 'retrait' de Patrick Mineault du projet, un nouveau leader a repris le flambeau et nous prépare cette version. Patience, donc... ;)

Voilà, notre petit aperçu des possibilités qu'offre AMFPHP1.9 est maintenant terminé.

Bon code !