Задавая еще несколько вопросов о запросах PDO, мне сказали, что сохранение моего объекта соединения PDO как глобального для использования его в моих различных функциях, вызывающих запросы к моей базе данных, обычно является плохой практикой.
Вот как я обычно использую свой объект PDO:
function somefunction(){ global $pdo; $statement = $pdo->prepare("some query"); $statement->execute(); }
Аргументы, которые я прочитал, больше касаются обслуживания и отладки кода, где трудно отследить, кто изменил объект PDO и где в коде он будет. Другие люди просто отвергают использование глобальных переменных для хранения объекта PDO, но не могут действительно объяснить, почему глобальные переменные являются плохим подходом.
Тем не менее, для проектов с небольшим размером с одной базой данных действительно ли недостаток в использовании глобальной переменной? Обычно у меня есть сценарий подключения и сценарий моих функций отдельно, где скрипт функций требует require_once () сценарий подключения, где создается мой объект PDO. Таким образом, мое соединение всегда устанавливается, и все изменения в объекте PDO выполняются в моем сценарии подключения.
Существуют ли какие-либо фундаментальные недостатки в использовании этого подхода?
Существуют ли какие-либо фундаментальные недостатки в использовании этого подхода?
Самое первое, что вам нужно понять, это то, что $pdo
является частью логики хранения . Это означает, что он должен использоваться только внутри классов, которые занимаются абстрактным доступом к данным , будь то таблица SQL или коллекция.
Давайте посмотрим на ваш код,
function somefunction(){ global $pdo; $statement = $pdo->prepare("some query"); $statement->execute(); }
Что делать, если вы хотите переключиться с MySQL на Mongo / MSSQL / PgSQL, в будущем? Тогда вам придется переписать много кода.
И для каждого поставщика базы данных вам нужно будет создать отдельный файл с другой переменной. Именно так
function somefunction(){ global $mongo; return $mongo->fetch(...); }
Используя глобальное состояние, вы получаете дублирование массового кода , потому что вы не можете передавать параметры и, следовательно, не можете изменять поведение функции во время выполнения.
Теперь давайте посмотрим на это,
function somefunction($pdo){ $statement = $pdo->prepare("some query"); $statement->execute(); }
Здесь $pdo
передается как аргумент, поэтому глобального состояния нет. Но проблема все еще остается, вы в конечном итоге нарушаете принцип единой ответственности
Если вы действительно хотите что-то поддерживаемое, чистым и очень читаемым, лучше придерживаться DataMappers . Вот пример,
$pdo = new PDO(...); $mapper = new MySQL_DataMapper($pdo); $stuff = $mapper->fetchUserById($_SESSION['id']) var_dump($stuff); // Array(...) // The class itself, it should look like this class MySQL_DataMapper { private $table = 'some_table'; private $pdo; public function __construct($pdo) { $this->pdo = $pdo; } public function fetchUserById($id) { $query = "SELECT * FROM `{$this->table}` WHERE `id` =:id"; $stmt = $this->pdo->prepare($query); $stmt->execute(array( ':id' => $id )); return $stmt->fetch(); } }
Неважно, если ваш проект небольшой или большой, вы всегда должны избегать глобального состояния во всех его формах (глобальные переменные, статические классы, синглтоны) – ради удобства обслуживания кода
Вы должны помнить, что $pdo
не является частью вашей бизнес-логики. Это часть логики хранения. Это означает, что прежде чем вы начнете что-то делать с бизнес-логикой, например, тяжелые вычисления, вы должны действительно абстрагировать доступ к таблице (включая операции CRUD)
Мост, который объединяет вашу computation logic
data access abstraction
и computation logic
, обычно называется службой
Вы всегда должны передавать функции функции в качестве параметров
Вам лучше перестать беспокоиться о своем коде и начать думать об уровнях абстракции.
И, наконец, прежде чем вы начнете делать какие-либо вещи, сначала инициализируйте все свои службы в bootstrap.php
а затем начните запрашивать хранилище в соответствии с вводом пользователя ( $_POST
или $_GET
).
Как,
public function indexAction() { $id = $_POST['id']; // That could be $this->request->getPost('id') $result = $this->dataMapper->fetchById($id); return print_r($result, true); }
Для крошечного крошечного проекта не будет много вреда для использования глобального. Когда размер проекта начинает расти, когда ситуация начинает ухудшаться.
если ваша somefunction()
имела в ней 300 строк с использованием 5 глобальных переменных, кто-то, смотрящий на ваш код, не знал бы, что функция использует внешние переменные, если только они не прошли через нее, ища глобальные переменные.
Кроме того, так легко не использовать глобальные переменные … так зачем это делать
function somefunction( PDO $pdo ){ $statement = $pdo->prepare("some query"); $statement->execute(); }
РЕДАКТИРОВАТЬ:
show_profile.php
– ваш контроллер. Контроллер собирает все данные для представления и загружает представление. Это очень упрощенная версия.
require( 'functions.php' ); $db = new PDO(); $user = get_user( $db, $user_id ); require( 'view.php' );