繁体   English   中英

如何通过重用使数据库对象更高效

[英]How do i make database object more efficient by reusing

我对如何处理重用数据库对象和应用程序全局的配置变量或常量的逻辑感到困惑。

到目前为止,我一直在做的事情是,我在Config目录中创建了一个config.php文件,并声明了所有的config元素,例如,我典型的config.php文件看起来像这样。

#Start Session
session_start();
#Start Output Buffering
ob_start();
#Set Default TimeZone
date_default_timezone_set('Asia/Kolkata');
#Define Time Constant
define('DATE', date("d-F-Y/H:ia"));
#Define Paths
define('CLASSES',$_SERVER['DOCUMENT_ROOT'].'/resources/library/classes/');
define('MODELS',$_SERVER['DOCUMENT_ROOT'].'/resources/library/models/');
define('LOGS',$_SERVER['DOCUMENT_ROOT'].'/resources/logs/');

#Define Connection Constant
define('HOST','localhost');
define('USERNAME','username');
define('PASSWORD','password');
define('DATABASE','dbname');

try
{
    #Connection String.
    $dbh = new PDO('mysql:host='.HOST.';dbname='.DATABASE,USERNAME,PASSWORD);
    #Set Error Mode to ERRMODE_EXCEPTION.
    $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
    #Print Errors.
    echo $e->getMessage();
    #Log Errors into a file
    file_put_contents(LOGS.'Connection-log.txt', DATE.PHP_EOL.$e->getMessage().PHP_EOL.PHP_EOL, FILE_APPEND);
}
#Autoload Classes.
function __autoload($class) {
   require_once CLASSES.'class.'.strtolower($class).'.php';
}

在index.php文件中,我将只包含此文件一次,并在每个对象中重复使用它。

我的index.php通常由这样的控制器组成。

if(isset($_GET['users'])) {
    require_once(MODELS.'users/users.php');
} else if(isset($_GET['categories'])) {
    require_once(MODELS.'categories/categories.php');
} else if(isset($_GET['search'])) {
    require_once(MODELS.'search/search.php');
}

在模型中,我将实例化我想要的对象,并在例如users/users.php使用它,我将像这样实例化它

$user = new User($dbh);

一切工作正常,但问题是每个类都必须通过构造函数传递数据库句柄对象,并在类中重用它,这对我来说有点丑陋。 如果我要使用包含静态方法和属性的类,而该类包含要从数据库中检索到的“应用程序”设置,则这种方法给我带来了问题。 我的要求是这样的。

我想使用单例模式创建一个静态方法,该方法将保存将在应用程序中使用的数据库对象,而无需每次都通过构造函数为每个类传递$dbh对象。 我对应该如何处理感到非常困惑。

谢谢

我有一个类似的设计模式,在该模式下,我将连接连接并存储在全局中。

您不需要将数据库变量传递给每个类,因为它是全局的。

您可以在任何地方使用它,如下所示:

$GLOBALS['dbh'];

为了隐藏这一点,我实际上创建了一个名为get_db_connection()的函数,该函数首先检查$GLOBALS数组中是否存在有效的连接,然后将其返回。 同样,如果那里没有有效的连接,它将创建一个新连接,将其存储在$ GLOBALS中并返回它。

它具有我需要在任何地方手动实例化连接的get_db_connection ,它是在第一次调用get_db_connection自动创建的,随后可在任何地方使用。

get_db_connection函数如下所示:

function get_db_connection(){
    if(isset($GLOBALS['db_conn']) && get_class($GLOBALS['db_conn']) == 'PDO'){
        return $GLOBALS['db_conn'];
    }else{
        $conn = new PDO(/* parameters */);
        $GLOBALS['db_conn'] = &$conn;
        return $conn;
    }
}

捍卫全球
我认为这是对全局变量的一种可辩护的用法,原因如下:

  • 变量$ dbh已经是全局变量,因为它不在函数或类内部。
  • 您不会在程序中的任何位置直接访问全局get_db_connection ,而只能通过单个函数get_db_connection因此这里没有任何人可以更改全局变量值的问题。
  • 解决此问题的唯一方法是使用Singleton,这对于这样一个简单的问题可能是不必要的。

其中我认为第二个原因是最具体的。

您可以尝试这样的事情:

function cnn() {
    static $pdo;
    if(!isset($pdo)) {
        $pdo = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
        $pdo->setAttribute(PDO::ATTR_TIMEOUT, 30);
        $pdo->setAttribute(PDO::ATTR_PERSISTENT, true);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
        return $pdo;
    } else {
        return $pdo;
    }
}

之后,您可以调用所需的任何查询:

echo cnn()->query('SELECT firstname FROM user WHERE id=4;')->fetch(PDO::FETCH_COLUMN)

第二个查询(对象被重用)

echo cnn()->query('SELECT title FROM news WHERE id=516;')->fetch(PDO::FETCH_COLUMN)

这是我最后想出的。

class DB {

    protected static $_dbh;
    const HOST = 'localhost';
    const DATABASE = 'dbname';
    const USERNAME = 'usname';
    const PASSWORD = 'passwo';

    private function __construct() { }

    public static function get_db_connection() {
        if(!isset(self::$_dbh)) {
            self::$_dbh = new PDO('mysql:host='.self::HOST.';dbname='.self::DATABASE,self::USERNAME,self::PASSWORD);
            self::$_dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        return self::$_dbh;
    }
}

应用单例模式并使用静态方法调用,我可以轻松访问数据库对象,而无需通过类构造函数传递数据库对象。

要在类范围之内或之外调用数据库对象,我要做的就是调用一行代码。

DB::get_db_connection();

听起来更可行,不是吗? :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM