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ı.


