28 May

WSDL Soap Web Servis Karmaşası

Bu konu üzerine bir iki yazım oldu. Ama gelen aramalardan ve sorulardan görebildiğim kadarı ile çok fazla karmaşa hakim. Olayı basite indirgemek için tüm terimleri özetlemeye çalışacağım.
Web Servis : Farklı veya aynı platformlar arasında; örneğin php ile yazılmış web uygulamanızın asp.net uygulaması ile iletişim kurabilmesi web servis ile mümkündür.
İki farklı dil, iki farklı platform. Peki iletişim nasıl mümkün olacak. Her ikisinin de aynı dili konuşmasını nasıl sağlayacağız.
Burada devreye SOAP girmektedir. Açılımı “Simple Object Access Protocol” dur. SOAP’ı bir kurallar bütünü olarak tanımlayabiliriz. PHP ile ASP.NET’in konuşabilmesi için SOAP’ın koyduğu kurallara uygun hareket etmeleri gerekiyor. Bu kuralları burada açmayacağım, amacım sadece kavram karmaşasını bir nebze azaltmak.

SOAP’ı kurallar bütünü olarak tanımladık, bu kuralların yazılı olması gerekiyor ki kalıcı olsun :) İşte bu yazılı kurallara da WSDL diyebiliriz. WSDL iki platform arasında iletişimi SOAP protokolü ile sağlar. SOAP protokolüne uygun olarak, gönderilecek komutların tanımlanmasını da WSDL sağlar.

WSDL alan istemci (client) , hanki interface’e sahip olduğunu. Bu interface’de hangi fonksiyon ve metodları bulunduğunu bilir ve buna göre karşı tarafa istek yapabilir.

1
$istemci= new SoapClient("http://sunucu.com/kurallar.wsdl");

Yukarıdaki satırın yorumu şudur : Gidip sunucu.com dan wsdl dosyasını al ve yönergelere göre kullandığım dile uygun hale getir. Eğer wsdl içerisinde listele gibi bir metod tanımlanmış ise :

1
$istemci->listele();

Şeklinde kullanabilirsiniz. WSDL ile hangi metodların,fonksyionların olduğu. Hangi parametreleri alabileceği, parametrelerin tipleri. Zorunlu olup olmadıkları gibi kuralları WSDL ile belirlersiniz. Bu belirlenen kurallar sunucu ve istemi tarafında yorumlanarak iletişim sağlanır.

Webden aşina olduğumuz HTTP bir protokoldür ve bu protokole göre browser ile sunucu anlaşmasını sağlar. Browserın neyi nasıl görüntüleyeceğini de HTML ile belirleriz.
SOAP ile WSDL bağlantısı da bu şekildedir. SOAP iletişimin nasıl yapılacağını belirten protokol, WSDL de iletişim kuracak sistemlerin nasıl davranmaları gerektiğini tanımlayan kural listesidir.

Web servis, SOAP ve WSDL kavramlarını bu düzleme indirdikten sonra ayrıntılandırırsanız anlaşılması daha kolay olur diye düşünüyorum.

Peki , html çok kolay oluşturuluyor ve Html yorumlamayı browser yapıyor. Ben WSDL’i nasıl oluşturacağım ve SoapClient’a nasıl yorumlatacağım :(

Web servis iletişiminde WSDL birkez oluşturulur ve gerekmedikçe değiştirilmez ve sadece hizmeti verecek taraf, yani server tarafı sorumludur bu işten. Genelde WSDL’i elle oluşturmak için kurduğunuz server tarafının otomatik olarak üretilmesini sağlayacak araçlar kullanılır. WSDL’i elle sıfırdan oluşturmak karmaşıktır.
Bu yüzden istemci tarafından bakarak, istemci tarafnda bize ne gibi bir görev düştüğüne bakalım.

Size web servis ile iletişim kuracağınız ve WSDL adresi verildiğinde “eyvah, ben ne yapacağım!” demenize gerek yok. İlk yapmanız gereken, mümkünse web servisi yazan kişi-kurum ile iletişim kurarak döküman rica etmeniz. Çünkü WSDL kuralları okunabilen , kısmen okunduğu kısmı ile anlaşılabilen bir yapıya sahip olsa da, hangi fonksiyonu ne zaman nerede kullanacağınızı ancak dökümantasyondan öğrenebilirsiniz.

İstemci tarafısınız, WSDL’i ve dökümanı aldınız, okudunuz ve anladınız. Bundan sonra yapmanız gereken tek şey SoapClient nesnesine gerekli parametreleri vererek istediğiniz şeyleri yapmasını sağlamanız :

1
2
3
 $client = new SoapClient("http://test-sunucusu.com/komut-tanimlamalari.wsdl"); // wsdl dosya isimlendirmesi tamamen uydurmadır, bir zorunluluk yoktur isimlendirmede
$parametre = array("a"=>1,"b"=>2);
$client->buFonksiyonWsdlDeTanımlı($parametre);

Yukarıdaki örnekde WSDL içerisinde buFonksiyonWsdlDeTanımlı diye bir fonksiyon olduğunu, bu fonksiyonunda bir array aldığını anlıyoruz.

Umarım daha fazla kavram karmaşasına sebep olmamışımdır.
Sorularınız için konu altına yorum bırakabilirsiniz.

25 Mar

Nasıl bir bilgisayar almalıyım ?

Daha öncekilerin aksine bu seferki yazmaya çalışacağım konu yazılım ile ilgili değil.
Bu defa amacım, çokca maruz kaldığım bir soruya, kendi görüşlerim doğrultusunda, basite indirgeyerek bir bakış açısı oluşturabilmek.
Bilgisayar alacaksınız, çok fazla işlem gücüne ihtiyacınız yok. Ve ne tür bir cihaz alacağınızı bilmiyorsanız bu yazı sizin içn yararlı olabilir.
Nasıl bir bilgisayar almalıyım sorusuna cevap arayışım dizüstü bilgisayar çevresinde olacak. Masaüstü bilgisayar için kendinize sormanız gereken soru : “Evde sabit olarak konumlandıracak bir yerim var mı ?”. Bu sorunun cevabı sizin için evet ise Masaüstü bilgisayar seçeneğini değerlendirebilirsiniz, dizüstü bilgisayardan daha konforlu bir çalışma ortamı sunar size.

Dizüstü bilgisayarlar fiyatlarından dolayı pek tercih edilebilir durumda değildi. Fakat zamanla bu engel ortadan kalktı ve her bütçeye uygun bir seçenek bulmak kolaylaştı. Bu sefer de zorluk, kullanıcıların hangi modeli, markayı, ne tür özelliklerde bir cihazı alacaklarını bilememeleri oldu (çevremden gözlemleyebildiklerimden çıkardığım sonuçtur). Bunun içi bilinen en geleneksel yöntem, çevresindeki bilgisayar ile en çok haşır neşir olan kişiye danışmak.

“Bunca şey yazdın, daha dişe dokunur birşey yok”. Tamam, başlayayım. Konuyu örnekleyecek en iyi şeyin baklava olduğunu düşünüyorum.Ne alaka mı? Şöyle ki, baklavayı oluşturan malzemeler bellidir. Temel malzemeleri un,su,şeker,yağ olmaksızın baklava yapabilmek mümkün değildir. Bu yüzden baklavalar arasında farklılaşmalar ustaların maharetine, içerisine eklenen bazı lezzet verici şeylere göre oluyor ( baklava uzmanıymış gibi yazmayayım :) sadece örnek vermeye çalışıyorum :), sürçü lisan edersem affola )
Bilgisayar da bu şekilde, bir bilgisayarı oluşturan temel malzemeler bellidir ve bu malzemelerin kullanımından kaçmak mümkün değildir.
Burdan ulaşmaya çalıştığım sonuç şu: Markaların hepsi aynı temel bileşenleri kullanarak bilgisayarları oluştururlar.
Nasılki baklavayı yapan usta suyu kendi üretmiyor ise, bilgisayarı üreten üreticilerin çoğu bilgisayar bileşenlerinden işlemciyi kendi üretmiyor.
Şimdi gelelim ayrışma kısımlarına(malzeme kalitesi kısmına hiç girmiyorum). Bilgisayar almaya karar verirken öncelikle ne kadar bütçe ayırabileceğinizi belirleyin. Birçok kullanıcı biraz fazla para vereyim en iyisi olsun, çok uzun süre kullanayım diye yaklaşıyor konuya.
Bilgisayar denilen cihaz, en çok parayı dökseniz bile belirli bir süre sonra ihtiyaçlarınızı gideremez ya da beğeninize hitap edemez hale gelecektir. Bu hem teknolojideki gelişmelerden hem de bu sektörün ürünlerini satabilmek için kullanıcılara kurduğu kurnaz tuzaklardan kaynaklanıyor. Bu yüzden en pahalısı en iyisdir fikrini bir kenara bırakın.
Bir diğer ayrım noktası, markanın teknik servis hizmetine ve müşteri hizmetlerine erişiminizin kolaylığı. Bu çok önemli bir konu, elektronik cihazlarda çıkabilecek sorunları önceden kestirebilmek mümkün değil. En iyi markanın en pahalı ürünü de arızalanabilir. Bunu göz önünde bulundurarak alacağınız cihazın teknik servis imkanlarını, bu hizmete kolay ulaşıp ulaşamadığınızı kontrol etmeye çalışın.
Bir diğer ayrım noktası cihazın görünümü. Bu konu ilk başta sizin için çok önemli görünmüyor olasa da aslında kullanımınızı etkileyen bir faktör. Çünkü sürekli bu cihaz ile çalışacaksınız ve her zaman gözünüzün önünde olacak. Göz estetiğinize hitap etmeyen cihaz olması gerekenden daha kısa sürede beğeninize hitap etmez hale gelebilir.

Gelelim teknik ayrıma. Bu ayrımı bu yazıya sığdırabilmek pek mümkün değil, birkaç ayrım noktasına değinmeye çalışacağım.

İşlemci : Genelde Intel veya AMD diye görürsünüz bilgisayar bileşenlerini açıklamalarında. Bunlar üreticilerdir, bir de bu üreticilerin i3,i5,i7,A10,E,Atom,A4 vb gibi modelleri vardır. Eğer 3D modelleme, autocad,photoshop,video düzenleme vb gibi çok fazla işlem gücüne gerek duyan programlar kullanmayı düşünmüyorsanız çok fazla dikkat etmeniz gerekmez.
Bu bileşenlerin yanında ayırca 2.25MHZ, 1.75MHZ gibi ibareler görürsünüz. Bu işlemcinin çekirdek hızını gösteren ve tek başına bilgisayarın hızını etkilemeyen birşeydir. Bu yüzden size işlemci çekirdek hızı bu kadar hızlı, şu kadar hızlı diye övmelerini çok önemsemeyin. Ama eğer yukarıda belirttiğim program-işlemler üzerine çalışıyorsanız birazcık dikkate alabilirsiniz. Çünkü bu uygulamalar çok fazla matemeaitksel işlem yapar ve bu işlemleri de işlemci yapar.
RAM : RAM önemli bir konu, işlemci çalışırken bazı şeyleri aklında tutması gerekir. Bir işlemin sonucunu aklında tutarki bir daha istediğinizde, o sonucu bulabilmek için yaptığı işlemi tekrar yapmayıp size istediğiniz sonucu hızlıca verebilsin. Bu parçanın kapasitesini bilgisayar özelliklerinde GB (Gigabayt) olarak geçer ve genelde 2GB olarak görünüyor en minimum değerler. Ama ben en az 4GB RAM tavsiye ederim.
Ekran Kartı: Ekran kartı çok göreceli bir kavram. Normalde yukarıda belirttiğim şekilde, çok fazla işlem gücünde ihtyiaç duymuyor iseniz, bir iki ufak oyun oynayıp, film izleyip, ofis programları kullanıp internette geziniyorsanız bu bileşenin özelliğini çok fazla dikkat etmenize gerek yok. Ama dikkat etmek istiyorsanız “Harici” olarak belirtilen modeli tercih ediniz. Harici ekran kartı, bilgisayarın ana kartında veya işlemci içerisinde bulunmayan tek görevi ekran ile ilgili işlemleri yapan bir bilgisayar bileşenidir.
Eğer temel bilgisayar kullanımının üstüne çıkan bir kullanıcı iseniz harici bir ekran kartını ve 2GB veya üzeri değere sahip modeli tercih etmeye özen gösteriniz.
En son değinmek istediğim bileşen ise Harddisk’tir. Harddisk, bilgisayara depoladığınız fotoğraf,müzik, döküman vb birçok dosyayı saklamanızı sağlayan önemli bileşenlerden biridir. Bu bileşenin değeri GB veya TB olarak görürsünüz. TB, GB dan büyüktür. 600GB, 750GB, 1TB gibi ibareler görürsünüz. Bunlar ne kadar yüksek ise kayıt alanınız o kadar çok olur.
Eğer ciddi anlamda performanslı bir bilgisayar arıyorsanız, sadece SSD türünde bir harddisk içerip içermediğine dikkat etmeniz yeterli olur.
Çünkü SSD içeren bir cihazın bileşenleri de harddiske paralel olarak iyi seçiliyor. Ama SSD türünde harddisk içeren cihazların fiyatları yüksek olmakta. Çok fazla işlem gücüne ihtiyaç duymuyorsanız dikkate almayınız SSD olup olmamasını.

Yukarıda temel ayrım noktalarını yazmaya çalıştım. Şimdi de seçim sürecinin nasıl olması gerektiğini maddeler halinde belirleyelim :
– Bütçeyi belirle
– Hangi markanın servisinin ve müşteri hizmetlerinin daha ulaşılabilir olduğunu bulmaya çalış
– Görsel olarak sana hitap etmesine dikkat et
– Yukarıda yazdığım temel bileşenleri, kendi ihtiyaçlarına göre kombine et ve filtrelemek için hangi bilgisayar bileşenine veya bileşenlerine önem vermen gerektiğine karar ver. Bu karara göre bir seçim listesi oluştur
– Oluşturduğun listeyi fiyat/performans oranına göre kafanda filtrele ve en az seçenek kalıncaya kadar devam et
– Kafanda en çok olgunlaşan model için fiyat araştırması yap
– Sonrası sana kalmış :)
Bilgisayar alımında dikkat ettiğim noktaları özetleyerek anlatmaya çalıştım. Umarım alacağın bilgisararın seçiminde katkım olur 😉

29 Mar

Sayfa Kodlaması Ne İşe Yarar Ki ?

Buraya eklediğim örnekleri mümkün olduğuca test etmeye çalışıyorum. Fakat, yine de hatanın önüne geçmek mümkün olmuyor.
Bloğumu ziyaret eden Mehmet SEVEN’den mail aldım. http://www.ersindogan.com/php-web-programlama/wsdli-nasil-okuyabiliriz adresindeki makaleyi okuduğunu, fakat ekteki örnek dosyaları çalıştıramadığını ve şöyle bir hata aldığını yazmıştı (Burdaki dosya yolları kendi bilgisayarımın yollarıdır) :

Fatal error: Uncaught SoapFault exception: [HTTP] Not Found in /home/dev/hosts/Workspace/WebServices/istemci.php:4 Stack trace: #0 [internal function]: SoapClient->__doRequest(‘__call(‘EchoTest’, Array) #2 /home/dev/hosts/Workspace/WebServices/istemci.php(4): SoapClient->EchoTest(‘Ersin’, ‘DOGAN’, ‘Merhaba Dunya’) #3 {main} thrown in /home/dev/hosts/Workspace/WebServices/istemci.php on line 4

Biraz kurcaladıktan sonra, wsdl içerisinde bulunan endpointURI (servis çağrılarının yapıldığı adresin) eksik olduğunu fark ettim :

Eksik Hali
http://localhost/Workspace/WebServices/
Doğru Hali
http://localhost/Workspace/WebServices/sunucu.php

Bu şekilde http://localhost/Workspace/WebServices/ çalışabilmesi için, sunucu.php dosyası içerisindeki kodun index.php dosyası içerisinde olması gerekirdi.Her ne kadar adı sunucu olarak da geçse, kendisi apache web suncusu olmadan çalışamayan bir php dosyasıdır. Bu yüzden adresleri bu durumu göz önünde bulundurarak oluşturmak gerekiyor.

Bunu düzelttikten sonra hatadan kurtulmak mümkün olmadı ama aldığım hata değişti :

Fatal error: Uncaught SoapFault exception: [Client] looks like we got no XML document in /home/dev/hosts/Workspace/WebServices/istemci.php:4 Stack trace: #0 /home/dev/hosts/Workspace/WebServices/istemci.php(4): SoapClient->__call(‘EchoTest’, Array) #1 /home/dev/hosts/Workspace/WebServices/istemci.php(4): SoapClient->EchoTest(‘Ersin’, ‘DOGAN’, ‘Merhaba Dunya’) #2 {main} thrown in /home/dev/hosts/Workspace/WebServices/istemci.php on line 4

Bu, sunucu.php dosyasında birşeylerin yanlış gittiğini gösteriyor. Normalde, sunucu.php dosyası kodu çalıştırdıktan sonra geriye cevap olarak XML dosyası göndermekte. Hatanın sebebini bulmak için kodu birazcık güncelledim :

$istemci=new SoapClient(‘test.wsdl’,array(‘trace’=>1));
try{
echo $istemci->EchoTest(‘Ersin’,’DOGAN’,’Merhaba Dunya’);
}catch(Exception $e){
echo ‘‘,$istemci->__getLastResponse(),’‘;
}

Ve asıl hatamıza ulaştık :

Fatal error: SOAP-ERROR: Encoding: string ‘Merhaba Ersin DOGAN Mesaj\xfd…’ is not a valid utf-8 string in /home/dev/hosts/Workspace/WebServices/sunucu.php on line 10 Call Stack: 0.0002 333680 1. {main}() /home/dido/hosts/Workspace/WebServices/sunucu.php:0 0.0006 340284 2. SoapServer->handle() /home/dev/hosts/Workspace/WebServices/sunucu.php:10

sunucu.php dosyasını incelediğimde (file -i sunucu.php komutunu çalıştırarak):

1
sunucu.php: text/x-php; charset=iso-8859-1

dosyanın kodlamasının iso-8859-1 olduğunu gördüm. SoapServer varsayılan olarak utf8 ayarlı olduğu için, dosya içeriğinin ISO-8859-1 kod seti ile oluşturulmuş olması, sunucu.php dosyasının bu kod setinin desteklemediği karakterler ile karşılaşmasından dolayı hata vermesine sebep oluyormuş. Bunu çözmek için komut satırından :

1
iconv -f ISO-8859-1 -t UTF-8 sunucu.php>sunucu_utf8.php

çalıştırıp, işlem başarı ile tamamlanınca sunucu.php dosyasını silip, sunucu_utf8.php dosyasını da sunucu.php olarak yeniden adlandırmak tüm sorunlarıma çözüm oldu.

Eğer linux kullanmıyorsanız, kodlar için yeni dosyalar açıp, kodları bu yeni dosyalara yazmanız ( kopyala yapıştır yapmadan) da sorununuzu çözecektir.

Bu ilginç hata ile, hatalı dosya kodlamasının başa ne dert açabileceğini görmeme sebep olduğu için Mehmet SEVEN arkadaşa da burdan teşekkür etmek isterim :)

25 Mar

Flash videoların kopyalanması

Sanırım linuxda olmanın bir handikapı, bazı şeyleri daha zor yollardan yapmanız gerekiyor. Eğer firefox eklentisi kullanmıyorsanız ya da yoksa böyle bir eklenti, izlediğiniz flash videoları bilgisayarınıza indirmeniz uğraşıtırıcı.

Gerçi önceden kolaydı (ubuntu 10.10 dan önce) , izelenen tüm flash videolar /tmp klasörü içerisine kopyalanıyordu. Videonun bulunduğu sayfayı kapadığınızda da, /tmp den siliniyordu. Flash videonun penceresini kapamadan, /tmp klasöründen alıp istediğiniz yere kopyalayabiliyordunuz.

Bu kolay adımlar bazılarının canını sıkmış sanırım, bu yüzden artık izlenen flash videolar tmp dizininde bulunmuyor. Bunun yerine /proc dizini altında, çalışan eklentinin process id si altındaki fd dizini içerisinde bulunan ilgili numaradaki dosya olarak bulunabiliyor :)

Şunun gibi yani (“lsof -n|grep Flash” komutunun çıktısı):

1
plugin-co 2535     ersin   16u      REG                8,1  5463336   12058865 /tmp/FlashXXcGtmnF (deleted)

Bunu bir arkadaştan öğrendim, lsof (açık olan tüm uygulamaların kullandığı dosyaları listeliyormuş) ile bu bilgilere ulaştıktan sonra geriye bu dosyayı kopyalamak kalıyordu :

1
cp /proc/2535/fd/16 ~/flash_dosyasi.flv

Bu yöntemin dez avantajı hangi dosyanın hangi video olduğunu bilmemeniz. Bu yüzden birden fazla flash video izliyorsanız, bunun takibini ve ayrımını yapmak tamamen size kalıyor.

Uzun sözün kısası şu, burda izlediğim adımları otomatize etmek için küçük bir php scripti yazdım, konsoldan çalışan. Bunu da burdan paylaşmak istedim :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/usr/bin/php
<?php
/**
 * Flas dosyalarını kopyalayabilmek için oluşturulacak Ui için ortak yapı
 * @author ersin
 *
 */

abstract class  Ui {
   /**
    *
    * Fla listesini tutar
    * @var array
    */

   protected $listArray;
   /**
    *
    * Komut çıktısını tutar
    * @var string
    */

   protected $list;
   /**
    *
    * Sistemde olan açık fla dosyalarının listesini dödnüdür
    */

   protected function listOpenFlas(){
      $this->list =`lsof -n|grep Flash`;
      $this->listArray = explode("\n",$this->list);
      array_pop($this->listArray);
   }
   /**
    *
    * Komut çıktısını ayrıştırarak fla dosyasına erişebilmeyi
    * sağlayan değerleri döndürür
    *
    * @param string $data
    */

   protected function parseFla($data){
       $res = array();
       $match = array();
       preg_match_all('/\d{1,}/',$data, $match);
       if(count($match)==0) {
       return false;
       }
   
       $res['pid'] = $match[0][0];
       $res['itm'] = (int)$match[0][1];
       return $res;
    }
   /**
    *
    * Fla dosyasının kaydedilmesini sağlar
    * @param integer $index
    * @param string $savePath
    */

   protected function saveFile($index,$savePath){
      @$file = $this->listArray[$index];
     
      if(!($fla  = $this->parseFla($file))){
         echo "\nFlash dosyası ayrıştırılamadı\n";
         return false;
      }
     
      $source ='/proc/'.$fla['pid'].'/fd/'.$fla['itm'];
         $res =`cp $source $savePath>&1`;
      if(null === $res) {
         echo "\nDosya aktarım işlemi başarılı ile sonuçlandı\n";
      }else {
         echo "\n\033[01;31mHata\t:\t\033[0m".$res."\n";
      }
   }
   /**
    *
    * Ortak başlatıcı
    */

   public function start(){}
}
/**
 *
 * Consoleda çalışan Ui
 * @author ersin
 *
 */

class ConsoleUi extends Ui {
   /**
    *
    * Conseole menü çıktısını verir
    */

   private function print_menu(){
      $msg= "\n\033[35;1m Seçenekler :\033[0m \n".
      "\033[01;31m(1)\t:\033[0m Flash Dosya Listesi\n".
      "\033[01;31m(2)\t:\033[0m Flashı farklı kaydet\n".
      "\033[01;31m(3)\t:\033[0m Çıkış\n".
      "\n\033[01;31mBir Seçenek Numarası Girin :\033[0m";
      return $this->prompt($msg);
   }
   /**
    *
    * Fla dosyalarının liste çıktısını verir
    */

   private function listMenu() {
      if(count($this->listArray)>0) {
         echo "\n\t\tŞu an açık olan flash dosyaları\n",
         $this->list;
      }else {
         echo "\nAçık flash dosyası bulunamadı\n";
         return false;
      }
   }
   /**
    * (non-PHPdoc)
    * @see Ui::listOpenFlas()
    */

   public function listOpenFlas(){
      parent::listOpenFlas();
      $this->listMenu();
   }
   /**
    *
    * Console dan parametre almamızı sağlar
    * @param string $message
    * @return string
    */

   private function prompt($message,$trim=true){
      echo $message;
      $input = fopen('php://stdin','r');
      $value = fgets($input);
      fclose($input);
      if($trim) {
         return trim($value);
      }else {
         return $value;
      }
   }
   /**
    *
    * Karar mekanizması
    * @param int $choice
    */

   private function makeAction($choice){
      switch($choice){
         case 1:
            $this->listOpenFlas();
            break;
         case 2:
            if(count($this->listArray)==0){
               if($this->prompt("\nListe boş görünüyor, tekrar kontrol edilsin mi? [e/h]")=="e"){
                  if(!$this->listOpenFlas()) return false;
               }else { return false;}
            }
            $fileChoice = $this->prompt("\nDosya indeksini girin(0 dan başlayarak) :");
            $savePath   = $this->prompt("\nDosyanın kaydedileceği yolu girin :");
            $this->saveFile($fileChoice,$savePath);
            break;
         case 3:
            exit(0);
            break;
         default :
            var_dump($choice);exit;
      }
   }
   /**
    * (non-PHPdoc)
    * @see Ui::start()
    */

   public function start(){
      while(true){
         $choice = $this->print_menu();
         $this->makeAction($choice);
      }
   }
}

$console = new ConsoleUi();

$console->start();

GTK destekli sürümünü de yapmak istediğimden, bunu yapabilecek şekilde düzenledim. Belki sizin de aklınıza farklı birşeyler gelir siz de ekleme yaparsınız,basit kullanışlı bir araç çıkar ortaya :)

09 Mar

Sphinx?in Ayarlanması ve Kullanımı

Önceki yazılarda sphinxin ne olduğunu açıklamaya çalışmıştım. Kısaca özet geçmek gerekirse, sphinx, bağımsız çalışan bir arama motorudur. Çok fazla veri içeren veritabanbları için , hızlı ve kolay, metin bazlı arama yapabilmek için kullanılabilecek bir uygulamadır.

Sphinxi paylaşımlı hostinglerde kullanabilmek pek mümkün olmaz sanırım. Çünkü sphinxi kullanabilmek için, sphinx sunucusu ve phpye has sphinx eklentisini kurmak gereklidir. Bunların haricinde, arama sunucusunun belirli aralıklarla çalışarak verileri yeniden indekslemesi gerekmektedir. Tüm bu ve buna benzer durumlardan ötürü, sphinxi sadece kendinizin yönetebildiği sunucularda kullanabileceğinizi unutmayın.

Şimdi gelelim sphinxin nasıl kullanılacağına. Bunun için sphinx ile birlikte gelen örnek veritabanını ve konfigürasyon dosyalarını kullanacağım.

Kurulumu tamamladıktan sonra, kurulum yaptığınız dizin altında bulunan etc kalsöründe (kendi bilgisayarımda sphinxi /opt/sphinx altına kurduğum için, /opt/sphinx/etc dizinini kullanacağım) bulunan example.sql dosyasını açarak başına kullanmak istediğimiz veritabanını ekleyelim:

CREATE DATABASE IF NOT EXISTS test;
use test;

Sonrasında :

1
mysql -u kullanici_adi -psifre<example.sql

komutunu çalıştırarak örnek veritabanını oluşturuyoruz. Bir sonraki adım ayar dosyasını oluştrumak. Yine aynı klasörde bulunan (/opt/sphinx/etc) sphinx.conf.dist sphinx-min.conf.dist dosyaları ile, tüm ayarları sıfırdan yapmak yerine. Varsayılan olarak gelen ayarları kullanıp veya düzenleyebiliriz. Varsayılan ayarlar her zaman işimize yaramaz, ama kendisi ile gelen örnek veritabanı ile uyumlu. Çok fazla karmaşaya sebep olmamak için en basit ve kısa olan ayarını kullanacağım :

1
sudo cp sphinx-min.conf.dist sphinx-test.conf

Yukarıdaki komutu çalıştırdığımızda, birlikte gelen ayar dosyalarından, sphinxin çalışabilmesi için gerekli olan minimum ayarların bulunduğu dosyayı, kendi ihtiyaçlarımız için düzenleyebileceğimiz ayrı bir dosya olarak kaydettim. sphinx-test.conf dosyasının içeriği aşağıdaki gibidir: (sphinx verisyonuna göre değişiklik gösterebilir)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#
# Minimal Sphinx configuration sample (clean, simple, functional)
#

source src1
{
   type        = mysql

   sql_host    = localhost
   sql_user    = test
   sql_pass    =
   sql_db         = test
   sql_port    = 3306   # optional, default is 3306

   sql_query      = \
      SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
      FROM documents

   sql_attr_uint     = group_id
   sql_attr_timestamp   = date_added

   sql_query_info    = SELECT * FROM documents WHERE id=$id
}


index test1
{
   source         = src1
   path        = /opt/sphinx/var/data/test1
   docinfo        = extern
   charset_type      = sbcs
}


index testrt
{
   type        = rt
   rt_mem_limit      = 32M

   path        = /opt/sphinx/var/data/testrt
   charset_type      = utf-8

   rt_field    = title
   rt_field    = content
   rt_attr_uint      = gid
}


indexer
{
   mem_limit      = 32M
}


searchd
{
   listen         = 9312
   listen         = 9306:mysql41
   log         = /opt/sphinx/var/log/searchd.log
   query_log      = /opt/sphinx/var/log/query.log
   read_timeout      = 5
   max_children      = 30
   pid_file    = /opt/sphinx/var/log/searchd.pid
   max_matches    = 1000
   seamless_rotate      = 1
   preopen_indexes      = 0
   unlink_old     = 1
   workers        = threads # for RT to work
}

Sphinxi hızlıca ayarlayabilmek için yapmanız gereken, bir source, bir index ve searchd ayarının tanımlı olması gerekiyor.

source : Arama yapılmasını istediğnizi veritabanına ve tabloya yapılacak bağlantı ve sorgunun tanımlaması burada yapılır. Sphinx bu ayar yardımı ile , veritabanına bağlanır, ilgili tabloadan verileri çeker ve indexler. Böylece sphinxe bir arama sorgusu gönderdiğinizde size sonuç döndürebilir. Burada veritabanına bağlanmak için gerekli parametrelerin nasıl verilmesi gerektiğini açıklamama grek yok sanırım. Ayar anahtarları gayet açıklayıcı duruyor. Ayar dosyası içeirisinde birden fazla source tanımlanabilir.

Burda üstünde duracağım ayar anahtarı “sql_query”. Buraya, indekslenmesini istediğiniz verileri elde edebileceğiniz sorguyu yazmalısınız. Sphinxin size dayattığı en belirgin kural, bu sql sorgusunun en az bir “id” alanı içermesidir. Bunun haricinde SQLinizi istediğiniz gibi yazabilirsiniz.

Sphinx ayar dosyasında mutlaka dikkat etmeniz gereken bir diğer husus ise, yeni bir satıra geçmek istiyorsanız satır bitimine \ karakteri eklemeniz gerektiğidir. Eğer buna dikkat etmezseniz sphinx ayar dosyasını ayrıştırıken hata verecek ve çalışmayı durduracaktır.

sql_attr_ ile başlayan ayar anahtarı, aramanız üzerinde filtreleme yapabilmeniz için kullanabileceğiniz alanları tanımlamanızı sağlar. Bu tanımlamalar, sorgu yaptığınız tablo üzerindeki alanlardan biri olmalıdır. sql_attr_ den sonra, ilgili alanın tipini belirtmelisiniz ( örneğin sql_attr_timestamp = date_added , sorgu yaptığınız tablo üzerinde timestamp tipinde date_added alanını temsil eder). Daha fazla ayrıntı için sphinx dökümantasyonunda “Data source configuration options” başlığına bakınız.

sql_query_info yu es geçebilirsiniz.

index : Bu başlıkta , sphinxin verileri nasıl indekslemesi gerektiği belirtilir. Ayar dosyası içerisinde birden faxla index başlığı olabilir ve bu index başlıklarını kod tarafında arama yaparken seçebilir ve istediğiniz indeks üzerinde arama yaptırabilirsiniz. Ayar dosyasında mutlaka bir index olmak zorundadır. index bir source a sahip olmalıdır. “index test1″ başlığı altında tanımlanmış örnekte görüldüğü gibi , bir source tanımlanmış, index verilerilerinin nerede saklanması gerektiği belirtlimiş (path= /opt/sphinx/var/data/test1). docinfo ve charset_type ı es geçiyorum, bunlarla ilgili daha fazla bilgiyi sphinx dökümantasyonunda bulabilirsiniz. Basit bir ayar için belirttiğim iki anahtar yeterlidir. searchd de bulunan ayarları değiştirmenize gerek yok şimdilik.

Yukarıdaki ayar dosyasında gerekli ayarları yaptıktan sonra, sphinxin gerekli dataları oluşturmasını sağlamaktır. Bunun için:

1
sudo /opt/sphinx/bin/indexer --all --config /opt/sphinx/etc/sphinx-test.conf

Yukarıdaki kod ile, ayar dosyamızdaki direktiflere göre veriler indexlenecek. Eğer bir problem olmaz ise, aşağıdaki gibi bir çıktı alırsınız :

1
2
3
4
5
6
7
8
9
10
11
12
13
Sphinx 1.11-dev (r2709)
Copyright (c) 2001-2011, Andrew Aksyonoff
Copyright (c) 2008-2011, Sphinx Technologies Inc (http://sphinxsearch.com)

using config file '/opt/sphinx/etc/sphinx-test.conf'...
indexing index 'test1'...
collected 4 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 4 docs, 193 bytes
total 0.036 sec, 5290 bytes/sec, 109.64 docs/sec
skipping non-plain index 'testrt'...
total 3 reads, 0.000 sec, 0.1 kb/call avg, 0.0 msec/call avg
total 9 writes, 0.000 sec, 0.1 kb/call avg, 0.0 msec/call avg

Örnek veritabanında çok fazla veri olmadığı için indeksleme işlemi çok kısa sürede tamamlandı. Şimdi sıra geldi arama sunucusunu çalıştırmaya :

1
sudo /opt/sphinx/bin/searchd --config /opt/sphinx/etc/sphinx-test.conf

Bunu çalıştırdığınızda aşağıdakine benzer bir sonuç alırsınız :

1
2
3
4
5
6
7
8
9
10
Sphinx 1.11-dev (r2709)
Copyright (c) 2001-2011, Andrew Aksyonoff
Copyright (c) 2008-2011, Sphinx Technologies Inc (http://sphinxsearch.com)

using config file '/opt/sphinx/etc/sphinx-test.conf'...
listening on all interfaces, port=9312
listening on all interfaces, port=9306
precaching index 'test1'
precaching index 'testrt'                                  
precached 2 indexes in 0.001 sec

Yukarıda çalıştırmış olduğumuz kod, arama sunucumuzun çalışmasını sağlar, böylece bizde arama sunucusuna sorgu göndererek arama işlemini gerçekleştirebiliriz.

Sphinx sunucumuzu ayarlayıp çalıştırmış olduk. Burda bahsettiğim /opt/sphinx klasörü kendi bilgisayarıma özgü bir yoldur. Siz nereye kurulum yaptı iseniz o dizini referans alınız.

Şimdi sphinxi ayarladık ve çalıştırdık, bitti mi ? Tam olarak bitti denemez, veritabanınıza sürekli veri ekleneceği için sphinx indekslerinin yenilenmesi gerekir. Bunun için de belirli aralıklarla :

1
/opt/sphinx/bin/indexer --all --rotate --config /opt/sphinx/etc/sphinx-test.conf

bu kodun çalışması gerekmektedir. Bu kod, indekslerin yenilenmesini sağlar. Bunu bir cron job olarak çalıştırabilirsiniz. Bu işlemin sıklığı ihtiyaçlarınıza göre değişir. Günde bir defa da yaptırabilirsiniz, dakikada bir de yaptırabilirsiniz. Bu tamamen size kalmış ( veritabanın büyüklüğü de rol oynuyor tabiki). Eğer yeniden indeksleme yapmazsanız, yeni girilen kayıtlar arama sonuçlarında çıkmaz.

Sunucunuzu ayarlayıp çalıştırdıktan sonra, buradaki örnekte olduğu gibi arama işlemi yapabilirsiniz.

Sphinx, çok fazla ayrıntıya sahip olan bir arama motoru sunucusudur. Burda aktarmaya çalıştıklarımdan daha fazlasını sphinx dökümantasyonunda bulabilirsiniz. Gayet anlaşılabilir bir dil ile örnekleyerek anlatmakta.

Bu seriye ait diğer yazılar :

Metin Bazlı Arama – Site İçi Arama Motoru
Aramanın Yapılması – Site İçi Arama Motoru
Sphinx nedir ?
Sphinx Kurulumu
Sphinx?in Ayarlanması ve Kullanımı

09 Feb

Sphinx nedir ?

MySQL 5.0 sürümünden itibaren güzel bir özellik sundu : fulltext search. Bu özellik sayesinde, veritabanındaki bir tablonun,istenilen alanları (fulltext indeksi eklenmiş alanlar) üzerinde metin bazlı arama yapabiliyoruz.

Fulltext search sadece MyISAM tipindeki tablolar üzerinde çalışabilmekte. Ayrıca çok da performanslı olduğu söylenemez.

Performans haricinde arama sırasında da çok da esnek olmayan bir yapısı var.

İşte burada Search Engine Server ( Arama motoru sunucusu) devreye giriyor.

Bu arama motrolarının yaptığı şey, veritabanından bağımsız çalışarak, verilerin, veritabanından belirli aralıklarda çekilerek indekslenmesi. Sonrasında da kendine gelen arama sorguları esnasında, indekslenmiş kayıtlar içerisinden sonucu kısa sürede vermek.

MySQL Fulltext Search de süreç şu şekilde olur:

Fulltext indeksi eklenmiş tablodaki alan üzerinde sorgu çalıştırılır :
SELECT * FROM articles
-> WHERE MATCH (title,body) AGAINST (‘database’);
Çıkan sonuçlar direkt olarak kullanılır.

Arama motoru sunucusundaki süreç de şöyle işler :

– Arama motoruna bağlatı yapılır
– Aranan kelime iletilir
– Aranan kelimenin bulunduğu kayıtların ID lerinin bulunduğu sonuçlar geri döndrülür
– Arama motoru sonuçları (eğer sonuç döndüyse) ayıklanarak veritabanından ilgili kayıtlar ID lerine göre çekilir.

Arama motoru ile ilgili işlem adımları daha çok görünse de,mysql fulltext search den daha hızlı sonuç alabilmekteyiz.

Burda bilinmesi gereken bir şey daha var, arama motoru sunucsu belirli aralıklarla veritabanına bağlanarak verileri yeniden indekslemek zorundadır. Yani üzerinde arama yapılan tabloya yeni veriler girilmiş veya mevcut veriler değişitirilmiş ya da silinmiş olabilir. İşte bu yüzden bir cron job ile , arama motorunun yeniden indeksleme yapması sağlanmalıdır. Bu indeksleme ve yeniden indeksleme ile ilgili konuya bir sonraki yazıda değinmeye çalışacağım.

Konumuzun başlığını oluşturan “Sphinx nedir” in cevabı: Yukarıda değinildiği gibi, veritabanından bağımsız olarak çalışarak, veritabanından çektiği verileri indeksleyen, sonrasında arama sorgularına cevap veren bir arama motoru sunucusudur. Sphinxin indeksleme yapabilmesi için tablo yapısının (MyISAM, InnodDB vb) önemi yoktur. Ayrıca dökümantasyonunda yazdıklarına göre, sadece MySQL için değil, PostgreSQL için de desteği mevcut..

Bu seriye ait diğer yazılar :

Metin Bazlı Arama ? Site İçi Arama Motoru
Aramanın Yapılması ? Site İçi Arama Motoru
Sphinx nedir ?
Sphinx Kurulumu
Sphinx’in Ayarlanması ve Kullanımı

28 Jan

REST Nedir ?

REST, ingilizce Representational State Transfer ( Temsili Durum Transferi) kelimelerinin kısaltması (REST) dır. Temelde, HTTP protokolü ile çalışan, dağıtık hypermedia sistemleri için kullanılan bir yazılım mimarisi biçimidir. REST de SOAP gibi bir servisdir.

SOAP da olduğu gibi , bir sunucu ve bir istemci tarafı vardır. Yalnız SOAP dakinin aksine, bellli bir standardı yoktur. Tek ortak yanları ve standartları HTTP dir. Her ikisi de HTTP protokolü üzerinden haberleşir.

Standartdan kastım, SOAP haberleşirken WSDL denen XML’leri kullanır. Sunucu da istemci de bu XML’lere göre çalışır. Sunucu, WSDL standardına göre oluşturulmuş XML i okuyarak, hangi sorgulara cevap vereceğini, ne sonuçlar döndüreceğini bilir. İstemci ise, bu xml yardımı ile, nereye bağlanacağını, hangi çağrıları yapacağını ve ne sonuçlar alacağını bilir. Böylece bu yazılı kurallar çerçevesinde sunucu ve yazıcı arasında iletişim gerçekleşir.

REST de ise, böyle XML veya benzeri, iletişimi bir standart içerisinde sınırlandıran veya belirleyen bir yapı yok. Sadece şöyle bir standart mevcut : İstemci , sunucuya isteklerini HTTP protokolü üzerinden GET, POST,PUT veya DELETE kullanarak istek yapmalıdır.

REST in SOAP, XML-RPC vb servislerin yerine tercih edilmesinin en önemli sebebi, REST’in birçok platformda, ekstra kütüphaneye ihtiyaç duymadan çalışabilmesidir. Ayrıca diğer birçok servis mimarisine göre daha kolay kullanılabilir, öğrenilebilir ve uygulanabilirdir. Bu ve daha birçok avantajınun dışında en önemli dezavantajı bir standardı olmayışıdır. Her bir REST sunucusu ile iletişim kurmak için farklı yöntemler kullanmanız gerekebilir.
Aynı zamanda bu sunucu tarafında da aynı, REST sunucusunun yazılması tamamen geliştiriciye kalmış.

REST i daha iyi anlatabilmek için küçük bir REST sunucusu ve REST istemcisi yazdım. Yalnız dikkat etmeniz gereken şey, aşağıda yazdığım kodlar, bir ürün içerisinde kullanılmaya uygun olmadığıdır. REST tarafında güvenlik tamamen geliştiriciye kaldığı için, REST sunucunuzu tasarlarken güvenlik işlemlerini ayrıca ve titizlikle yapmalısınız. Aksi taktirde istemediğiniz sonuçlar ile karşılaşma olasılığınız yüksektir.

Burdaki kodların çalışabilmesi için linux bir makinaya sahip olmanız gerekiyor. Windows kullanmadığım için , windows makina üzerindeki kurulumun nasıl yapılacağını anlatmayacağım.

1- Kendi makinanızda bulunan web sunucusunda restex diye bir klasör oluşturun. Ben kendi makinamda /var/www dizini altına oluşturdum. Ve geri kalan ayarları da bu dizin yapısını baz alarak anlatacağım

2- /etc/hosts dosyasını sudo komutu ile açarak şu satırı ekleyin :
127.0.0.1 api.local

3- Apache’de bir sanal host tanımlayın. Bendeki Apache ayarlarının bulunduğu dizin /etc/apache2/sites-enabled/000-default olduğundan, ben bu dosyaya aşağıdaki satırları ekledim

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<VirtualHost *:80>
        ServerAdmin webmaster@localhost

        DocumentRoot /var/www/restex
        ServerName api.local
        <Directory />
                Options FollowSymLinks
                AllowOverride All
        </Directory>
        <Directory /var/www/restex/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>
</VirtualHost>

Tabi bunu yapabilmek için sudo ile super user hakları ile açmış olduğum bir editörle yapabileceğimi de vurgulayayım. Gerçi düzenli linux kullanıcıları buna alışkındır, fakat yeni başlayanlar bunu unutur çoğunlukla.

4- Apache’yi yeniden başlattım :

1
sudo apache2ctl restart

5- /var/www/restex dizini içerisinde bir .htaccess dosyası oluşturdum ve içine şunları ekledim :

1
2
3
4
5
6
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]

Bu satırları eklememdeki amaç, api.local hostuna gelecek tüm çağrıları index.php ye yönlendirmem gerektiğindendir. Böylece api çağrımın ne olduğunu bulabileceğim ( aşağıda ekledğim sunucu kodundaki -RestServer- response metodunu inceleyerek bu işlemi neden yaptığımı daha iyi kavrayabilirsiniz )

6- /var/ww/restex dizini altında index.php oluşturarak şu satırları ekledim (sunucu kodu) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php
class RestServer {
  /**
   * Döndürülecek yanıt tipini belirliyoruz
   *
   * @var string $responseType
   */

  protected $responseType;
  /**
   * Classımızın construct metoduna döndürmek istediğimiz
   * farklı bir yanıt tipi varsa bunu verebiliyoruz
   *
   */

  public function __construct($responseType = "text/json"){
    $this->responseType = $responseType;
  }
  /**
   * Sunucumuzun başlatılmasını sağlar
   *
   * @return void
   */

  public function run(){
    // döndürmek istediğimiz yanıt tipini belirtiyoruz.
    header('Content-type: '.$this->responseType);
    // yaptığımız hataları başkaları görsün istemiyoruz :)
    set_error_handler(array($this,'errorHandler'));
    // gelen komutu algılayıp cevabımızı ekrana yazdırıyoruz
    echo $this->response();
  }
  /**
   * Tüm işi burası yapıyor, bizden ne istendiğini
   * anlayarak bir cevap vermemiz gerekiyor.
   *
   * @return mixed
   */
 
  public function response(){
    $request   = substr($_SERVER['REQUEST_URI'],1);
    $request   = explode('/',$request);
    $function  = array_shift($request);

    if(isset($_POST['params'])) {
      $_POST['params'] = json_decode($_POST['params']);
      return call_user_func_array($function,$_POST['params']);
    }else {
      return call_user_func($function);
    }
  }
  /**
   * Hata yakalayıcımız, sistemdeki hataları göstermeyip standart
   * bir mesaj döndürüyoruz. Bu sistemi geliştirerek hata raporlaması vb şeyler de
   * yapılabilir. Fantaziye gerek yok, basit bir örnek sadece :)
   */

  public function errorHandler ($errno, $errstr, $errfile, $errline) {
    echo 'Hatalı veya eksik istek';
    exit;
  }
}
$server = new RestServer('text/html');
$server->run();

Sunucu kodunu açıklama grek yok sanırım, kod üzerindeki açıklamalar yardımcı olacaktır.

7- Şimdi sıra geldi sondan bir önceki adıma. REST istemcimi oluşturmak için , web ana dizininde rest.client.php oluşturdum ( /var/www/rest.client.php) ve içerisine aşağıdaki satırları ekledim :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php

class RestClient {
  /**
   * Api çağrıların yapmamızı sağlayacak istemcimiz
   * REST çağrıları HTTP protokolü ile yapılacağından
   * curl e ihityaç duyuyoruz
   *
   * @var resource
   */

  protected $client;
  /**
   * Api çağrılarının yapılacağı URL
   *
   * @var string
   */

  protected $url;

  public function __construct($url){
    $this->client = curl_init();
    $this->url = $url;
    curl_setopt($this->client, CURLOPT_RETURNTRANSFER ,1);
  }
  /**
   * Rest sunucumuza istek yapmamızı ve sonucu
   * ekrana yazdırmamızı sağlar.
   *
   * @return void
   */

  public function call($function,$params=null){
    curl_setopt($this->client,CURLOPT_URL,$this->url.'/'.$function);
     curl_setopt($this->client, CURLOPT_POST, 0);
    if(is_array($params)){
      curl_setopt($this->client, CURLOPT_POST, 1);
      curl_setopt($this->client,CURLOPT_POSTFIELDS,$params);
    }
    echo curl_exec($this->client);
  }
}

$client = new RestClient('api.local');
$client->call('date',array('params'=>json_encode(array('d-m-Y H:i:s'))));
$client->call('phpinfo');

8- Ve geldik son adıma, tarayıcıdan localhost/rest.client.php çağırıyoruz. Eğer eksiksiz yaptı iseniz bu adımları, ekranınıza tarih ve php bilgisi dökülmeli. RestClient kodunu da açıklamaya gerek yok sanırım.

Görüldüğü gibi, REST adı ile korkutucu ve karmaşık görünmesine rağmen. Çok da zor olmayan bir yapıya sahip. Yukarıda yaptığımız örnekte sunucumuza istek olarak, php fonksiyonlarını gönderdik. Sunucumuzda kendinde bu php kodlarını çalıştırdı ve bize sonucu döndürdü.
Normal şartlarda sunucu böyle bodoslama her çağrıyı yerine getirmez. Twitter veya Flickr gibi sosyal medya sitelerinin API lerini incelerseniz, Rest sunucusu için kullanılabilecek güvenlik sisteminin nasıl olması gerektiğini kafanızda daha iyi oturtabilirsiniz.

22 Jan

Sphinx Kurulumu

Sphinx kurulumu için aşağıdaki adımları takip etmek gerekiyor. Öncelikle adımları yazıyorum, sonra bunları açıklamaya çalışacağım :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mkdir sphinx-base
cd sphinx-base
wget http://pecl.php.net/get/sphinx -o /dev/null -O  sphinx.tar.gz
svn checkout http://sphinxsearch.googlecode.com/svn/trunk
cd trunk/api/libsphinxclient/
./configure --prefix=/usr/local
make
make install
cd ~/sphinx-base
tar -zxvf sphinx.tar.gz
cd sphinx-1.1.0/
phpize
/configure --prefix=/usr/local --with-sphinx
make
make install
nano /etc/php5/conf.d/sphinx.ini
extension=sphinx.so
cd ~/sphinx-base/trunk
configure --prefix=/usr/local
make
make install

(1-2) İndirdiğimiz dosyaların derli toplu olabilmesi için bir dizin oluşturdum, bu dizini home klasörümde oluşturdum. Siz de aynı şekilde home dizininizde sphinx-base diye bir klasör oluşturursanız , burdaki örneğin çalışabilmesi mümkün olur. Klasörü oluşturduktan sonra klasöre giriyoruz

(3-4) PHP sphinx eklentisini, sonrasında da sphinx kodlarını sitelerinden indiriyoruz

(5-6-7-8) PHP eklentimizin çalışabilmesi için, libsphinxclient kütüphanesine ihityaç var. Bu yüzden öncelikle bunu derliyoruz.

(9-10-11-12-13-14-15-16-17) Bu uzun adımlarda da php eklentisini derliyoruz.

(18-19-20-21) Bu adımlarda da sphinxi derliyoruz.

Yuakrıdaki adımlarda mutlaka dikkat etmeniz gereken şeyler var. Bunlardan ilki, yukarıda belirttiğim gibi home klasörünüzde sphinx-base diye bir klasör
oluştrumuş olmanız gerekli.
Anlattığım tarih ititbari ile, php sitesinden indirdiğim (3) dosyayı indirememiş olabilirsiniz. Dosyanın doğru yolunu bularak sphinx-base klasöürne indirin ve yukarıda belirttiğim şekilde (10) sphinx-base klasörü içerisine açın. İndirdiğim versiyondaki klasör ismi sphinx-1.1.0 . Sizin edindiğiniz dosyanın ismi farklı olabilir, bu yüzden 11. adımda doğru klasöre giriş yapmalısınız.

Sisteminizde, derlemeler için gerekli kütüphaneler mevcutsa, kurulumu sorunsuz olarak tamamlanacaktır. Bir sonraki yazıda, sphinx ile gelen örnek veritabanı ve örnek ayarlar ile basit bir örnek kod ekleyeceğim.

Bu seriye ait diğer yazılar :

Metin Bazlı Arama ? Site İçi Arama Motoru
Aramanın Yapılması ? Site İçi Arama Motoru
Sphinx nedir ?
Sphinx Kurulumu
Sphinx’in Ayarlanması ve Kullanımı

22 Jan

Aramanın Yapılması – Site İçi Arama Motoru

1
2
3
4
5
6
7
8
$sphinx = new SphinxClient;
$sphinx->setServer('localhost',9312);
$sphinx->setMatchMode(SPH_MATCH_EXTENDED);
$sphinx->setMaxQueryTime(30);
$sphinx->setLimits(1,6);  
echo '<pre>',
          print_r($sphinx->query($arananKelime,"indexAdi"),true),
          '</pre>';

Sphinx ile yapılan aramalar direkt veritabanı tabloları üzerinde olmamaktadır, Sphinx kurulumunda belirttiğimiz index üzerinde bir SQL oluştururuz. Bu SQL, Sphinx in indeksleyeceği verileri veritabanından almasını sağlar, bu verileri bizim belirleyeceğiniz aralıklarda alarak indeksi günceller.

Arama işlemini yapmak için yukarıdaki kodlar çalıştırılmalıdır. Kodlar sade ve anlaşılır.
Sınıfımızı oluşturuyor,sunucu adresimizi ve portunu ayarlıyoruz (genelde yukarıda belirtilen portta çalışır, siz farklı bir port belirtmedikçe). Sonrasında arama modu, toplam sorgu zamanı ve limit değerlerini ayarladıktan sonra sorgumuzu çalıştırıyoruz.

Bu sorgu sonucunda aşağıdakine benzer bir sonuç elde edersiniz (eğer aramanızdan sonuç dönmezse null döner) :

Array
(
    [error] => 
    [warning] => 
    [status] => 0
    [fields] => Array
        (
            [0] => name
            [1] => short_description
            [2] => description
            [3] => meta_description
        )

    [attrs] => Array
        (
            [type_id] => 1
            [language] => 1
        )

    [matches] => Array
        (
            [507] => Array
                (
                    [weight] => 1
                    [attrs] => Array
                        (
                            [type_id] => 1
                            [language] => 1
                        )

                )

            [508] => Array
                (
                    [weight] => 1
                    [attrs] => Array
                        (
                            [type_id] => 12
                            [language] => 1
                        )

                )

            [509] => Array
                (
                    [weight] => 1
                    [attrs] => Array
                        (
                            [type_id] => 1
                            [language] => 1
                        )

                )

            [510] => Array
                (
                    [weight] => 1
                    [attrs] => Array
                        (
                            [type_id] => 1
                            [language] => 1
                        )

                )

            [511] => Array
                (
                    [weight] => 1
                    [attrs] => Array
                        (
                            [type_id] => 12
                            [language] => 1
                        )

                )

            [512] => Array
                (
                    [weight] => 1
                    [attrs] => Array
                        (
                            [type_id] => 1
                            [language] => 4
                        )

                )

        )

    [total] => 1000
    [total_found] => 28214
    [time] => 0
)

Yukarıda dönen sonucu açıklayayım :
error, warning, status, fields, attrs alanlarını açıkalamaya gerek yok şimdilik, çünkü adlarından anlaşıldığı gibi, sorgu ile ilgili gerekli bazı bilgilerin döndürülmesini sağlar.
Burda en önemli anahtar matches dır. Bu anahtar altında, aranan kelimeye uygun kayıtların ID’leri döndürülür.

 [511] => Array
                (
                    [weight] => 1
                    [attrs] => Array
                        (
                            [type_id] => 12
                            [language] => 1
                        )

                )

Burdaki kaydın anlatmaya çalıştığı şey şudur : aradığınız kelime 511 nolu kayıtda mevcut ve bu kaydın attributleri şunlardır, bu kelimenin arama ağırlığı şudur vb. Burdaki attrs, index oluşturulması sırasında bizim tarafımızdan belirlenir. Eğer herhangi bir attribute belirtmezsek buradaki attrs anahtarı altında hiçbir kayıt olmayacaktır.
Attribute tanımlamanın temel amacı, aranan kelimeyi filtereleyebilmektir.

Bunların dışında kalan total kısmı, bir defada listelenebilecek veri miktarını.
Total found, arama sonucu bulunan toplam kayıt miktarını temsil eder.

Daha önce belirttiğimiz gibi, sorgu direkt olarak veritabanı üzerindeki tablo üzerinde çalıştırılmaz, arama motoru sunucusu verileri aldıktan sonra bağımsız olarak çalışarak, bu verileri en hızlı sonuç verecek şekilde indeksler. Sonra siz sorgu yaptığınızda, belirtmiş olduğunuz tabloda, aradığınız metne uyan kayıdın ID sini ve yaptığınız ayarlamaya göre diğer sonuçları döndürür (yukarıdaki örnek sonuç gibi).

Sonrasında yapmanız gereken, dönen SPhinx sonuçlarından IDleri ayıklayarak veritabanı üzerindeki tabloya sorgu yapmak :

$sorgu='SELECT*FROM books where id in(507,508,509,510,511,512)';

Burda vermiş olduğum örnek döküm, bilgisayarımda çalışan Sphinx sunucusunda oluşturduğum indexde yapılan arama sonucu dönen veridir. Sizin oluşturacağınız indexlerde yapacağınız aramalarda, yukarıdakine benzer sonuç alamayabilirsiniz. Ama ana bölümler aynıdır.

Bu seriye ait diğer yazılar :

Metin Bazlı Arama ? Site İçi Arama Motoru
Aramanın Yapılması ? Site İçi Arama Motoru
Sphinx nedir ?
Sphinx Kurulumu
Sphinx’in Ayarlanması ve Kullanımı

22 Jan

Metin Bazlı Arama – Site İçi Arama Motoru

Aslında burda anlatmaya çalışacağım şey, bir site içi arama motorunun nasıl oluşturulcağından öte, bu iş için kullanılabilecek, metin bazlı bir arama motorunu (Sphinx) anlatmak.

Basit anlamda bir site içi arama motoru, site içerisine eklenmiş bütün metinleri arayabilecek bir SQL sorgusu ile yapılır. Bunun için basit SQL ler veya daha iyi sonuç alabilmek için kompleks SQL lerde kullanılabilir.

Ama ne yazık ki, başarılı bir metin bazlı arama için bunlar yetmiyor. Arama yapacak tablo veya tabloların boyutu arttıkça sorgularımızın yavaş çalışması kaçınılmaz olacak. İşte burda devreye metin bazlı arama motorları devreye giriyor.

Bu arama motorları, kullanılan veritabanlarından bağımsız olarak çalışarak, istenilen tablo veya tablolardan metinlerin alınıp indekslenmesi ile, daha hızlı ve daha başarılı arama sonuçları alınmasını sağlıyor.

Açık kaynak kodlu ve ücretsiz bazı arama motorları şunlar :

DataparkSearch
Ferret
Ht-//Dig
Hyper Estraier
Lemur/Indri
Lucene
mnoGoSearch
Sphinx
Swish-e
Xapian

Bunlardan sadece Sphinx ve Lucene’i inceleme fırsatı bulabildim. Lucene in dağıtık sistemler için uygun olmaması ve (benim için) anlaşılması zor bir yapısı olması sebebi ile Sphinx ile çalışmalarıma devam ettim. Sphinx iyi bir dökümantasyona sahip, kolayca kurup ayarlama yapabiliyorsunuz.

Normalde öncelikle kurulumundan başlayarak anlatmam gerekirdi, ama bu sefer tersinden anlatmaya çalışacağım :

– Aramanın yapılması
– İstemcinin kurulması
– Sunucunun kurulması ve yapılandırılması

şeklinde anlatmaya çalışacağım.

Sphinxin PHP için hazırlanmış bir eklentisi mevcut, eklenti kurmak istemiyorsanız, Sphinx işlemlerini yapabilmek için hazırlanmış hazır bir sınıf da mevcut. Ben eklentiyi kullanmayı tercih ediyorum, ama eklentinin kurulmasının mümkün olmadığı zamanlarda bu sınıf iyi bir çözüm olabilir.

Burda eklentiyi baz alarak anlatacağım, bu yüzden burda yazdığım kodlar ile API classını kullanırken hata alırsanız, bunun API classından kaynaklanabileceğini unutmayın. Böyle bir ihtimal düşük olmakla birlikte belirtmekte fayda var.

Bu seriye ait diğer yazılar :
Metin Bazlı Arama ? Site İçi Arama Motoru
Aramanın Yapılması ? Site İçi Arama Motoru
Sphinx nedir ?
Sphinx Kurulumu
Sphinx’in Ayarlanması ve Kullanımı