Bardzo często zdarza się, że tworzone aplikacje potrzebują pobierać dane z bazy danych, czy wysyłać dane do bazy danych. Sama aplikacja nie ma takiej możliwości, ale z pomocą przychodzi nam biblioteka AMFPHP.
AMFPHP jest open source'owym, binarnym protokołem AMF(Action Message Format), który umożliwia komunikację pomiędzy aplikacją Flex'a, a serwerem opartym na PHP. Aplikacja korzysta z usług udostępnianych przez serwer do pobierania danych z bazy danych, bądź wysyłania danych z aplikacji do bazy danych na serwer. Taka komunikacja jest możliwa dzięki utworzeniu klas i wywoływaniu jej metod z pozycji aplikacji.
Tutaj można zobaczyć działanie aplikacji komunikującej się z bazą danych MySQL.
Tutaj można zobaczyć działanie aplikacji komunikującej się z bazą danych MySQL.
Bibliotekę pobieramy ze strony http://sourceforge.net/projects/amfphp/files. Skorzystamy z najnowszej dostępnej wersji 2.0.1. Następnie, użyjemy lokalnego serwera WampServer w wersji 2.2d (może być też wersja starsza np. 2.1) do umieszczenia na nim pobranej biblioteki. W tym celu tworzymy w katalogu C:\wamp\www folder o nazwie amfphp2 i kopiujemy do niego całą zawartość biblioteki.
[kliknij na obrazek aby powiększyć] |
W katalogu Services będziemy umieszczali nasze usługi. Znajduje się w nim przykładowa usługa ExampleServices.php, którą można uruchomić aby zobaczyć jak ona działa.
My napiszemy własną usługę i ją przetestujemy. W tym celu tworzymy klasę Test i tworzymy dwie funkcje: sayHello i myName.
Test.php
<?php
class Test {
public function sayHello() {
return "Hello World!";
}
public function myName($first_name, $last_name) {
$result = "Imie: $first_name\nNazwisko: $last_name";
return $result;
}
}
?>
Teraz sprawdzamy, czy usługa działa prawidłowo. Wpisujemy w przeglądarce internetowej adres http://localhost/amfphp2. Po lewej stronie przeglądarki widzimy usługi jakie udostępniliśmy i listę metod, jakie posiadają. Klikamy na metodę sayHello. Obok pojawią się informacje o funkcji i przycisk Call method. Klikając na przycisk, powinien pojawić się napis Hello World!.
[kliknij na obrazek aby powiększyć] |
Zobaczmy, jak działa druga metoda. Klikamy na myName. Zauważmy, że tutaj musimy podać dwa parametry i klikamy Call method. Poniżej pojawi się napis z podanymi przez nas parametrami.
[kliknij na obrazek aby powiększyć] |
Tak poprawnie utworzoną usługę możemy udostępnić w aplikacji. W tym celu utwórzmy sobie nowy projekt o nazwie AMFPHP_APP. Następnie musimy dodać plik konfiguracyjny, który będzie się łączył z biblioteką na serwerze. Klikamy prawym przyciskiem myszki na folder src i wybieramy New ---> File. W polu File name wpisujemy services-config.xml i klikamy Finish. Do utworzonego pliku wklejamy następujące ustawienia:
<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service id="amfphp-flashremoting-service" class="flex.messaging.services.RemotingService" messageTypes="flex.messaging.messages.RemotingMessage">
<destination id="amfphp">
<channels>
<channel ref="amfphp2"/>
</channels>
<properties>
<source>*</source>
</properties>
</destination>
</service>
</services>
<channels>
<channel-definition id="amfphp2" class="mx.messaging.channels.AMFChannel">
<endpoint uri="http://localhost/amfphp2/" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
</channels>
</services-config>
Następnie dołączamy go do kompilatora: Prawym przyciskiem myszki klikamy na AMFPHP_APP ---> Properties ---> Flex Compiler i dołączamy argument -services services-config.xml.
[kliknij na obrazek aby powiększyć] |
Skoro mamy już wszystko przygotowane, to możemy przystąpić do udostępnienia usługi w aplikacji. W tym celu użyjemy obiektu zdalnego
<mx:RemoteObject>
. <mx:RemoteObject id="test" source="Test" destination="amfphp"
result="resultHandler(event)" fault="faultHandler(event)">
<mx:method name="sayHello" />
<mx:method name="myName" />
</mx:RemoteObject>
Do atrybutu
source
przypisaliśmy nazwę klasy, do destination
przypisaliśmy identyfikator z pliku konfiguracyjnego. Przy pomocy znacznika <mx:method>
zdefiniowaliśmy metody należące do klasy Test.Aby możliwe było wyświetlenie danych pobranych z serwera implementujemy w ActionScript funkcję resultHandler przypisaną do atrybutu
result
. W razie niepowodzenia wyświetlimy kod i nazwę błędu przy pomocy funkcji faultHandler, którą przypisaliśmy do atrybutu fault
.<mx:Script>
<![CDATA[
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
private function resultHandler(event:ResultEvent):void {
wynik.text = event.result.toString();
}
private function faultHandler(event:FaultEvent):void{
wynik.text = "### Error ###\nCode: " + event.fault.faultCode + "\nMessage: " + event.fault.faultString;
}
]]>
</mx:Script>
Zwracane dane są przypisane do pola tekstowego, a za pomocą przycisków wywołamy metody z klasy Test.
<mx:VBox top="100" left="100">
<mx:HBox>
<mx:Button id="btn1" label="sayHello" click="test.sayHello()" />
<mx:Button id="btn2" label="myName" click="test.myName('Jan','Kowalski')" />
<mx:Button id="btn3" label="error" click="test.myName()" />
</mx:HBox>
<mx:TextArea id="wynik" width="260" height="120" />
</mx:VBox>
Zauważmy, że do ostatniego przycisku dodaliśmy funkcję myName bez parametrów. Sprawdzimy w ten sposób działanie funkcji faultHandler.
Poniżej widzimy działanie aplikacji komunikującej się z serwerem PHP.
[kliknij na obrazek aby powiększyć] |
Przykład komunikacji AMFPHP z bazą danych MySQL
Na początek stwórzmy sobie przykładową bazę danych AMFPHP_FLEX i tabelę users następująco:
CREATE TABLE users(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(1000) NOT NULL ,
surname VARCHAR(1000) NOT NULL ,
email VARCHAR(1000) NULL,
age INT NULL)
Ważne jest aby przy tworzeniu bazy, tabeli i kolumn (typ np. varchar) Metoda porównywania napisów była ustwiona na utf8_general_ci. Wtedy nie będą pojawiać się "krzaczki" podczas pobierania z bazy i przesyłania do bazy danych napisów z polskimi znakami.
Teraz musimy napisać usługę, która będzie się komunikowała z bazą danych.
Database.php
<?php
class Database
{
private $AUTHOR = "poradnikkomp@o2.pl";
private $URL = "http://poradnikkomp.blogspot.com";
private $VERSION = "2.0.0";
public function Database()
{
}
/*
* Execute a SQL statement to database. READ
* @return the result array.
*
*/
public function query($strQuery, $strUser, $strPass, $strHost, $strDB)
{
$rsConnectionID = $this->open($strUser, $strPass, $strHost, $strDB);
$rsResult = mysql_query($strQuery, $rsConnectionID);
$result = array();
while ($data = mysql_fetch_object($rsResult)) {
$result[] = $data;
}
if(!$rsResult)
return mysql_error($rsConnectionID);
if(($lastInsertID = mysql_insert_id($rsConnectionID)) != 0)
return $lastInsertID;
$this->close($rsConnectionID);
return $result;
}
/*
* Execute a SQL statement to database. CREATE, UPDATE, DELETE
* @return null.
*
*/
public function queryOperation($strQuery, $strUser, $strPass, $strHost, $strDB)
{
$rsConnectionID = $this->open($strUser, $strPass, $strHost, $strDB);
$rsResult = mysql_query($strQuery, $rsConnectionID);
if(!$rsResult)
return mysql_error($rsConnectionID);
if(($lastInsertID = mysql_insert_id($rsConnectionID)) != 0)
return $lastInsertID;
$this->close($rsConnectionID);
return null;
}
/*
* Open the connection to the database.
* @return the connection id.
*
*/
private function open($strUser, $strPass, $strHost, $strDB)
{
$rsConnectionID = @mysql_connect($strHost, $strUser, $strPass);
mysql_select_db($strDB, $rsConnectionID);
mysql_query("SET NAMES 'utf8';");
mysql_query('SET CHARACTER SET utf8;');
return $rsConnectionID;
}
/*
* Close the connection to the database.
* @return a resource.
*
*/
private function close($rsConnectionID)
{
$res = @mysql_close($rsConnectionID);
return $res;
}
/*
* @return a string Author.
*
*/
public function getAuthor()
{
return $this->AUTHOR;
}
/*
* @return a string Url.
*
*/
public function getUrl()
{
return $this->URL;
}
/*
* @return a string Version.
*
*/
public function getVersion()
{
return $this->VERSION;
}
}
?>
Dołączamy naszą usługę jak uprzednio.
<mx:RemoteObject id="connection" source="mysql.database" destination="amfphp"
showBusyCursor="true" result="resultHandler(event)" fault="faultHandler(event)">
<mx:method name="query" />
<mx:method name="queryOperation" />
</mx:RemoteObject>
Następnie ustawiamy parametry funkcji query i queryOperation:
private static const USER:String = "root"; // login do MySQL'a
private static const PASSWORD:String = ""; // hasło do MySQL'a
private static const HOST:String = "localhost"; // nazwa hosta
private static const DB:String = "AMFPHP_FLEX"; // nazwa bazy danych
Teraz napiszemy funkcje, które będą wykonywały operację CRUD (create, read, update, delete).
private var execute:String;
// CREATE
private function createUser():void {
execute = "INSERT INTO users (name, surname, email, age) VALUES ('" + textUSER.text + "', '"
+ textSURNAME.text + "', '" + textEMAIL.text + "', '" + textAGE.text + "')";
connection.queryOperation(execute, USER, PASSWORD, HOST, DB);
}
// READ
private function getUsers():void{
execute = "SELECT * FROM users";
connection.query(execute, USER, PASSWORD, HOST, DB);
}
// UPDATE
private function updateUser():void {
execute = "UPDATE users SET name='" + textUSER.text + "', surname='" + textSURNAME.text
+ "', email='" + textEMAIL.text + "', age='" + textAGE.text
+ "' WHERE id='" + dataMysql.selectedItem.id + "'";
connection.queryOperation(execute, USER, PASSWORD, HOST, DB);
}
// DELETE
private function deleteUser():void{
execute = "DELETE FROM users WHERE id=" + dataMysql.selectedItem.id;
connection.queryOperation(execute, USER, PASSWORD, HOST, DB);
}
Funkcje te podpinamy do zdarzenia
click
znacznika <mx:Button>
.Potrzebujemy jeszcze kontrolki, która będzie wyświetlała naszych użytkowników. Użyjemy do tego DataGrid.
<mx:DataGrid id="dataMysql" dataProvider="{users}">
<mx:columns>
<mx:DataGridColumn dataField="id" headerText="Number" />
<mx:DataGridColumn dataField="name" headerText="First name" />
<mx:DataGridColumn dataField="surname" headerText="Last name" />
<mx:DataGridColumn dataField="age" headerText="Age" />
<mx:DataGridColumn dataField="email" headerText="Email" width="200" />
</mx:columns>
</mx:DataGrid>
Do atrybutów
dataField
przypisaliśmy nazwy kolumn z tabeli MySQL'a. I na koniec zmodyfikujmy funkcję resultHandler:
[Bindable]
public var users:ArrayCollection;
private var resultObject:Object;
private function resultHandler(event:ResultEvent):void {
resultObject = event.result;
users = new ArrayCollection(resultObject as Array);
}
W kolejnych częściach kursu:
Mam ptytannie odnośnie "Na początek stwórzmy sobie przykładową bazę danych AMFPHP_FLEX i tabelę users następująco:"
OdpowiedzUsuńGdzie mam utworzyć tą baze?
Generalnie, to jak zainstalujesz sobie wampa, to tam masz phpAdmina i tam sobie utwórz bazę danych.
UsuńDodatkowo nie mogę dojść do tego gdzie wrzucić te funkcje :(
OdpowiedzUsuńFunkcje w jednym pliku Database.php umieszczasz w amfphp2/services. Zrób sobie dokładnie pierwszą część opisu na tej stronie. Ten ogólny. Tam jest opisane gdzie umieszczać usługi.
UsuńNiestety, teraz nie mam chwili żeby przysiąść i napisać bardzo szczegółowo tego. Może za jakieś 2 tygodnie mogę postarać się napisać.
OdpowiedzUsuń