Profili Göster

PHP İle Merkezileştirerek Bağımsızlaştırma(OOP)

Hakan DAMAR Tarih: 6/04/2009 Yorum: 7 adet

Okunma : 3897 Tutanlar: Bu yazıyı 4 kişi tuttu.

Merhaba arkadaşlar,

Bildiğiniz üzere PHP artık bir çok görevi başarıyla yerine getirebilir seviyeye gelmiştir. Bu nedenlede PHP artık Web sayfalarından Web uygulamalarına geçişte önemli bir yerde durmaktadır.

Merkezileştirme derken anlatmak istediğim web uygulamalarımızda bütün bir uygulama üzerinde gerekli olan ve kullanılan ihtiyaçlarınızı bir pipeline'dan geçirerek bağımsızlaştırmaktır.Yaptığımız bir nevi DAL'dır aslında.[Data Access Layer(Veri Erişim Katmanı)] Nasıl olacak sorusunun cevabını beraberce arayalım. Örnek senaryo üzerinden daha iyi anlatabileceğimi düşündüğümden, bir örnek ile açıklayayım.

Basit bir contact manager yazmamız gerektiğini düşünelim. Bu tür uygulamalar veri işleme üzerine kurulduğundan tüm verilerin doğru ve kontrollü şekilde ilerlemesi gerekmektedir. Veri tabanı olarak ne kullanırsanız kullanın mutlaka önemli alanlar için Transaction yönetimi yapmayı unutmayın. Konumuz veri tabanları olmadığından bu konuya girmiyorum. İlerleyen makalelerim de bu konuyuda ayrıntılı şekilde anlatacağım. Şimdilik devam edelim. Diyelim ki veri tabanı olarak MySQL Server'ı seçtik. İşimiz aslında her developer'ın da yaptığı gibi database programming. Aslında biz yazılım ile uğraştığımızı sanıyoruz ama yaptığımız 10 projeden 7/8'i veri tabanı programlama aslında. :) Şimdi object-oriented şekilde nasıl uygulamamızı merkezileştireceğimize bakalım.

Bu uygulamada veri tabanı kullanacağımızdan mutlaka veri tabanına sorgu göndereceğiz. Demin söylediğimi hatırlarsak uygulamamızın bütününde bize gereken şeyleri bir yerde toplayacaktık ve yönetimini kolaylaştıracaktık. Şimdi biz SQL sorgularımızı bir yerden geçecek şekilde hazırlıyoruz ve daha sonra sağladığı kolaylığı inceleyeceğiz.


<?php
/**
 * OOP ile Uygulama Bağımsızlaştırma.
 * Lang: PHP DB: MySQL
 * Developer: Hakan DAMAR
 * @copyright GPL
 */
Class DBProvider{
private $dbType;
private $dbConn;
private $sqlQuery;
    public function __construct(){
        // Nesnenin İlk Noktası
    }

    public function __destruct(){
        // Nesnenin Son Noktası
    }

    public function Provider($Type,$Connection){
        $this->dbType = $Type;
        $this->dbConn = $Connection;

    }

    public function Query($ExecQuery){
        $this->sqlQuery = $ExecQuery;
        switch ($this->dbType){
            case "MySQL":
                // Transaction için Table Engine Type InnoDB olmalıdır.
                @mysql_query("BEGIN");
                // Eğer birden fazla veri tabanı ile çaışıyorsanız!
                // mysql_query() fonksiyonuna 2. parametreyi veriniz.
                # $executeQuery = mysql_query($ExecQuery,$this->dbConn);
                $executeQuery = mysql_query($ExecQuery);
                if ($executeQuery){
                    @mysql_query("COMMIT");
                    // Sorgu Başarılı
                }else{
                    @mysql_query("ROLLBACK");
                    // Sorgu BAŞARISIZ!!!
                }
                break;
            case "MsSQL":
                // Ms SQL Server code here... etc...
                break;
            case "Oracle":
                // Oracle Connection here.. etc..
                break;
            case "PostgreSQL":
                // PostgreSQL connection and execute sql query code here.
                break;
            default:
                die("Bu veri tabanı henüz desteklenmiyor.<br>
                Şimdilik: MySQL,MsSQL,Oracle,PostgreSQL desteklenmektedir.");
                exit();

    }
  }
}
/**
 * İlgili Sayfanıza require_once() ederek 
 * aşağıdaki şekilde kullanabilirsiniz.
 */
// Nesnemizi Oluşturduk.
$DAL = new DBProvider();
//Veri Tabanı Türümüzü ve Bağlantımızı Belirttik.
$DAL->Provider("MySQL",$DB->Connection);
//SQL Sorgumuzu Çalıştırdık.
$DAL->Query("SELECT count(*) as TotalUser FROM tbl_user ORDER BY UName DESC");
?>

Yukarıdaki kod bize sorgularımızı merkezi tek bir noktadan kontrol etme imkanı verdi. Bizde Transaction yaparak işlem bütünlüğünü sağladık. Bu ders olmadığından diğer tüm özelliklerini de yazmadım. Sadece mantığını anlatmak adına bir kısmını yazdım. Siz bunu geliştirmek adına ekstra olarak bir string temizleme function'ı yazarak gelen sorgularınızı çalıştırmadan önce temizleyebilirsiniz.

Kod'da $DB->Connection(); diye bir parça var. Bu bölümü kodun içerisinde göremiyorsunuz çünkü DB Class'ı da ayrı bir parçasıdır programın. DB Class'ını yazdıktan sonra bağlantı parametrelerini alan Connection isminde bir function ile bu kodu tamamlayabilirsiniz. Tavsiyem Connection() bool bir değer dönsünki Connection State yapmak istediğinizde bunu if gibi karak kontrol mekanizmalarında kullanabilin. İleri de DAL'da yazacağımızdan bu konuya girmiyorum. Çünkü kendisi başlı başına bir konudur. :)

Burada değinmek istediğim ikinci nokta ise Query function'nın içerisinde gördüğünüz Switch döngüsüdür. Bu döngü ile (şimdilik DAL'ı bilmediğimizden) veri tabanı bağımsız şekilde uygulamamızı geliştirmeye devam edebiliriz. Olduda bir gün artık uygulamanızı Ms SQL Server'a geçirmek isterseniz tek yapmanız gereken Provider Function'na set ettiğiniz Type parametresini MsSQL olarak değiştirmektir. Gerekli ayarları yaptıktan sonra artık uygulamanız Ms SQL Server üzerinde başarılı bir şekilde çalışıyor olacaktır.

Gördüğünüz gibi OOP(Nesne tabanlı programlama) ile web uygulamaları geliştirdiğimizde bir sayfaya database connection sağlayıp, güvenli sorgular çalıştırmak için yazacağımız kod satırı 3'ü geçmemektedir. Ayrietten Uygulamalarınızdaki bazı noktaları merkezileştirerek uygulamamızı nasıl bağımsız hale getireceğimizide gördük.

Bu ilk makalem olduğundan biraz kısa oldu. Umarım ileride daha geniş zamanlarımda yazacağım makalelerimden daha çok bilgi edinirsiniz.

Saygılarımla,

Hakan DAMAR

aç-kapa İçeriğin rss beslemesi kullanımda değil Yorumlar

Profili Göster
Ahmet Erkan ÇELİK 8/04/2009

güzel bir makale olmuş, tebrikler. Aslında sizin örnek olarak verdiğniz class'ın biraz daha gelişmiş versiyonunu yazdmıştım. Bir kaç yıldır kullanıyorum. SQL yazmayı sevmediğimden, class içindeki fonksiyonlar, verilerden faydalanarak SQL'i otomatik yazıyor.

aecSQL5.php


<?php
class aecSQL5 {
    private $dbConnection;
    private $dbPrepend;
    private $dbname;
    private $username;
    private $password;
    private $server;
    private $dbObj;
    public static $STRING =1;
    public static $DECIMAL =0;
    public function __construct($server,$dbname,$username,$password,$prep=""){
            $this->dbPrepend=$prep;
            $this->dbname =  $dbname;
            $this->username = $username;
            $this->password = $password;
            $this->server = $server;
            if($this->dbPrepend!="") $this->dbPrepend.="_";
            $this->dbObj= new mysqli($this->server,$this->username,$this->password,$this->dbname);
    }
    public function __destruct(){
        $this->dbObj->close();        
    }
    public function SQL($sql){
        if (!$result=@$this->dbObj->query($sql)) {
            $errno=$this->dbObj->errno;
            throw new Exception("WebOrb DB Error SELECT query error: \nUsed Query:".$sql."\nErrorNo:" . $errno); 
        }
        return($result);
    }
    public function execSQL($sql){
        if (!@$this->dbObj->real_query($sql)) {
            $errno=$this->dbObj->errno;
            throw new Exception("WebOrb DB Error SELECT query error: \nUsed Query:".$sql."\nErrorNo:" . $errno); 
            return $sql;
        }
        return true;        
    }
    public  function isSavedValue($table,$contidion){
        $sql="SELECT * FROM ".$table." WHERE ".$contidion;
        if (!$result=@$this->dbObj->query($sql)) {
            $errno=$this->dbObj->errno;
            throw new Exception("WebOrb DB Error SELECT query error: \nUsed Query:".$sql."\nErrorNo:" . $errno);
            return false;
        }
        $count=$result->num_rows;
        if($count>=1) return true;
        else return false;
    }
    private function escapeQuots($str){
        $search=array("\"","'");
        $replace=array("\\\"","\\'");
        $str = str_replace($search,$replace,$str);
        return $str;
    }
    public 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.="'".$this->escapeQuots($value)."'";
        }
        $insertSQL.=$fieldSQL.") VALUES (";
        $insertSQL.=$valueSQL.");";
        if (@$this->dbObj->query($insertSQL)) {
            $errno=$this->dbObj->errno;
            if($errno!=0){
                throw new Exception("WebOrb DB Error INSERT query error: " . $errno);
            } 
        }
        return true;
    }
    public function replaceSQL($table,$fields){
        $insertSQL="REPLACE INTO `".$this->dbPrepend.$table."` (";
        $fieldSQL="";
        $valueSQL="";
        foreach ($fields as $field=>$value){
            if($fieldSQL!="") $fieldSQL.=",";
            $fieldSQL.="`".$field."`";
            if($valueSQL!="") $valueSQL.=",";
            $valueSQL.="'".$this->escapeQuots($value)."'";
        }
        $insertSQL.=$fieldSQL.") VALUES (";
        $insertSQL.=$valueSQL.");";
        if (@$this->dbObj->query($insertSQL)) {
            $errno=$this->dbObj->errno;
            if($errno!=0){
                throw new Exception("WebOrb DB Error INSERT query error: " . $errno);
            } 
        }
        //return $insertSQL;
        //echo $insertSQL;
        return true;
    }
    public function getInsertSQL($table,$fields){
        $insertSQL="INSERT INTO `".$this->dbPrepend.$table."` (";
        $fieldSQL="";
        $valueSQL="";
        foreach ($fields as $field=>$value){
            if($fieldSQL!="") $fieldSQL.=",";
            $fieldSQL.="`".$field."`";
            if($valueSQL!="") $valueSQL.=",";
            $valueSQL.="'".$this->escapeQuots($value)."'";
        }
        $insertSQL.=$fieldSQL.") VALUES (";
        $insertSQL.=$valueSQL.");\r\n";
        return $insertSQL;
    }

    public function deleteSQL($table,$whereSQL){
        $deleteSQL="DELETE FROM `".$this->dbPrepend.$table."` WHERE ".$whereSQL;
            if (@$this->dbObj->query($deleteSQL)) {
            $errno=$this->dbObj->errno;
            if($errno!=0){
            throw new Exception("WebOrb DB Error DELETE query error: " . $errno);
            } 
        }
        return true;    
    }

    public function updateSQL($table,$values,$primaryKey,$primaryKeyValue,$keyType=0){
        $updateSQL="UPDATE `".$this->dbPrepend.$table."` SET ";
        $valueSQL="";
        foreach ($values as $key=>$value){
            if($valueSQL!="") $valueSQL.=",";
            $valueSQL.="`".$key."` = '".$this->escapeQuots($value)."'";
        }
        $quot = ($keyType==aecSQL5::$DECIMAL)? "" : "'";
        $updateSQL.=$valueSQL." WHERE `".$primaryKey."` = $quot".$primaryKeyValue.$quot.";";
        if (@$this->dbObj->query($updateSQL)) {
            $errno=$this->dbObj->errno;
            if($errno!=0){
                throw new Exception("WebOrb DB Error UPDATE query error: " . $errno);
            }
        }
        $updateSQL;
        return true; 
    }
    public function getUpdateSQL($table,$values,$primaryKey,$primaryKeyValue,$keyType=0){
        $updateSQL="UPDATE `".$this->dbPrepend.$table."` SET ";
        $valueSQL="";
        foreach ($values as $key=>$value){
            if($valueSQL!="") $valueSQL.=",";
            $valueSQL.="`".$key."` = '".$this->escapeQuots($value)."'";
        }
        $quot = ($keyType==aecSQL5::$DECIMAL)? "" : "'";
        $updateSQL.=$valueSQL." WHERE `".$primaryKey."` = $quot".$primaryKeyValue.$quot.";\r\n";
        return $updateSQL; 
    }
    public function updateConditionSQL($table,$values,$condition=""){
        $updateSQL="UPDATE `".$this->dbPrepend.$table."` SET ";
        $valueSQL="";
        foreach ($values as $key=>$value){
            if($valueSQL!="") $valueSQL.=",";
            $valueSQL.="`".$key."` = '".$this->escapeQuots($value)."'";
        }
        if($condition !="") $condition = " WHERE ".$condition.";";
        $updateSQL.=$valueSQL.$condition;
        if (@$this->dbObj->query($updateSQL)) {
            $errno=$this->dbObj->errno;
            if($errno!=0){
                throw new Exception("WebOrb DB Error UPDATE query error: " . $errno);
            }
        }
        return true; 
    }
    public function getUpdateConditionSQL($table,$values,$condition=""){
        $updateSQL="UPDATE `".$this->dbPrepend.$table."` SET ";
        $valueSQL="";
        foreach ($values as $key=>$value){
            if($valueSQL!="") $valueSQL.=",";
            $valueSQL.="`".$key."` = '".$this->escapeQuots($value)."'";
        }
        if($condition !="") $condition = " WHERE ".$condition;
        $updateSQL.=$valueSQL.$condition."\r\n;";
        return $updateSQL;
    }

    public function getNewId($table){
        $query_userIdRS = "SHOW TABLE STATUS LIKE '".$this->dbPrepend.$table."'";
        $userIdRS = $this->SQL($query_userIdRS);
        $row_userIdRS = $userIdRS->fetch_assoc();
        $Id=$row_userIdRS['Auto_increment'];
    return $Id;
    }   
}

?>

bu class'ın kullanımına ilişkin bir örnek.


$dbObj= new aecSQL5("localhost","test","root","");
$data=array('alan_1'=>'veri1',
            'alan_2'=>'veri2');
$dbObj->insertSQL('tblTest',$data);
Profili Göster
Hakan DAMAR 9/04/2009

Teşekkürler. Bir framework projem var onun üzerinde çalışıyorum. Bittiğinde sizinde işinize çok yarayacağını düşünüyorum. DB Provider bağımsız uygulama geliştirebilmeyi sağlayan bir Class'ta var içerisinde.

Framework'ü http://Oxijen.org adresinden takip edebilirsiniz.

Beta: http://oxijen.org/?Home.do

İyi Çalışmalar.

Profili Göster
Salih Dincer 9/04/2009

Erkan Hocam, biz bunu yaptık mı? Hafızayı en iyi şekilde kullanmak için şart olabilir mi?

Siz bunu geliştirmek adına ekstra olarak bir string temizleme function'ı yazarak gelen sorgularınızı çalıştırmadan önce temizleyebilirsiniz.

Bu arada sizin bahsettiğiniz Smarty gibi bir şey değil mi? Orada da sorgulamaları bir kaç basit komut ile pratik şekilde yapabiliyorduk.

Bu ilk makalem olduğundan biraz kısa oldu. Umarım ileride daha geniş zamanlarımda yazacağım makalelerimden daha çok bilgi edinirsiniz. Saygılarımla, Hakan DAMAR

Teşekkürler, devamını bekleriz.

Başarılar...

Profili Göster
Ahmet Erkan ÇELİK 9/04/2009

@salih stringin temizlenmesi güvenlik için yapılır. String injection metoduyla veri tabanına sızmaları engellemek için. Sizin projede zaten verileri girenler dışarıdan değil. şirket çalışanları. Ayrıca flash girilen verileri kontrol ediyor. Hatalı veri girişine izin vermiyor. Fonksiyonlarda yanlız başına çalıştırılamaz. Remote object ise credidentails yapmadan oluşturulamaz. Ayırca tırnaklar he girilen kayıtta kontrol ediliyor ve oluğu gibi veri tabanına kaydediliyor. Zaten tırnak kullanmadan string injection yapılamaz

Profili Göster
Yılmaz Uğurlu 10/04/2009
Teşekkürler. Bir framework projem var onun üzerinde çalışıyorum. Bittiğinde sizinde işinize çok yarayacağını düşünüyorum.

Öncelikle çalışmanız için tebrik ederim. İki sorum olacak framework ile herhangi bir ORM kullanmayı düşünüyor musunuz, büyük çaplı php projelerinde artık framework ve orm kullanmak olmazsa olmazlardan oldu, bu konuda bilgi verebilir misiniz?

İkincisi; Uygulama içerisinde bahsettiğiniz sınıf kendi hazırladığınız bir sınıf mı yoksa, varolan bir kütüphane üzerinden (AdodbPHP olabilir) işlem gören proxy bir sınıf mı?

Profili Göster
Hakan DAMAR 11/04/2009

ORM konusu yazılım mühendisi arkadaşalardan gelen feedback'lerde bolca karşılaşıyorum ama sanırım ORM'in tam tersine büyük projelerde çok sorunlu bir şey olduğunu deneyim etmediklerindendir diye düşünüyorum. Çünkü araya ORM koyarsam SQL ile performans kelimelerini bir araya getiremeyiz. Büyük proje olunca soruglarımızda kompleks oluyor ve kompleks sorgular ORM söz konusu iken daha da kompleks hale geliyor. :)Implemantation'a ise hiç girmiyorum bile.

Bu ve ekleyebileceğim daha bir çok nedenden ötürü ORM'in yapısını direkt olarak eklemiyorum. Fakat, size ORM'e benzer bir yapı sunmaya çalışıyorum.

Oxijen framework her ne kadar open source bir framework olacaksa da dışarıdan kod kullanmamaktayım.

Yorumunuz için teşekkür ederim.

İyi Çalışmalar.

Profili Göster
Ali Bakar 13/08/2009

Harika bir makale , tebrikler.

yeni üyelik | şifremi unuttum

üyeler Son Kahramanlar...

stats Kimler Burada? web stats

Son 1 dakika içinde MMIstanbul' da 54 (50 kayıtlı, 4 ziyaretçi) kullanıcı varmış. Login durumda olanlar aşağıda:

...

Blog Bölümü Blogevi.com'a Taşınıyor

Selam arkadaşlar MMIstanbul'da , tasarımcı ve programcıların blog yazılarını "feedleyerek" MMIstanbul okurlarını MMIstanbul dışın ...

7.500'üncü üyemiz Cem Koç!

Neler Yapılabilir?

500 Hatası Hakkında!

Reklam, MMIstanbul ve Yeni Projeler (Durumumuz Bu Tarzında)

coldfusion mysql ubuntu
 
sponsor adobe istanbul