[英]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;
}
}
捍衛全球
我認為這是對全局變量的一種可辯護的用法,原因如下:
get_db_connection
,而只能通過單個函數get_db_connection
因此這里沒有任何人可以更改全局變量值的問題。 其中我認為第二個原因是最具體的。
您可以嘗試這樣的事情:
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.