2006-05-21 14:05
Czasy się zmieniąją, zmieniają się wersje Flasha, ale większość użytkowników nie zmienia swoich przyzwyczajeń, korzystając ciągle z metod które już niedługo mogą być deprecated, lub wymagają sporo zachodu przy większych projektach.
Technologia Flash Remotingu dostępna jest już od 6 wersji Flasha. Jednak ze względu na niską dostępność dla przeciętnego developera oraz brak materiałów na ten temat przemknęła cicho nie zwracając na siebie uwagi. Technologia ta ma swoje implementacje w .NET, Javie, ColdFusion i innych językach serverside wbudowane domyślnie, lub jako odrębne biblioteki, Niski odsetek użytkowników tych technologii spowodował że remoting nie stał się zbyt popularny. Jednak od jakiegoś czasu dostępna jest darmowa (co ważne) implementacja w PHP
I tu zaczyna się nasza historia.
Remoting to metoda na prosta wymianę danych między Flashem i językiem serwerowym. Czym różni się od LoadVars itp.? Argumentów jest sporo.
Kiedy przesyłasz do Flasha jedną, 2 zmienne nie jest to problemem. Kiedy chcesz przesłać większą paczkę danych korzystasz z xml. A co jeśli chcesz wykorzystać bazę danych?
Po stronie serwera wywołujesz zapytanie sql, przekładasz je na XML (lub nawet stringa) przesyłasz do Flasha gdzie zamieniasz z powrotem na ciąg zmiennych, obiekty, tablice itp.
Jak na tak prostą rzecz to trochę długa droga. Spora strata czasu i zasobów na prosta wymianę informacji.
Flash Remoting to zestaw narzędzi w których skład wchodzi bramka serwerowa, zestaw komponentów, klas i debugger. Po stronie Flasha dysponujesz zestawem klas do kodowania i dekodowania danych. Podobnie po stronie serwera bramkę która wykonuje to samo zadanie oraz wywołuje żądaną metodę. Dane wymieniane są w binarnym formacie AMF inspirowanym SOAP. Zarówno bramka jak i klasy flasha tłumaczą dane na neutralny format, i to pozwala na wymianę danych między różnymi technologiami w sposób niewidoczny.
Jakie więc zalety remotingu zdecydują o tym aby zrezygnować zupełnie z innych metod?
Trzy podstawowe czynniki powinny Cię do tego przekonać – zachowanie typów zmiennych (String, Number, Array, Object [hash, tablica asocjacyjna jak kto woli]), obsługa obiektów zwracanych przez zapytania sql (żadnych tam fetch_array itp.) oraz mapowanie klas (czego tutaj nie rozwiniemy niestety)
Po wszystkich zachwytach na technologią przejdźmy do konkretów
Paczkę instalacyjna ostatniej wersji AMFPHP ściągniesz tutaj lub bezpośrednio ze strony projektu w dziale download .
Update:
Wersję beta AMFPHP 1.9 możesz pobrać tutaj
Pamiętaj jednak że ta wersja różni się od opisanej w tutorialu, min brak methodTable, i deaktywowane kilku typowych ficzersów.
Po stronie PHP
Instalacja po stronie serwera sprowadza się do skopiowania zawartości katalogu instalacyjnego na serwer. Poprawne funkcjonowanie zapewniają ustawienia w pliku gateway.php. Podstawową zmianą jaką musimy wprowadzić jest odnalezienie tej linii
//$gateway->setCharsetHandler("utf8_decode", "ISO-8859-1", "ISO-8859-1");
i zamiana na
$gateway->setCharsetHandler("iconv", "ISO-8859-2", "ISO-8859-2");
Co umożliwi nam obsługę polskich znaków. Jeśli to ustawienie nie przynosi rezultatu odnośnie polskich znaków możesz spróbować drugiej wersji, czyli zamienić tą linię na
$gateway->setCharsetHandler( "iconv", "UTF-8", "UTF-8" );
Jeśli uważasz że wszystko zrobiłeś jak trzeba, i w dalszej części wywołanie metod z flaha nie przynosi rezultatu (mimo że w debuggerze widzisz że wywołanie się powiodło) sprawdź czy masz zainstalowana bibliotekę iconv, w przypadku jej braku i takiego ustawienia w gateway.php AMFPHP nie musi zwrócić błędu.
Po przygotowaniu wszystkiego, wywołaj plik gateway.php w przeglądarce w poszukiwaniu ew. błędów. Jeśli przeglądarka spróbuje ściągnąć plik, oznacza to, że wszystko poszło zgodnie z oczekiwaniami. Pamiętaj aby wszystkie pliki zostawić na serwerze, są one wymagane do poprawnego funkcjonowania FR. Jedynie Service Browser jest wskazane aby nie umieszczać na ostatecznym serwerze, gdyż zawiera podgląd wszystkich metod.
Pamiętaj że jedna instalacja AMF obsługuje nieograniczoną (nigdzie nie podaje się limitu) liczbę usług, także jedną instalację możesz wykorzystać równolegle do wielu projektów.
Po stronie flasha
Dostęp do klas remotingu dostajesz po instalacji rozszerzenie które można pobrać tutaj
Po zainstalowaniu tego rozszerzenia otrzymujesz 5 podstawowych elementów
Po przygotowaniu wszystkich elementów czas na przetestowanie systemu.
Utworzymy więc pierwszą usługę (Service) po stronie serwera. Utwórz plik HelloWorld.php i wpisz do niego
<?php
class HelloWorld
{
function HelloWorld()
{
$this->methodTable = array
(
"krzycz" => array
(
"access" => "remote",
"description" => "Zwraca przesłaną informację"
)
);
}
function krzycz($wiadomosc)
{
return 'Dre się ' . $wiadomosc;
}
}
?>
Tak przygotowany plik php umieść w folderze services w instalacji twojego AMFPHP
W tym folderze musisz umieszczać wszystkie przygotowane przez Siebie usługi. Przeglądać je możesz wchodząc w folder browser, gdzie umieszczona jest prosta i funkcjonalna przeglądarka Twoich usług wraz z generowanym kodem AS do wykorzystania.
Teraz we Flashu utwórz nowy dokument, otwórz Window > Common Libraries > Remoting
(lub Window > Others > Libraries > Remoting zależnie od wersji flasha) i przeciągnij obydwie paczki na scenę. Oczywiście mimo że są one widoczne nie mają one swojej reprezentacji graficznej po opublikowaniu filmu.
Następnie w pierwszej klatce filmu wklej następujący kod
import mx.remoting.*;
import mx.rpc.*;
import mx.remoting.debug.NetDebug;
var gatewayUrl:String = "http://localhost/flashservices/gateway.php"//tutaj oczywiście ścieżka do Twojej instalacji AMF, zamiast pliku gateway.php lepiej przy testowaniu wykorzystywać plik debuggateway.php, który znajduje się w tym samym folderze, a przesyła więcej informacji do NetDebugerra
NetDebug.initialize();
var _service:Service = new Service(gatewayUrl, null, 'HelloWorld', null , null);//przyjmowane argumenty to: [sciezka do bramki, logger, nazwa metody, połaczenie, responder ]
//logger
//obiekt w którym tworzone będą logi, więcej informacji szukaj w Log class
//połączenie
//pozwala wykorzystać istniejące połączenie, np. nazwaUslugi.connection,
//responder
//obiekt responder zawierający metody obsługujące rezultaty oraz błędy
var pc:PendingCall = _service.krzycz("Hello world!");//wywołujesz metodę i przekazujesz jej wybrane argumenty, pamiętaj że możesz przekazywać nie tylko Stringi ale praktycznie wszystkie dostępne typy z Tablicami włącznie
pc.responder = new RelayResponder(this, "onRezultat", "onError");//
//obiekt responder zajmuje się wywołaniem przekazanych mu metod/funkcji po uzyskaniu odpowiedzi ze strony serwera
//pierwszy argument to obiekt który otrzyma odpowiedź, zazwyczaj odpowiada Listwie czasowej na której znajdują się funkcje obsługujące rezultaty
//Jeśli scieżka ta będzie niepoprawna skrypt nie zareaguje na odpowiedź serwera, co jest częstym błędem na początku.
function onRezultat(re:ResultEvent) {//funkcji tej przekazywany jest obiekt z rezultatem zwróconym przez metodę, np. rezultatem zapytania sql, ale o tym później
trace('Co się drzesz, ' + re.result);
}
function onError(fe:FaultEvent){//tutaj z koleji przekazywany jest obiekt błędu
trace('Wystąpił błąd, o następującej treści: '+fe.fault.faultstring);//a tak można dostać się do jego treści
}
Przetestuj film i spójrz co wyświetliło Ci okno Output. Powinieneś uzyskać "Co się drzesz, Dre się Hello world!"
Jeśli jednak zakończyło się to monitem o błędach:
Jeśli uzyskałeś informację **Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 8: The class 'Service' could not be loaded. (...)
Nie dodałeś poprawnie klas do filmu Wybierz Window > Common Libraries > Remoting (lub Windows > Others > Libraries > Remoting) i przeciągnij obydwie klasy na scenę, a poźniej możesz je skasować, ważne żeby znajdowały się w bibliotece filmu.
Error opening URL "http://localhost/flashservices/gateway.php"
Niepoprawnie podałeś ścieżkę do bramki, lub serwer nie jest uruchomiony.
"Wystąpił błąd, o następującej treści: (...)"
Sprawdź treść błędu lub spójrz w okno NetConnection Debugger. Możliwe że popełniłeś jakiś błąd w klasie PHP, lub nie wpisałeś metody do methodTable
Jeśli nie otrzymujesz żadnego komunikatu, a film po wysłaniu zapytania (co jest widoczne w debuggerze) nie odpowiada, sprawdź poprawność napisanej klasy PHP (wywołując ją w przeglądarce) lub sprawdź czy firewall nie blokuje wywołań.
Jak wspomniałem parokrotnie wcześniej remoting pozwala na zachowanie typów zmiennych przesyłanych w obie strony. Poniżej tabelka jak obsługiwane są poszczególne typy wraz z ograniczeniami.
| Typ we flash`u | Typ w PHP | uwagi | Automatyczna obsługa |
|---|---|---|---|
| null | null | tak | |
| Boolean (wartość logiczna) | boolean | tak | |
| String | string | tak | |
| Date | float | Unix timestamp, ustaw typ zwracanej zmiennej na Date | nie |
| Array | array | tak | |
| Object | tablica asocjacyjna | tak | |
| XML | String | Ustaw typ zwracanej zmiennej na XML aby przesłać do AS | nie |
| Recordset | Resource | Tylko z PHP do AS, nie odwrotnie | tak |
Dla typów z automatyczną obsługą nie ma potrzeby deklarowania typu zwracanego. W innym
wypadku musisz zastosować rozwiązanie podobne jak tutaj
<?php
class RemoteDate
{
function RemoteDate()
{
$this->methodTable = array(
"getRemoteDate" => array(
"description" => "Zwraca czas serwera jako obiekt Date do flasha",
"access" => "remote",
"returns" => "Date"
),//returns ustala typ zwracanej zmiennej
"getRemoteDateString" => array(
"description" => 'Zwraca czas na serwerze w formie stringa, w formacie"Sun Mar 12 00:06:30 GMT+0800 2006"',
"access" => "remote",
),
"getTimezoneOffset" => array(
"description" => "Zwraca różnicę w minutach, między czasem uniwersalnym a czasem serwera",
"access" => "remote",
)
);
}
function getRemoteDate()
{
//Note:: musisz zwrócić czas w milisekundach pomnożony przez *1000
return time()*1000;
}
function getRemoteDateString()
{
return date('D M d H:i:s \G\M\TO Y', time());
}
function getTimezoneOffset()
{
return date('Z')/60;
}
}
?>
Mam nadzieję że to przybliżyło Cię do nowego wymiaru wymiany danych Flash-ServerSide, i skłoni do pożegnania się z LoadCośtam.
Miłego testowania.