PHP - DB 抽象层使用静态类还是单例对象?

2022-01-05 00:00:00 oop static database singleton php

我不想讨论单例优于静态或优于全局等.我在 SO 上阅读了许多关于类似主题的问题,但我无法想出这个特定问题的答案,所以我希望现在有人可以通过一个(或多个)真正简单的例子来回答这个问题来启发我,而不仅仅是理论讨论.

I don't want to create a discussion about singleton better than static or better than global, etc. I read dozens of questions about similar subjects on SO, but I couldn't come up with an answer to this SPECIFIC question, so I hope someone could now illuminate me by answering this question with one (or more) real simple EXAMPLES, and not just theoretical discussions.

在我的应用程序中,我有典型的 DB 类来抽象 DB 层并在 DB 上执行任务而无需在代码中到处编写mysql_connect/mysql_select_db/mysql...

In my app I have the typical DB class to abstract the DB layer and to perform tasks on DB without having to write everywhere in code mysql_connect / mysql_select_db / mysql...

我可以将类编写为静态类:

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
   }

   ...
}

或作为单身人士:

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
   }

   ...
}

然后在我的应用程序中,如果我想查询我可以做的数据库

Then after in my app if I want to query the DB i could do

//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...");

对我来说,Singleton 的唯一优势是避免将类的每个方法声明为 static.我相信你们中的一些人可以给我一个例子在这个特定案例中单例的真正优势.提前致谢.

To me Singleton has got the only advantage to avoid declaring as static each method of the class. I'm sure some of you could give me an EXAMPLE of real advantage of singleton in this specific case. Thanks in advance.

推荐答案

以下(简化)示例有什么问题:

What is wrong with the following (simplified) example:

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 );

这演示了如何利用延迟加载连接,并且仍然可以灵活地使用不同的数据库连接.

This demonstrates how you can make use of lazy loading connections, and still have flexibility to use different database connections.

仅当使用其中一个实例(在本例中为模型之一)的对象决定调用该实例的方法时,数据库实例才会连接到它们各自的连接.

The database instances will only connect to their individual connection when an object that consumes one of the instances (in this case one of the models) decides to call a method of the instance.

相关文章