Как сделать объект базы данных более эффективным путем повторного использования - PullRequest
0 голосов
/ 23 сентября 2011

Я запутался в том, как обращаться с логикой повторного использования объекта базы данных и переменных или констант конфигурации, которые являются глобальными для приложения.

То, что я делал до сих пор, я создал config.php файл в каталоге Config и объявил все элементы 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 каждый раз через конструктор для каждого класса. и я очень смущен тем, как я должен иметь дело с этим.

спасибо

Ответы [ 3 ]

1 голос
/ 23 сентября 2011

У меня есть похожий шаблон проектирования, где я подключаюсь и сохраняю соединение в глобальном.

Вам не нужно передавать переменную базы данных каждому классу, поскольку он является глобальным.

Вы можете использовать его где угодно, как это:

$GLOBALS['dbh'];

Чтобы скрыть это, я фактически создал функцию с именем get_db_connection(), которая сначала проверяет, существует ли допустимое соединение в массиве $GLOBALS, а затем возвращает его. Также, если там нет действующего соединения, оно создает новое соединение, сохраняет его в $ GLOBALS и возвращает его.

Он обладает дополнительным преимуществом, которое мне нужно для создания экземпляра подключения вручную в любом месте, оно автоматически создается при первом вызове 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 так что проблема в том, что любой может изменить глобальное значение не Вот.
  • Единственный способ обойти это с помощью Singleton, который может быть ненужно для такой простой проблемы.

Из них я считаю 2-ю причину наиболее конкретной.

0 голосов
/ 03 июня 2013

Вы можете попробовать что-то вроде этого:

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)
0 голосов
/ 23 сентября 2011

вот что я наконец-то придумал.

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

это звучит более осуществимо, не так ли? :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...