PHP - tek nesne vs DB soyutlama katmanı kullanımı statik sınıf?

4 Cevap php

Ben küresel daha statik daha iyi veya daha iyi tekiz, vb SO benzer konular hakkında sorular onlarca okudum, ama ben bu ÖZEL soruya bir cevap gelmedi hakkında bir tartışma yaratmak istemiyorum, bu yüzden umarım Birisi şimdi real simple EXAMPLES bir (veya daha fazla) bu soruyu cevaplayarak beni aydınlatmak değil, sadece kuramsal tartışmalar olabilir.

Benim app ben typical DB class to abstract the DB layer var ve kod her yerde yazmak zorunda kalmadan DB görevleri gerçekleştirmek için mysql_connect / mysql_select_db / mysql...

I could write the class either as a STATIC CLASS:

class DB
{
   private static $connection = FALSE; //connection to be opened

   //DB connection values
   private static $server = NULL; private static $usr = NULL; private static $psw = NULL; private static $name = NULL;

   public static function init($db_server, $db_usr, $db_psw, $db_name)
   {
      //simply stores connections values, without opening connection
   }

   public static function query($query_string)
   {
      //performs query over alerady opened connection, if not open, it opens connection 1st
   }

   ...
}

OR as a SINGLETON:

class DBSingleton
{
   private $inst = NULL;
   private $connection = FALSE; //connection to be opened

   //DB connection values
   private $server = NULL; private $usr = NULL; private $psw = NULL; private $name = NULL;

   public static function getInstance($db_server, $db_usr, $db_psw, $db_name)
   {
      //simply stores connections values, without opening connection

      if($inst === NULL)
         $this->inst = new DBSingleton();
      return $this->inst;
   }
   private __construct()...

   public function query($query_string)
   {
      //performs query over already opened connection, if connection is not open, it opens connection 1st
   }

   ...
}

Sonra benim app sonra ben yapabilirdim DB sorgulamak istiyorsanız

//Performing query using static DB object
DB:init(HOST, USR, PSW, DB_NAME);
DB::query("SELECT...");

//Performing query using DB singleton
$temp = DBSingleton::getInstance(HOST, USR, PSW, DB_NAME);
$temp->query("SELECT...");

Benim için Singleton sınıfının static her yöntemi olarak ilan önlemek için tek avantajı var. Sana bazı bana EXAMPLE bu specific case içinde tekiz gerçek avantajı verebilir eminim. Şimdiden teşekkürler.

4 Cevap

Ne aşağıdaki (basitleştirilmiş) örnek yanlış:

class Database
{
    protected $_connection;

    protected $_config;

    public function __construct( array $config ) // or other means of passing config vars
    {
        $this->_config = $config;
    }

    public function query( $query )
    {
        // use lazy loading getter
        return $this->_getConnection()->query( $query );
    }

    protected function _getConnection()
    {
        // lazy load connection
        if( $this->_connection === null )
        {
            $dsn = /* create valid dsn string from $this->_config */;

            try
            {
                $this->_connection = new PDO( $dsn, $this->_config[ 'username' ], $this->_config[ 'password' ] );
            }
            catch( PDOException $e )
            {
                /* handle failed connecting */
            }
        }

        return $this->_connection;
    }
}

$db1 = new Database( array(
    'driver'   => 'mysql',
    'host'     => 'localhost',
    'dbname'   => 'test',
    'username' => 'test_root',
    'password' => '**********'
) );

$db2 = new Database( array(
    'driver'   => 'pgsql',
    'host'     => '213.222.1.43',
    'dbname'   => 'otherdb',
    'username' => 'otherdb_root',
    'password' => '**********'
) );

$someModel       = new SomeModel( $db1 );
$someOtherModel  = new SomeOtherModel( $db2 );
$yetAnotherModel = new YetAnotherModel( $db2 );

Bu tembel yükleme bağlantıları yararlanabilirler nasıl gösterir, ve yine farklı veritabanı bağlantıları kullanmak için esnekliğe sahip.

Veritabanı örnekleri sadece kendi bireysel bağlantısına zaman örnekleri birini (bu durumda modellerinden biri) örneğinin bir yöntemini çağırmak için karar tüketir bir nesne.

Benim en son projede, aslında veritabanı sınıfı tamamen statik yaparak "iyi" tasarım ilkelerine karşı gitti. Bu arkasındaki nedeni PHP nesneleri önbelleğe alma bir sürü kullanılmış olmasıdır. Başlangıçta ancak ben veritabanı kesinlikle gerekli olmadıkça bağlamak zorunda değildi emin olmak istedim, bir bağımlılık enjeksiyon olarak her nesnenin yapıcısı aracılığıyla geçirilen veritabanı vardı. Eğer önbellek bir nesne dizgilenmemiş eğer, aslında üzerinde bir işlem yürüttü sürece veritabanına bağlanmak istemem çünkü Böylece, o nesnenin bir üye değişkeni olarak bir veritabanı kullanarak pratik olmazdı.

Yani sonunda sadece iki (kamu) statik işlevleri, Veritabanı :: fetch () ve Veritabanı vardı :: zaten bağlı olduğu olup olmadığını kontrol hangi () yürütmek, ve değilse, bağlanıp sorgu gerçekleştirmek olacaktır. Bu şekilde ben serisini kaldırma konusunda endişelenmenize gerek olmaz ve mümkün olduğunca nadiren bağlayacak. Bu teknik rağmen birim test imkansız hale getirir.

Her zaman her iyi uygulama takip etmek zorunda değilsiniz. Ama yine de bazıları erken optimizasyon düşünecektim beri ne yaptım yaparak karşı öneriyoruz.

Benim tavsiyem: hep birlikte Singleton ve statik kullanarak DUR.

Neden? Diğer projelerde kod kullanılmaz kılacak bağımlılıkları ekler ve bunu test birimine izin vermez çünkü. Ayrıca tekiz kullanıyorsanız gevşek bağlantı unutun.

The alternatives? Dependency Injection. http://www.potstuck.com/2009/01/08/php-dependency-injection

DB kütüphanesi statik yapma kesinlikle kısa ve yaparak daha hızlıdır:

$db = DBSingleton::blabla(); // everytime I need ya

Küresel olduğu Ama aynı zamanda, her yerde kullanmak için cazip.

Yani, diğer yöntemleri seçerseniz want temiz kod ... ve statik seçerseniz need hızlı kod ;-)