Faire des requêtes SQL (MySQL) avec AMFPHP en Flex
26 juin 2008
Par Jean Marie Macé - Exemples Flex - Lien permanent
Suite à différents message sur des forums je me suis aperçu qu'un petit tutoriel en français était peut être utile. Je vais donc vous présenter comment installer AMFPHP, puis comment faire des requêtes vers une base de données MySQL avec une classe PHP, et récupérer le résultat dans notre application Flex pour alimenter un DataGrid par exemple.
Première chose à faire, c'est récupérer AMFPHP 1.9. Une fois fait, nous allons donc décompresser l'archive puis la déposer sur un ftp. Dans ce tutoriel, je suppose que mon dossier d'installation de AMFPHP est le suivant : /www/amfphp/. Une fois le dossier déposé, allons vérifier l'installation : http://www.lenomdevotredomaine.com/amfphp/gateway.php, vous devriez avoir ce message :
amfphp and this gateway are installed correctly. You may now connect to this gateway from Flash...
Si ce n'est pas le cas, vous devriez trouver de l'aide sur internet pour les cas particuliers. ou bien poster votre problème en commentaires, je tacherais de vous aider ;)
A présent, nous allons peupler notre base de donnée, le script SQL de ce tutoriel est disponible ici
Maintenant, que nous disposons d'un AMFPHP fonctionnel et d'une base de donnée pleine a craquer :), nous allons coder notre classe PHP qui effectuera la requête vers notre base de données. Je ne rentre pas dans les détails concernant le php... vous pouvez récupérer le script ici(click droit, enregistrer la cible sous) . Il faut bien évidement, remplacer les informations de connexion à votre base (host,utilisateur,motdepasse,table) ;). Voici un extrait du code, ne le copiez pas, il n'est pas complet.
[php]
class Contact {
function getAllContact()
{
$rest = array();
// on se connecte
$link = mysql_connect("host","utilisateur", "motdepasse") or die ("Impossible de se connecter : " . mysql_error());
mysql_select_db("table",$link);
$sql = "SELECT * FROM `amfphp_contact`";
// on envoie la requête
$req = mysql_query($sql) or die('Erreur SQL !'.$sql.''.mysql_error());
// on fait une boucle qui va faire un tour pour chaque enregistrement
while($data = mysql_fetch_assoc($req))
{
$id = $data('id');
$nom = $data('nom');
$prenom = $data('prenom');
$email = $data&('email');
array_push($rest, array("id"=>$id, "nom"=>$nom, "prenom"=>$prenom, "email"=>$email));
}
// on retourne le tableau
return $rest;
}
}
Dans ce tutoriel j'ai créé un dossier test dans le répertoire services de AMFPHP. Placez donc ce script PHP dans le dossier suivant : /www/amfphp/services/test/
Nous allons tester que notre script PHP fonctionne correctement, pour cela nous allons utiliser le très utile browser de AMFPHP, il se trouve à cette adresse : http://www.lenomdevotredomaine.com/amfphp/browser/, vous devriez voir a gauche dans l'arborescence un dossier test, et votre classe Contact, cliquez sur celle-ci, puis dans le panneau principal, appuyez sur call. Vous obtiendrez normalement dans le panneau du bas les enregistrements de votre base, comme ceci :
si ca ne fonctionne pas, vérifiez vos identifiant de connexion à votre base...
Voila, maintenant il ne vous reste plus que la partie Flex à mettre en place. Pour cela, créez un nouveau projet sous Flex Builder. Ensuite, créez un fichier services-config.xml à la racine de votre projet(répertoire au dessus de src ;) ). Ce fichier doit contenir ceci (n'oubliez pas de modifier l'url vers votre install d'AMFPHP):
[xml]
<services-config>
<services>
<service id="amfphp-flashremoting-service"
class="flex.messaging.services.RemotingService"
messageTypes="flex.messaging.messages.RemotingMessage">
<destination id="amfphp">
<channels>
<channel ref="my-amfphp"/>
</channels>
<properties>
<source>*</source>
</properties>
</destination>
</service>
</services>
<channels>
<channel-definition id="my-amfphp" class="mx.messaging.channels.AMFChannel">
<endpoint uri="http://www.lenomdevotredomaine.com/amfphp/gateway.php" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
</channels>
</services-config>
Ensuite, indiquez le chemin vers ce fichier au compilateur. Pour ce faire, il faut ajouter une variable de compilation, click droit sur votre projet->Properties->Flex Compiler: ajoutez -services "..\services-config.xml" dans la zone de texte Additional compiler arguments.
Puis, dans votre fichier*.mxml, il vous faut mettre en place vos composants qui vous serviront à afficher les résultats, voici un simple exemple:
[xml]
<mx:VBox horizontalAlign="center">
<mx:Button label="Récupérer les contacts"
click="myservice.getOperation('getAllContact').send();" />
<mx:DataGrid id="myDataGrid">
<mx:columns>
<mx:DataGridColumn dataField="id" headerText="id"/>
<mx:DataGridColumn dataField="nom" headerText="nom"/>
<mx:DataGridColumn dataField="prenom" headerText="prenom"/>
<mx:DataGridColumn dataField="email" headerText="email"/>
</mx:columns>
</mx:DataGrid>
</mx:VBox>
Comme vous le voyez déjà, note bouton va faire l'appel a notre classe PHP, mais pour cela il nous manque le plus important , le RemoteObject :
[xml]
<mx:RemoteObject id="myservice" fault="faultHandler(event)" showBusyCursor="true"
source="test.Contact" destination="amfphp">
<mx:method name="getAllContact" result="resultHandler(event)" fault="faultHandler(event)"/>
</mx:RemoteObject>
On peut noter que la source de notre RemoteObject pointe vers notre classe Contact dans le dossier test. Il ne reste qu'à coder nos méthodes de résultat et d'erreur(toujours utile):
[actionscript]
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
private function resultHandler (evt:ResultEvent):void
{
myDataGrid.dataProvider = evt.result;
}
private function faultHandler (fault:FaultEvent):void
{
Alert.show("code:
" + fault.fault.faultCode + "
Message:
" + fault.fault.faultString + "
Detail:
" + fault.fault.faultDetail);
}
Vous voyez que ma méthode resultHandler alimente le dataProvider de mon DataGrid avec le résultat. Etant donné que mon résultat est un tableau d'objet(id,nom,prenom,email), on voit l'utilité de la propriété dataField dans la déclaration de mon DataGrid.
Voila, tout y est, pour finir, je vous propose une petite démonstration (les sources sont disponible avec le click droit), si vous avez des questions, postez un commentaire ;):
Commentaires
bonjour,
tomasiapparement il y a un problème avec le fichier contact.php,
impossible de l'ouvrir ou de le sauver
Merci pour la remarque, je l'ai renommé en .txt et maintenant c'est ok ;)
Jim_Nastiqmerci pour ce tutoriel très bien fait
tomasifinalement cela fonctionne parfaitement
une question me vient cependant, comment faire pour communiquer dans l'autre sens ?
à savoir de flex vers la base de données (en passant par php) par exemple changer les valeurs de la base en lançant un update depuis flex
comme tu peux le voir pour l'action du bouton j'utilise la méthode send() pour envoyer la requête:
Jim_Nastiqmyservice.getOperation('getAllContact').send();
tu peux tout a fait passer des paramètres :
myservice.getOperation('getAllContact').send("ton param");
concrètement comment ça se passe si je veux mettre à jour mes champs (à supposer que ceux soient éditables) ?
tomasii13quelle sera la valeur du paramètre ?
Je ne comprend pas vraiment ta question...
Jim_Nastiqla valeur a passer cest la valeur que tu souhaites mettre en base de donné:
par exemple un utilisateur change son email, il faut répercuter ce changement en bdd. Tu récupères donc d'un formulaire coté flex que tu auras fais une String correspondant à l'email. Tu appelles donc ta méthode php qui permet de faire un update de ta base.
myservice.getOperation('updateEmail').send("tonmail@mail.com",idducontact);
coté php tu auras un truc du genre :
function updateEmail($email,$id)
{
$query="UPDATE contact SET email=$email WHERE id=$id";
$result=mysql_query($query);
}
Merci pour ces infos;
TomasJ'aimerais savoir si tu as réussi à faire fonctionner correctement amfphp avec des dates (format DATE dans mysql), c'est à dire faire des updates et des select
pour l'instant cela ne fonctionne pas (insertion de 00-00-0000) et on m'a dit que PHP ne reconnait pas les dates comme type de façon native...
cela peut-il fonctionner ? ya il un moyen de contourner ça ?
merci pour tes conseils
je regarderais pour l'update si j'ai un moment, mais en tout cas je fais des SELECT sans aucun soucis sur des champs au format DATE.
Jim_NastiqJ'ai exposé un peu plus en détails mon problème sur le forum developpez.com
Tomaswww.developpez.net/forums...
peut être pourrais tu me montrer comment toi tu fais, utilises-tu la classe DateWrapper ?
Le probleme que tu obtient est simple due au fait que ta base est au format francais alors que le flex lui est au format amercain ( cherche dans le tuto de phiphou (google )) il explique a la fin comment passer d'un a l'autre.
Atherylps : ceci n'est pas de la pub d'ailleurs j'invite l'auteur de ce tuto a le mettre plus ca mis plus c'est lu ;)
Pas de soucis pour le blog de Jean-Philippe ;)
Jim_Nastiqje rajouterais l'information dans mon billet.
Merci pour se super tuto,
ZlotenIl me reste néanmoins un probleme, quand je clique sur "récupérer les contacts" j'obtient l'erreur :
"Channel.Security.Error error Error #2048: Violation de la sécurité Sandbox "
Quelqu'un a-t-il déjà eu se problème ?
as tu bien mis ton services-config.xml à la racine de ton projet flex?
Jim_Nastiqton projet tu l'executes en local? AMFPHP fonctionnne sur un serveur local(easyphp,wamp?) ou bien sur un serveur distant? si tu pouvais des détails sur ce que tu as fait , merci ;)
Oui en effet j'aurais pu donner plus de précision ^^.
ZlotenEn fait je tourne en local avec wamp et je pense que le probleme viens de l'adresse du endpoint sur le fichier services-config.xml je ne suis pas sur d'avoir mis la bonne. Sachant que j'ai placé les fichiers amfphp dans www/amfphp quelle adresse dois-je mettre ?
tu devrais avoir un endpoint de ce genre :
Jim_Nastiqwww.lenomdetondomaine.com...
mais déjà quand tu te connectes au browser amfphp(www.lenomdetondomaine.com... cela fonctionne ou pas?
Oui ca marche bien ca y a pas de probleme. En fait en survolant internet, j'ai trouvé une piste, le probleme serais une histoire de crossdomain.
Zlotenle fichier crossdomain.xml est nécessaire si ton application n'est pas sur le même serveur que AMFPHP. ou si tu as besoin de faire des requetes sur différent serveur.
Jim_Nastiqcomment regler le probleme de crossdomaine alors ???
adnaneil faut créer un fichier crossdomain.xml puis le placer sur ton serveur et faire appel à lui dans ton application flex. je ne me rappelle plus du terme exact mais c'est quelque chose comme securityPolicy. Il y a pas mal d'explication sur le web pour le crossdomain ;)
Jim_NastiqUn grand merci pour ce tutoriel qui fonctionne sous flex 3 sur mon serveur free.
vinceJ'en avais essayé d'autres mais jusqu'à présent ça ne marchait pas.
Je n'ai cependant pas réussi en local avec la même erreur que Zloten...
Bravo pour ce tutorial. Ne relâche pas le mouvement, j'attends tes prochaines contributions avec impatience. Tes tutos sont d'une qualité rare !
xavBonjour
fabienphilippComment ferais tu pour trier les données du datagrid renvoyées par amfphp sans effectuer une nouvelle requête.
Faut il convertir le dataProvider en collections:ArrayCollectionExtended et utiliser alors la propriété filterFunctions.
Cordialement
Fabien.
j'ai un probleme avec la connection a ma base sql
amineAmine,
Si tu souhaites de l'aide, il me faut plus d'informations sur ton problème. As-tu un message d'erreur? quel code as tu mis en place , ... ;)
Jim_NastiqMerci pour votre tuto il m'a bien aidé ! J'ai pu réaliser mon site Flex/php avec easyphp. Mais quand j'ai voulu le mettre en ligne j'ai eu un message d'erreur. Il y a un problème de connexion.
L'erreur :
code: Client.Error.MessageSend
Message: Send failed
Detail: Channel.Security.Error error Error #2048: Violation de la sécurité Sandbox : http://www.l2ol.com/ultimate.swf ne peut pas charger de données à partir de http://localhost:80/ultimate_L2OL/a... url: 'http://localhost:80/ultimate_L2OL/a...
En effet il ne peut pas charger de données depuis localhost, comment lui dire que c'est pas la qu'il faut chercher ?
Quelqu'un peut il m'aider ?
RomEn fait j'avais omis de configurer service-config.xml.txt
Rom... ça marche pas, j'arrive pas à acceder au browser d'AMFPHP j'ai une erreur 500.
et j'ai des erreurs :
Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Failed: url: 'http://www.monsite.com/amfphp/gatew...
Personne ?
Rompbm réglé
RomBonjour,
Rien à faire, j'avais toujours ce message :
message = "faultCode:INVALID_AMF_MESSAGE faultString:'Invalid AMF message' faultDetail:'
Warning: Cannot modify header information - headers already sent by (output started at c:\www\amfphp\services\test\Contact.php:1) in c:\www\amfphp\core\shared\exception\php4Exception.php on line 38
'"
name = "Error"
rootCause = (null)
Il faut dire que j'avais sauvegardé le fichier Contact.php en UTF8 par le bloc-note et qu'un caractère spécial est ajouté en début de fichier!
fmafwoEn le remettant en ansi ça marche. Je ne comprends pas vraiment car j'ai plein de prog php sauvés en utf8 mais je tenais à vous le dire si ça peut aider d'autres personnes.
A bientôt et bon courage.
JM
je te remercie pour ton tuto, il permet de comprendre facilement comment faire des requetes
Tony Ducrocqbonjour merci pour le
goumaje l'ai essayé mais j'ai eu l'erreur suivante
Parse error at '<mx:RemoteObject>'.
Bonjour et merci pour ce tutorial.
Lorsque je tente d'accèder au browser amfphp, j'obtiens l'erreur suivante :
faultDetail = "Channel.Security.Error error Error #2048: Violation de la sécurité Sandbox : file:///C:/wamp/www/amfphp/browser/servicebrowser.swf ne peut pas charger de données à partir de http://localhost/amfphp/gateway.php..."
Je ne comprend pas très d'où vient l'erreur, la page gateway.php m'indique que tout est ok.
Pouvez-vous m'aider svp ?
KanedaMerci d'avance.
Salut Kaneda,
ton problème est classique, c'est un problème de sécurité du Flash Player. Il faut que tu testes ton appli soit en mode web soit en local mais pas de mélange des deux.
Jim_NastiqTu peux rechercher des infos sur le web avec ton erreur, c'est blindé de réponse ;)
Salut Gouma,
Peux tu me donner la ligne de ton code mxml qui correspond à l'instance de ton remoteObject, stp ?
Jim_Nastiqtout le monde doit lire ca pour comprendre!!
fatalisteBonjour,
Mon application fonctionne très bien en local mais pas sur le web (prépod) : elle n'arrive pas à accéder au service et ne met même pas de message d'erreur.
Je travaille actuellement sur notre base de préproduction et l'accès à l'url nécessite une authentification. (l'accès à l'endpoint http://monsite/amfphp/gateway.php a besoin d'un mot de passe). Lorsque j'ai essayé de mettre amfphp sur un répertoire non protégé, j'ai eu la fameuse erreur #2048.
Comment puis-je accéder à mes services? dois-je créer un services-config.xml? (je n'en utilise pas en local, j'appelle directement les services en AS).
Merci d'avance
dringl'erreur 2048 est un problème de sécu sandbox, donc il te faut gérer un cross domain si ton install d'amfphp est sur un autre serveur que ton swf. E tsi tu es en HTTPS il faut indiquer dans ton service config que tu utilises le HTTPS:
<channel-definition id="my-amfphp" class="mx.messaging.channels.SecureAMFChannel">
Jim_Nastiq<endpoint uri="https://tonserveur/amfphp/gateway.p..." class="flex.messaging.endpoints.SecureAMFEndpoint"/>
</channel-definition>
Juste un petit remerciement pour ce tuto... je cherche depuis un moment comment permettre à mes visiteurs de laisser des commentaires sur les rubriques de mon site codé en flex. C'est là une excellente base de travail, bravo !
PierrickSalut !!
nindjaje bloque avec l'intégration de l'amfphp avec flex ,parce que je dois réaliser un système login et je pense que je dois utiliser amfphp????!!
Merci pour votre aide.
héhé !!!! good job
kostarikaBonjour,
J'ai des soucis pour récupérer le fichier Contact.txt . En fait, il n'existe pas.
Est-ce que tu peux le remettre en place STP ?
Merci,
louckiBonjour j'ai un problème avec le fichier gateway.php lorsque j'exécute mon code il m'affiche l'erreur suivante
Channel.Security.Error error Error #2048 url: 'http://localhost/bourse1/php/int/ga...
En faite le même travail marche sur le pc de mon binôme mais lorsque je l'ai essayé sur ma machine sa marche pas
PS: la machine de mon binôme Windows XP la mienne Vista sa pose un problème !!??
achileBonjour,
En faite je travail sur le même sujet, mais une application flex-BlazeDS-java:
J'ai commencé par l'exple de l'article: http://blog.valtech.fr/wordpress/20...
j'utilise comme outil FlexBuilder, en exécutant l'appl déployée sous Tomcat6 dans un navigateur ça fonctionne mais quand je génère le fichier SWF et je l'exécute j'ai l'erreur:
--------------- extrait de l'erreur ------------------
enbilifaultCode:InvokeFailed faultString:'[MessagingError message='Destination 'welcomeServiceDest' either does not exist or the destination has no channels defined (and the application does not define any default channels.)']' faultDetail:'Couldn't establish a connection to 'welcomeServiceDest''
--------------- Fin extrait de l'erreur ------------------
Avez vous une idée sur ce pb
Merci
suite ..
enbilisi j'exécute le SWF généré ar FlexBuilder sous le war: le pb c'est:
--------------- extrait de l'erreur ------------------
faultCode:Client.Error.MessageSend faultString:'Send failed' faultDetail:'Channel.Security.Error error Error #2048: Violation de la sécurité Sandbox : file:///C|/DOCUME%7E1/SNIBIL%7E1.CHO/LOCALS%7E1/Temp/Rar%24DI03.094/flexClient.swf ne peut pas charger de données à partir de http://localhost:8080/valtechFlexDe... url: 'http://localhost:8080/valtechFlexDe...
--------------- Fin extrait de l'erreur ------------------