PHP ve yardımcı diller için

Ubuntu’da Thunderbird için indicator applet eklentisi

Geçenlerde Ubuntu’da Thunderbird için indicator applet ayarı var mıdır diye araştırma gereği duydum. Aslında e-posta için bir client kullanmıyordum. Fakat Thunderbird yükleyince indicator applet ile Thunderbird kullanma yollarını araştırdım.

http://ubublogger.wordpress.com/2010/09/02/new-version-1-1/

Bu adreste epey güzel bir eklenti buldum.
Öncelikle

sudo add-apt-repository ppa:ruben-verweij/thunderbird-indicator

Komutu ile repo adresini ekliyoruz.

sudo apt-get update

ile güncelledikten sonra

sudo apt-get install xul-ext-indicator

ile yeni eklentiyi kuruyoruz.
Aslında hala geliştirme aşamasında görünüyor. Daha pencereyi indicator applete küçültemesek de en azından e-posta uyarıları ve yeni posta gönderme gibi özellikleri indicator applete eklemek de epey kullanışlı.
Umarım birilerinin işine yarar.

PHP 5 sınıf yapısı 2

Kaldığımız yerden devam edelim.

Sınıflarda bazen sabit değerler olması ve tüm yapının o sabitlere göre çalışması gerekebilir. Pi sayısı gibi kesinlikle değişmeyecek verileri tutan bu sabitlere “constant” denir ve “const” ile tanımlanırlar. Ayrıca bu sabitler public static özellklerine sahiptir.

<?php
class Db{
 const MySql = 'mysql';
 const PostgreSql = 'postgresql';
 
 const FETCH_ASSOC = 'fetch_assoc';
 const FETCH_OBJECT = 'fetch_object';
}

Yukarıdaki Db sınıfına bakarsanız dört tane sabiti olduğunu göreceksiniz. Bunlardan ilk iki sabiti bu sınıfın bağlanabileceği veritabanı sunucu tipleri olarak düşünürsek, sabit olmaları yerinde bir karar gibi. Diğer ikisi de çekilecek verinin tipini belirtecek.

Sınıfları birbirine eklemek ve standartları kullanmak amaçlı birşeyler yazmak için örnekler verelim.

Başlangıç seviye de olsa PHP bilgisi olanlar farklı veritabanı bağlantısı için farklı fonksiyonlar kullanıldığını bilir. Bunların hepsini aynı şekilde kullanacak bir sınıf yazalım. Aslında veritabanı örneği biraz garip kaçıyor bunun için. Malum PDO, AdoDb gibi standart kütüphaneler zaten var. Fakat bizim buradaki amacımız sınıf yazmak :)

Öncelikle her şekilde sabit olacak fonksiyonları belirleyelim.

<?php
interface Db_Connection_Interface{
 
 public function connect($username,$password,$host,$database);
 
 protected function query($sql=null);
 
 public function setSql($sql);
 
 public function setType($type);
 
 public function execute($type=null);
 
}

Bu sınıf “class” ile başlamıyor ve fonksiyonlarında herhangi bir belirleme yapılmamış. Bu açıdan epey farklı ve aslında çok kullanışlı.
Bu arayüz(interface) sınıfı. Bir sınıfın neleri nasıl yapacağını belirler. Birden fazla kişinin çalıştığı bir projede aslında farklı şekilde çalışan ama aynı şekilde çalışması istenen birşeyler varsa interface hazırlanır ve kodun buna göre yazılması istenir.
Bu arayüzde tanımladığımız fonksiyonlara bir bakalım.
- connect fonksiyonu, kullanıcı adı, parola, host ve veritabanı ismi alarak bağlantıyı oluşturur.
- query fonksiyonu, belirtilen sql sorgusunu çalıştırılmaya hazırlar.
- setSql fonksiyonu, hangi sql sorgusunun çalışacağını belirtir.
- setType fonksiyonu, sorgu çalıştırıldıktan sonra dönecek olan veri tipini belirler.
- execute fonksiyonu, hazırlanmış sorguyu çalıştırır.

Arayüz sınıflarında herhangi bir şekilde fonksiyonlara kod yazılmaz. Sadece hangi parametreleri alacak ve ne sonuç döndürecek olduğu yazılır. Bizim örneğimiz buna çok uygun. Mysql ve Postgresql veritabanlarını kullanan iki farklı class yazacağız fakat ikisini de aynı şekilde kullanabiliyor olmamız lazım.
Bu iki sınıfı yazmadan önce ortak olarak kullanılacak fonksiyonları yazacağımız sınıfımızı yazalım.

<?php
 
abstract class Db_Connection_Abstract implements Db_Connection_Interface {
protected $sql;
 
protected $type;
 
public function setSql($sql){
$this->sql = (string) $sql;
}
 
final public function setType($type){
$this->type = (string) $type;
}

Burada da daha farklı bir yazım görüyorsunuz. abstract classlar nesne oluşturamaz ama normal sınıflara eklenebilirler. Ayrıca arayüz sınıfımızın bu sınıfa eklendiğini fakat extend yerine implement ile eklendiğini farkedeceksiniz. Arayüz sınıfları extend ile sınıfı genişletmezler. Sadece sınıfın şeklini belli ederler. Eğer bu sınıfta arayüz sınıfında belirtilen fonksiyonlardan bir tanesini bile farklı şekilde oluştursaydık PHP hatası ile karşılaşırdık. Örneğin

public function setSql($sql){
$this->sql = (string) $sql;
}
yerine

public function setSql(){
$this->sql = ”;
}

yazsaydık setSql fonksiyonu bir tane parametre almalıdır diye bir hata alırdık.
Ayrıca setType fonksiyonunun başında da yeni bir belirteç var.
- Final fonksiyonlar daha sonra tekrar tanımlanamazlar. Yazıldıkları gibi kalırlar. Abstract olmaması koşuluyla sınıflar da final olabilir ve başka bir sınıfa eklenmesi engellenebilir. Abstract sınıflar başka bir sınıfa eklenmek zorunda olduğundan final belirtecini alamazlar.

Şimdi asıl classlarımızı yazalım

<?php
class Db_MySql extends Db_Connection_Abstract implements Db_Connection_Interface{
 
 public function connect($username,$password,$host,$database){
 $conn = mysql_connect($host, $username, $password);//veritabanı bağlantısını hazırlayalım
 #veritabanı bağlantısını kontrol edelim.
 if(!$conn){
 throw new Exception('veritabanı bağlantısı sağlanamadı.');
 }
 mysql_select_db($database,$conn));//veritabanını seçelim
 
 }
 
 protected function query($sql=null){
 $sql = (null !== $sql) ? $sql : $this->sql;
 if($sql){
 $resource = mysql_query($sql); //protected query değişkenine hazırlanmış sorguyu atayalım
 if($resource){
 return $resource;
 }
 }
 throw new Exception('çalıştırmak istediğiniz sorguda bir problem var lütfen sorguyu kontrol ediniz.');
 }
 
 public function setSql($sql){
 if(!is_string($sql)){
 throw new Exception('sql sorgusu string olmak zorundadır');
 }
 parent::setSql($sql); // abstract sınıfta tanımlanmış olan fonksiyona biraz eklenti yapıp sonra abstract sınıftaki halini çağırıyoruz.
 }
 
 public function execute($type=null){
 $type = (null !== $type) ? $type : $this->type;
 if($type){
 $resource = $this->query();
 switch($type){
 case Db::FETCH_ASSOC :
 $return = array();
 while($result = mysql_fetch_assoc($resource)){
 $return[] = $result;
 }
 break;
 case Db::FETCH_OBJECT :
 default:
 $return = array();
 while($result = mysql_fetch_pbject($resource)){
 $return[] = $result;
 }
 break;
 }
 }
 return $return;
 }
}

Abstract sınıfımızı extend, arayüzümüzü implement ederek mysql sınıfımızı yazmaya başladık. Fonksiyonları aynı yukarıda anlattığımız işlevleri yerine getirecek şekilde yazdık. Burada sınıflarla ilgili yeni olan tek şey setSql fonksiyonunu yeniden tanımlamamız. Eğer üst sınıflardan birinde var olan bir fonksiyon ile aynı isimde bir fonksiyon tanımlarsanız o fonksiyonun üzerine yazılır. Artık üst sınıftaki fonksiyon kullanılmaz olur. Bazen o fonksiyona ekleme yapmak istersiniz işte bu gibi durumlarda parent kullanılır. “parent”, üst sınıftaki aynı isimli fonksiyonu çalıştırır. Yani önceden tanımlanmış fonksiyonu da çalıştırır.

Şimdi asıl Db sınıfımızı biraz değiştirelim.

<?php
class Db{
 const MySql = 'mysql';
 const PostgreSql = 'postgresql';
 
 const FETCH_ASSOC = 'fetch_assoc';
 const FETCH_OBJECT = 'fetch_object';
 
 public static function connection($type){
 switch($type){
 case Db::MySql:
 $connection = new Db_MySql();
 break;
 case Db::PostgreSql:
 $connection = new Db_PostgreSql();
 break;
 default:
 $connection = null;
 break;
 }
 return $connection;
 }
}

kullanımı;

<?php
try{
 
$connection = Db::connection(Db::MySql)->connect($user,$pass,$host,$dbName);// Db_Mysql sınıfını döndürür.
$connection->setSql('SELECT * FROM table');
$sonuc = $connection->execute(Db::FETCH_OBJECT);
 
}catch (Exception $e){
 echo $e->getMessage();
}

PostgreSql sınıfı da aynı fonksiyonlar ve aynı işlevler ile yazılacak. Aradaki tek fark sınıf metodları içinde kullanılan fonksiyonların değişik olması.

PHP 5 sınıf yapısı

Sınıf(class) elemanlarının kullanıldıkları yere göre 3 tipi vardır. Bunlar public, protected ve private’tir.
public – sınıf elemanının her şekilde kullanılabileceği anlamına gelir.
protected – sınıf elemanının sadece aynı sınıf içinden veya eklenmiş sınıflar içinden kullanılabileceği anlamındadır.
private – sınıf elemanının sadece aynı sınıf içinden kullanılabileceği anlamındadır.

örnek vermek gerekirse;

  1. <?php
  2.  
  3. #Okul isimli bir sınıfımız olsun
  4.  class Okul{
  5.  public $siniflar;
  6.  private $okulAdi;
  7.  protected $ogrenciSayisi;
  8.  
  9. public function __construct(){
  10.  
  11. $this->siniflar = array('1-A','1-B','1-C');
  12.  
  13. $this->okulAdi = 'Benim Okulum';
  14.  
  15. $this->ogrenciSayisi = 75;
  16.  }
  17.  }

Öncelikle henüz değeri olmayan sınıf özelliklerini tanımladık.
Bunlar siniflar, okulAdi ve ogrenciSayisi. Dikkat ederseniz siniflar public yani her yerden erişilebilir, okulAdi sadece Okul sınıfının ve ona bağlı diğer sınıfların içinden erişilebilir, ogrenciSayisi ise sadece ve sadece Okul sınıfı içinden erişilebilir. Bu bir tür kısıtlama. Standartlara uygun kod yazmakta epey faydası var.

__construct fonksiyonu ise nesne oluşturulduğu anda kendiliğinden çalışır. Yani nesne oluşturulduğu gibi önceden hiçbir değer taşımayan bu üç elemana __construct fonksiyonu içine belirtilen değerler eklenecektir. buradaki $this içinde bulunulan nesneyi belirtir ve içinde bulunulan ya da o nesneye bağlı her türlü eleman genellikle $this ile kullanılabilir. Genellikle yazıyorum çünkü onun da bir istisnası var. Şimdilik $this’in nesne içindeki elemanlara erişmek için kullanıldığını bilmek yeterli.

Kullanıma gelince;

<?php
#öncelikle Okul nesnemizi oluşturuyoruz.
 $okul = new Okul();
 #dışarıdan erişebildiğimiz public olan tek eleman siniflar olduğundan bunu direk kullanabiliriz.
 print_r($okul->siniflar);

çıktısı
array(0 => 1-A,
1 => 1-B,
2 => 1-C)
gibi olacaktır. public olan “siniflar” haricinde hiçbir elemana $okul nesnesi ile direk erişemeyiz.

Şimdi diğerlerine bakalım.


<?php
 
#Okul isimli bir sınıfımız olsun
 class Okul{
 public $siniflar;
 private $okulAdi;
 protected $ogrenciSayisi;
 
public function __construct(){
 $this->siniflar = array('1-A','1-B','1-C');
 $this->okulAdi = 'Benim Okulum';
 $this->ogrenciSayisi = 75;
 }
#ogrenciSayisi değişkenine dışarıdan erişebilecek public foksiyonu oluşturalım
public function getOgrenciSayisi(){
return $this->ogrenciSayisi;
}
#ogrenci sayısını dışarıdan müdahale ile değiştirmemize yarayacak fonksiyonu yazalım.
public function ogrenciEkle($sayi){
$this->ogrenciSayisi  = $this->ogrenciSayisi + $sayi;
}
}

şimdi kullanııma tekrar bakalım.

$okul değişkenimize Okul nesnesini oluşturmuştuk.

<?php
echo $okul->getOgrenciSayisi();//ekrana 75 yazar.
 $okul->ogrenciEkle(10);//eskiden 75 olan öğrenci sayısına 10 daha ekledik.
 echo $okul->getOgrenciSayisi();//ekrana 85 yazar.

Neden öğrenci sayısını protected yapıp dışarıdan erişimini engellediğimize gelirsek.
öğrenci sayısını kontrol ederek değiştirmek istiyor olabiliriz. Ya da belirli işlemlerden geçirilerek kullanılması gerekiyor olabilir. Ayrıca direk değişkenlere erişim bir süre sonra bazı durumlarda karışıklığa neden olabiliyor bunun için sistemli bir şekilde fonksiyonlar yazıp sınıf değişkenlerinin değerlerine bu şekilde müdahale etmek isteyebilirsiniz hem bu şekilde farklı yerlerde aynı kontrolü yapmak yerine bu değişkeni kullanmanız gereken her yerde istediğiniz kontrol kendiliğinden yapılacaktır.

Örnek vermek gerekirse okulunuzun kapasitesi 100 olsun. Eğer eklenmek istenen sayı 100′ü geçerse öğrencileri ekleyemezsiniz. Bunun için kontrol yapmanız gerek.

<?php
#öğrenci kapasitesini belirten bir değişken hazırlayalım
 protected $ogrenciKapasitesi = 100;
 
#şimdi de ogrenciEkle fonksiyonunda kapasite kontrolü yapalım
 public function ogrenciEkle($sayi){
 if(($this->ogrenciSayisi+$sayi) <= $this->ogrenciKapasitesi){
 $this->ogrenciSayisi  = $this->ogrenciSayisi + $sayi;
 return true;
 }
 return false;
 }

okul kapasitesini (okulKapasitesi) 100 olarak belirttik ve her öğrenci eklenmeye çalıştığında mevcut öğrenci sayısı (ogrenciSayisi) ile eklenmek istenen öğrenci sayısı ($sayi) toplamının okulKapasitesi değişkenini aşıp aşmayacağı kontolünü yapıyoruz. Eğer okul kapasitesini aşacaksa eklemiyor ve bir problem olduğunu belli eden false dönüyor aksi halde true dönüyor ki bu da öğrencinin eklendiğini belirtiyor.

Kullanım şekline gelirsek;

en son 85 öğrencimiz vardı

<?php
echo $okul->getOgrenciSayisi();//ekrana 85 yazar.
 #öğrenci eklemeye çalışalım. bu sefer fonksiyonun değer döndürmesini sağladık. o yüzden olumlu mu yoksa olumsuz mu olduğunu da kontrol edeceğiz.

if($okul->ogrenciEkle(20)){ // true ya da false dönecek
 echo 'Öğrenciler başarıyla eklendi.
 }else{
 echo 'Öğrenciler eklenemedi. Okul kapasitemizi aştınız.';
 }

bir de sınıflar için nesne ekleyelim.

<?php
class Siniflar extends Okul{
 private sinifAdi = '1-A';
 }

Burada kullandığımız “extends” sınıfı genişletmeye yarıyor. Bu şekilde Siniflar sınıfı hem Siniflar sınıfının kendisindeki hem de Okul sınıfındaki elemanlara erişebilir. Buradaki tek istisna Okul sınıfındaki private değişken olan okulAdi. Önceden de söylediğim gibi private değişkenler sadece aynı sınıf içinde kullanılabilir. Burada Siniflar sınıfı ile okuldaki sınıfların bilgilerini tutacağız ve okul ismine direk bir müdahalede bulunmamız sakıncalı diye düşünüp sadece Okul sınıfı içinden değişiklik yapmaya izin verdik.
Şimdi Siniflar sınıfından bir nesne oluşturalım;

<?php $siniflar = new Siniflar();

$siniflar kullanarak az önce $okul değişkeninde yaptığımız herşeyi yapabiliriz çünkü Okul, extends kullanılarak Siniflar nesnesine bağlı.
Umarım örneğim fazla kafa karıştırıcı olmamıştır.
Ayrıca protected, private ve public tipleri haricinde kullanım şekline göre “static” eklentisi var.
static’teki olay nesne oluşturmaya ihtiyaç kalmamasıdır.

<?php
class Oda{
 protected static $masaSayisi = 10;
 
public static function getMasaSayisi(){
 return self::$masaSatisi;
 }
 }

bu şekilde bir Oda sınıfı olduğunu düşünürsek masa sayısını ekrana yazdırmak için aşağıdaki kodu kullanırız.

echo Oda::getMasaSayisi(); // ekrana 10 yazdırır.

Buradaki en büyük fark Oda sınıfından bir nesne oluşturabiliriz fakat -> kullanarak yukarıda tanımladığımız elemanlara erişemeyiz. Erişememizin nedeni static olarak tanımlanmaları. Fonksiyonu herhangi bir nesne oluşturmadan çağırdığıma ve sınıf isminden sonra kullanılan :: işaretine dikkatinizi çekmek isterim. static elemanlar bu şekilde direk kullanılabilir. Aynı zamanda postun en başında sınıf içi elemanlara erişimde genellikle $this kullanılır demiştim. Bunun istisnası da yine static elemanlar. Fonksiyonun içine dikkat ederseniz masaSayisi değişkenine erişmek için önce “self” ardından yine :: kullandım. Static elemanlarda $this kullanamazsınız. Bu şekilde çağırmanız gerekir. Aslında daha anlatılabilecek çok şey var fakat saatin geç olduğunu farkederek bırakıyorum. Umarım açık bir şekilde anlatabilmişimdir.