Blog Archive

Friday, May 28, 2010

AmfPHP ile Flash Remoting'e Giriş(Flash ile veri tabanı arasında XML olmadan veri alışverişi yapacağız)

Flash ile ActionScript kullananların şu ana kadarki en büyük korkulu rüyası veri tabanı ile iletişim kurmaktı herhalde. Çünkü Flash doğrudan veri tabanından veri alamaz. Doğrudan veri tabanına veri yazamaz.

Adobe Flex Data Services ürününü çıkardığında işte bu ve benzeri sorunları çözme yoluna gitti. Flex Data Services, Java Programlama Dili ile server taraflı uygulamalaları, class olarak yazdıktan sonra, Flash uygulamalarınızla bu classlardan nesne yaratma olanağı sunuyor idi.

XML ile iletişimde farklı olarak Adobe Flex Data Services ürünü flash ile Binary iletişim kuruyordu. Bu da XML için kullandığınız Tag ‘ları kullanmamanız böylece daha yalın veriler ile alışveriş yapmanız anlamına geliyordu. Adobe iletişimde kullandığı bu mesaj formatına Adobe Messaging Format ismini verdi. Bu şekilde AMF0 ortaya çıktı. Bu gün bu format revize edildi ve AMF3 oldu. Ancak siz haberleşmenizde hala AMF0 ve AMF3 tercihi yapabiliyorsunuz.

Daha sonra adobe firması bu ürünün adını Adobe Live Cycle Data Services olarak değiştirdi. Açık kaynak kod cephesinde de bu ürünün yerini doldurmak amacıyla çeşitli ürünler çıktı. Bu ürünlerden en popüleri olarak RED5 ‘i burada örnek vermek yerinde olur.

Adobe bir boşluğu doldurmuştu ama bu ürünle birlikte önemli bir boşluk daha ortaya çıkmıştı. PHP, ASP.NET dillerini kullanarak server taraflı kod yazan ve Flash’ı bu şekilde veri tabanı ile haberleştiren kişiler için de bu teknikleri kullanabilecekleri bir ürün gerekliydi. Bu amaçla 3. nesil program olarak birkaç çözüm geldi. Bu çözümlerden en popüler ikisinin ismi AmfPHP ve WebOrb.

WebOrb, php,.NET,Java ve Ruby on Rails için 4 ayrı sürüme sahiptir ve .NET için olan sürümü RTMP dahil Adobe Live Cycle Data Services ürününün Java ile yapabildiği herşeyi yapabilir.

AmfPHP ise sadece yazdığınız PHP class dosyasını uzaktan çalıştırmanızı sağlar.

AmfPHP’yi www.amfphp.org adresinden indirebilirsiniz. Yada buraya tıklayarak doğrudan indirebilirsiniz. Şu anki kararlı son sürüm amfphp 1.2 ve son sürüm ise amfphp 1.9 betadır.

AmfPHP ‘yi indirdikten sonra web server’ınızdaki document root klasörüne açınız. yani http://localhost/amfphp

şeklinde AmfPHP’ye erişebilmeliyiz. Eğer herşey yolunda ise

http://localhost/amfphp/gateway.php

adresinden aşağıdaki gibi bir görüntü alırsınız:

MMİstanbul

eğer Load the service browser linkine tıklarsanız. Oluşturduğunuz servisleri görmek ve olarla test sürüşü yapma şansına sahip olursunuz. Ancak ilk kez service browser’ı açıyorsanız o zaman AmfPHP size hangi iletişim kuralını kullanacağınızı sorar.

MMİstanbul

AmfPHP’yi başka bir klasöre kopyalarsanız yada uzak sunucuya atarsanız yine aynı soru ile karşılaşırsınız. Bu soruya bir kez yanıtvermeden de flash yada flex ile AmfPHP’ye bağlantı kuramazsınız

AmfPHP ile bir web servisi oluşturmak için tek yapmanız gereken servisinizi bir class olarak hazırlayıp amfphp klasörü içindeki services klasörüne atmak olacaktır.

Ancak buna geçmeden önce AmfPHP ile yapılacak son bir işlemimiz daha var. AmfPHP standart olarak ilk kurulduğunda ISO-8859-1 karakter setiyle çalışmaktadır. Oysaki bu karakter seti ile türkçe karakterleri kullanmamız çok zor olur. Bu karakter seti ayarlamasını UTF-8 ‘e dönüştürmeliyiz. Bunun için amfphp kök dizinindeki gateway.php dosyasını açıp şu satırı bulun:

//Read above large note for explanation of charset handling
//The main contributor (Patrick Mineault) is French,
//so don't be afraid if he forgot to turn off iconv by default!
$gateway->setCharsetHandler("utf8_decode", "ISO-8859-1", "ISO-8859-1");

üstteki üç satır açıklama satırı. Alttaki satır ise karakter setinin belirlendiği satır. Bu satırı şu şekilde yeniden düzenleyin:

$gateway->setCharsetHandler("utf8_decode", "utf-8", "utf-8");

Şimdi Flash Remoting ‘e en basit girişi yapabileceğimiz AmfPHP ‘yi kullanarak, bir veri tabanına kayıt yapalım. Öncelikle MySQL ile bir veri tabanı ve tablo oluşturalım:

CREATE DATABASE `flash_test_db` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

CREATE TABLE `flash_test_db`.`kisiler` (
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR( 20 ) NOT NULL ,
`tel` VARCHAR( 11 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB

veri tabanımızın adı : flashtestdb ve kişi isimleri ve telefon numaralarını tutacağımız tablonun ismi ise kisiler oldu.

Bu veritabanında yetkili kullanıcıyı oluşturalım ve bu veri tabanı üzerinde yetkilendirelim

CREATE USER 'amfphpuser'@'localhost' IDENTIFIED BY 'amfphppass';

GRANT USAGE ON * . * TO 'amfphpuser'@'localhost' IDENTIFIED BY 'amfphppass' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;

GRANT ALL PRIVILEGES ON `flash\_test\_db` . * TO 'amfphpuser'@'localhost' WITH GRANT OPTION ;

bu veri tabanına ulaşacak php class’ını oluşturalım:

dbObj = mysql_pconnect(DATABASE_SERVER, DATABASE_USERNAME, DATABASE_PASSWORD) or (trigger_error(mysql_error(),E_USER_ERROR));
mysql_select_db(DATABASE_NAME, $this->dbObj);
}
private function SQL($sql){
$queryReturn= mysql_query($sql,$this->dbObj) or trigger_error("AMFPHP şu hatayı döndürdü hata oluşan class: 'connect_to_mysql' hata veri tabanında SELECT cümlesi işlenirken oldu. mysql tarafından döndürlen hata :\nError:" . mysql_error());
return $queryReturn;
}
private function insertSQL($table,$fields){
$insertSQL="INSERT INTO `".$this->dbPrepend.$table."` (";
$fieldSQL="";
$valueSQL="";
foreach ($fields as $field=>$value){
if($fieldSQL!="") $fieldSQL.=",";
$fieldSQL.="`".$field."`";
if($valueSQL!="") $valueSQL.=",";
$valueSQL.="'".$value."'";
}
$insertSQL.=$fieldSQL.") VALUES (";
$insertSQL.=$valueSQL.");";
mysql_query($insertSQL,$this->dbObj) or trigger_error("AMFPHP şu hatayı döndürdü hata oluşan class: 'connect_to_mysql' hata veri tabanında INSERT cümlesi işlenirken oldu. mysql tarafından döndürlen hata :\nError:" . mysql_error());
return true;
}
public function insertPerson($person){
$values= array(
'name' =>$person['name'],
'tel' =>$person['tel']
);
$this->insertSQL('kisiler',$values);
}
public function getAllPersons(){
$personSQL="SELECT * FROM `kisiler`";
return $this->SQL($personSQL);
}
}
?>

bu php class’ı PHP5 standarlarına göre yazıldı. Ancak PHP4’e de uygun yazıldı. eğer public ve private bildirimlerini silerseniz PHP4 ile de çalışacaktır. Yazdığımız class dosyasını amfphp klasöründeki services klasörünün altına kaydediyoruz.

Nesne Yönelimli Programlamanın en temel unsurlarından olan public ve private bildirimleri ile çalışmak çok önemlidir. Yazdığımız php cllass’ındaki private yordamlara (fonksiyon) flashRemoting ile erişmemiz mümkün değil. Bu yolla veri tabanını ve uygulamamızı korumuş oluyoruz.

Şimdi de flash dosyamızı oluşturalım:

MMİstanbul

ve action script kodları da şöyle:

btnGonder.addEventListener(MouseEvent.CLICK,btnGonderClicked);
function btnGonderClicked(event:MouseEvent){
var postObj:Object={name:txtAdSoyad.text,tel:txtTelefon.text}
var nc:NetConnection= new NetConnection();
var resp:Responder = new Responder(postSuccessHandler,faultHandler);
nc.connect("http://localhost/amfphp/gateway.php");
nc.call("connect_to_mysql.insertPerson",resp,postObj);
}
function postSuccessHandler(result:Object){
trace("Kayıt Girişi başarılı");
}
function faultHandler(fault:Object){
trace("Bağlantı Hatası");
}

burada yapılan işlem kabaca şöyle:

http://localhost/amfphp/gateway.php adresine bir bağlantı oluşturuluyor. Bu bağlantıyı oluşturan bağlantı nesnesinin türü NetConnection, ismi ise nc. Bu nesnenin call yordamı bizim yazdığımız php class’ına erişmemizi sağlıyor. sınıfadı.yordam_adı şekilnde hangi yordama bağlanacağımızı ilk parametre ile anltoyoruz.

ikinci parametre bu işlem gerçekleştiğinde dönen bilgileri yakalamak için kullanılacak Responder tipinde resp nesnesi. Bu nesne ise iki türlü sonucun olabilirliği ile çalışıyor. Birisi fonksiyonun (yordamın) başarıyla çalışması ve geriye bir değer döndürmesi. Diğeri ise bir hata oluşması.

üçüncü parametre isteğe bağlıdır. Son parametre değildir. Üçüncü parametreden itibaren istediğimiz kadar parametre yazabiliriz. Bu parametreler çağırdığımız yordama geçirilecektir. Bizim yazdığımız insertPerson yordamı bir parametre aldığı için bizde bir parametre göndermeyi tercih ettik. Gönderdiğimiz parametre bir Object idi. Bu türden parametreler göndermeye mecbur değiliz. Sadece öreneğimizin zengin olması bakımından, nesneleri de parametre olarak geçirbileceğimizi göstermek ve geçirdiğimiz nesne parametreleri PHP ile nasıl çözeceğimizi de göstermek amacıyla Object geçirdik.

flash’ı çalıştıralım ve bir veri girişi yapalım :

MMİstanbul

bu işlem sonucunda veri tabanına veri girişi yapılıp yapılmadığını phpmyadmin ile kontrol edelim :

MMİstanbul

service borwser’ı tekrar çalıştıralım:

MMİstanbul

yazdığımız class soltarafta görünüyor. Sağda ise class’daki public fonksiyonlar görünüyor. getAllPersons fonksiyonunu seçip call butonuna bastığımda alt kısımda fonksiyon çaıştığında geriye döndürdüğü değerleri görüyoruz. Eğer Flex ile çalışıyorsanız o zaman aşağıdaki kodu kullanabilirsiniz.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
public function btnGonderClicked(event:MouseEvent):void{
var postObj:Object={name:txtAdSoyad.text,tel:txtTelefon.text}
var nc:NetConnection= new NetConnection();
var resp:Responder = new Responder(postSuccessHandler,faultHandler);
nc.connect("http://localhost/amfphp/gateway.php");
nc.call("connect_to_mysql.insertPerson",resp,postObj);
}
private function postSuccessHandler(result:Object):void{
trace("Kayıt Girişi başarılı");
}
private function faultHandler(fault:Object):void{
trace("Bağlantı Hatası");
}
]]>

</mx:Script>
<mx:Panel x="10" y="10" width="370" height="238" layout="absolute">

<mx:Form right="0" left="0" bottom="50" top="0">
<mx:FormItem label="Adı Soyadı">
<mx:TextInput id="txtAdSoyad"/>

</mx:FormItem>
<mx:FormItem label="Telefonu">
<mx:TextInput id="txtTelefon"/>
</mx:FormItem>
</mx:Form>
<mx:Button x="187" y="156" label="Gönder" id="btnGonder" click="btnGonderClicked(event)"/>

</mx:Panel>

</mx:Application>


php class’ındaki fonksiyondan geriye dönen değerler Responder clasından tanımladığımız nesnenin result olayına atadığımız fonksiyona parametre olarak döner. Yani yukarıdaki iki örnekte de eğer fonksiyon bir değer döndürüyorsa

private function postSuccessHandler(result:Object):void{

fonksiyonundaki result bu dönen değeri alabilir. result ismi ile tanımladığımız nesne illaki Object olmak zorunda değildir. php class’ından hangi türde değer dönüyorsa ona göre ihtiyaç duyduğunuz tipte tanımlayabilirsiniz.

No comments:

Post a Comment

Followers