Время от времени я вижу вопросы, касающиеся подключения к базе данных.
Большинство ответов я делаю не так, иначе я могу просто не получить правильные ответы. Тем не мение; Я никогда не думал об этом, потому что то, как я это делаю, работает для меня.
Но вот сумасшедшая мысль; Может, я все делаю неправильно, и если это так; Я действительно хотел бы знать, как правильно подключиться к базе данных MySQL с помощью PHP и PDO и сделать ее доступной.
Вот как я это делаю:
Во-первых, вот моя файловая структура (урезанная) :
public_html/
* index.php
* initialize/
-- load.initialize.php
-- configure.php
-- sessions.php
index.php
У меня на самом верху require('initialize/load.initialize.php');
.
load.initialize.php
# site configurations
require('configure.php');
# connect to database
require('root/somewhere/connect.php'); // this file is placed outside of public_html for better security.
# include classes
foreach (glob('assets/classes/*.class.php') as $class_filename){
include($class_filename);
}
# include functions
foreach (glob('assets/functions/*.func.php') as $func_filename){
include($func_filename);
}
# handle sessions
require('sessions.php');
Я знаю, что есть лучший или более правильный способ включения классов, но не могу вспомнить, что это было. У меня еще нет времени разобраться в этом, но я думаю, что это было что-то с autoload
. что-то такое...
configure.php
Здесь я просто переопределяю некоторые свойства php.ini и выполняю другие глобальные настройки для сайта.
connect.php
Я установил соединение с классом, чтобы другие классы могли его расширить ...
class connect_pdo
{
protected $dbh;
public function __construct()
{
try {
$db_host = ' '; // hostname
$db_name = ' '; // databasename
$db_user = ' '; // username
$user_pw = ' '; // password
$con = new PDO('mysql:host='.$db_host.'; dbname='.$db_name, $db_user, $user_pw);
$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$con->exec("SET CHARACTER SET utf8"); // return all sql requests as UTF-8
}
catch (PDOException $err) {
echo "harmless error message if the connection fails";
$err->getMessage() . "<br/>";
file_put_contents('PDOErrors.txt',$err, FILE_APPEND); // write some details to an error-log outside public_html
die(); // terminate connection
}
}
public function dbh()
{
return $this->dbh;
}
}
# put database handler into a var for easier access
$con = new connect_pdo();
$con = $con->dbh();
//
Здесь я действительно считаю, что есть возможности для значительного улучшения, поскольку я недавно начал изучать ООП и использовать PDO вместо mysql.
Итак, я просто следил за парочкой руководств для начинающих и пробовал разные вещи ...
sessions.php
Помимо обработки обычных сеансов, я также инициализирую некоторые классы в сеансе следующим образом:
if (!isset($_SESSION['sqlQuery'])){
session_start();
$_SESSION['sqlQuery'] = new sqlQuery();
}
Таким образом, этот класс доступен повсюду. Это может быть не очень хорошей практикой (?) ... В
любом случае, это то, что этот подход позволяет мне делать отовсюду:
echo $_SESSION['sqlQuery']->getAreaName('county',9); // outputs: Aust-Agder (the county name with that id in the database)
Внутри моего sqlQuery
- класса , который является extends
моим connect_pdo
- классом , есть общедоступная функция, getAreaName
которая обрабатывает запрос к моей базе данных.
Думаю, довольно аккуратно.
Работает как шарм.
Вот как я это делаю.
Кроме того, всякий раз, когда мне нужно получить что-то из моей БД не из класса, я просто делаю что-то похожее на это:
$id = 123;
$sql = 'SELECT whatever FROM MyTable WHERE id = :id';
$qry = $con->prepare($sql);
$qry -> bindParam(':id', $id, PDO::PARAM_INT);
$qry -> execute();
$get = $qry->fetch(PDO::FETCH_ASSOC);
Поскольку я помещаю соединение в переменную внутри connect_pdo.php , я просто ссылаюсь на него и готов к работе. Оно работает. Я получаю ожидаемый результат ...
Но независимо от этого; Я был бы очень признателен, если бы вы, ребята, сказали мне, если я далеко отсюда Что я должен делать вместо этого, области, которые я мог бы или должен изменить для улучшения и т. Д.
Я очень хочу учиться ...
Ответы:
Цель
На мой взгляд, в данном случае ваша цель двоякая:
Решение
Я бы рекомендовал использовать как анонимную функцию, так и фабричный шаблон для работы с подключением PDO. Его использование будет выглядеть так:
$provider = function() { $instance = new PDO('mysql:......;charset=utf8', 'username', 'password'); $instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $instance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); return $instance; }; $factory = new StructureFactory( $provider );
Затем в другом файле или ниже в том же файле:
$something = $factory->create('Something'); $foobar = $factory->create('Foobar');
Сама фабрика должна выглядеть примерно так:
class StructureFactory { protected $provider = null; protected $connection = null; public function __construct( callable $provider ) { $this->provider = $provider; } public function create( $name) { if ( $this->connection === null ) { $this->connection = call_user_func( $this->provider ); } return new $name( $this->connection ); } }
Таким образом, у вас будет централизованная структура, которая гарантирует, что соединение будет создаваться только при необходимости. Это также значительно упростило бы процесс модульного тестирования и сопровождения.
В этом случае провайдер будет найден где-то на этапе начальной загрузки. Такой подход также дал бы четкое место, где определить конфигурацию, которую вы используете для подключения к БД.
Имейте в виду, что это чрезвычайно упрощенный пример . Вам также может быть полезно посмотреть два следующих видео:
Кроме того, я настоятельно рекомендую прочитать соответствующий учебник по использованию PDO (в Интернете есть журнал плохих учебников).
источник
mysql_*
на PDO. Затем вы можете вернуться и посмотреть на это решение, которое предназначено для тех, кто уже использует PDO, но нуждается в способе совместного использования соединения с БД между несколькими классами.Я бы посоветовал не использовать
$_SESSION
глобальный доступ к вашему соединению с БД.Вы можете сделать одно из нескольких (в порядке от худшего к передовому ):
$dbh
с использованиемglobal $dbh
внутри ваших функций и классовИспользуйте одноэлементный реестр и получите доступ к нему глобально, например:
Внедрите обработчик базы данных в классы, которым он нужен, например:
class MyClass { public function __construct($dbh) { /* ... */ } }
Я очень рекомендую последний. Это известно как внедрение зависимости (DI), инверсия управления (IoC) или просто принцип Голливуда (не звоните нам, мы вам позвоним).
Однако он немного более продвинутый и требует большей «проводки» без каркаса. Итак, если внедрение зависимостей для вас слишком сложно, используйте одноэлементный реестр вместо группы глобальных переменных.
источник
sqlQuery
класс в сеанс, поскольку он расширяетсяconnect_pdo
?Недавно я сам пришел к аналогичному ответу / вопросу. Вот что я сделал, если кому-то интересно:
<?php namespace Library; // Wrapper for \PDO. It only creates the rather expensive instance when needed. // Use it exactly as you'd use the normal PDO object, except for the creation. // In that case simply do "new \Library\PDO($args);" with the normal args class PDO { // The actual instance of PDO private $db; public function __construct() { $this->args = func_get_args(); } public function __call($method, $args) { if (empty($this->db)) { $Ref = new \ReflectionClass('\PDO'); $this->db = $Ref->newInstanceArgs($this->args); } return call_user_func_array(array($this->db, $method), $args); } }
Чтобы вызвать его, вам нужно всего лишь изменить эту строку:
$DB = new \Library\PDO(/* normal arguments */);
И подсказки типа, если вы используете его для (\ Library \ PDO $ DB).
Он действительно похож как на принятый, так и на ваш ответ; однако у него есть заметное преимущество. Рассмотрим этот код:
$DB = new \Library\PDO( /* args */ ); $STH = $DB->prepare("SELECT * FROM users WHERE user = ?"); $STH->execute(array(25)); $User = $STH->fetch();
Хотя он может выглядеть как обычный PDO (изменяется
\Library\
только этим), на самом деле он не инициализирует объект, пока вы не вызовете первый метод, в зависимости от того, какой он есть. Это делает его более оптимизированным, поскольку создание объекта PDO немного дорого. Это прозрачный класс, или то, что его называют призраком , разновидность ленивой загрузки . Вы можете рассматривать $ DB как обычный экземпляр PDO, передавать его, выполнять те же операции и т. Д.источник
$dsn = 'mysql:host=your_host_name;dbname=your_db_name_here'; // define host name and database name $username = 'you'; // define the username $pwd='your_password'; // password try { $db = new PDO($dsn, $username, $pwd); } catch (PDOException $e) { $error_message = $e->getMessage(); echo "this is displayed because an error was found"; exit(); }
источник