Пара вариантов:
$connection = {my db connection/object}; function PassedIn($connection) { ... } function PassedByReference(&$connection) { ... } function UsingGlobal() { global $connection; ... }
Итак, пройдены, переданы по ссылке или используются глобальные. Я думаю о функциях, которые используются только в одном проекте, который будет иметь только 1 подключение к базе данных. Если есть несколько соединений, то определенно передается или передается по ссылке.
Я использую объект, поэтому я не хочу, если вы используете PHP5, а затем передаете или используете глобальные возможности.
Причина, по которой я спрашиваю, – это то, что я устаю всегда вставлять $ connection в свои параметры функции.
Я использую класс Singleton ResourceManager для обработки таких вещей, как соединения с DB и настройки конфигурации, через целое приложение:
class ResourceManager { private static $DB; private static $Config; public static function get($resource, $options = false) { if (property_exists('ResourceManager', $resource)) { if (empty(self::$$resource)) { self::_init_resource($resource, $options); } if (!empty(self::$$resource)) { return self::$$resource; } } return null; } private static function _init_resource($resource, $options = null) { if ($resource == 'DB') { $dsn = 'mysql:host=localhost'; $username = 'my_username'; $password = 'p4ssw0rd'; try { self::$DB = new PDO($dsn, $username, $password); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); } } elseif (class_exists($resource) && property_exists('ResourceManager', $resource)) { self::$$resource = new $resource($options); } } }
А затем в функциях / объектах / где-либо:
function doDBThingy() { $db = ResourceManager::get('DB'); if ($db) { $stmt = $db->prepare('SELECT * FROM `table`'); etc... } }
Я использую его для хранения сообщений, сообщений об ошибках и предупреждений, а также глобальных переменных. Здесь интересный вопрос, когда нужно использовать этот тип класса.
Попробуйте создать свой код в объектно-ориентированном виде. Методы, которые используют базу данных, должны быть сгруппированы в класс, а экземпляр класса должен содержать соединение с базой данных как переменную класса. Таким образом, соединение с базой данных доступно для функций, которые в ней нуждаются, но это не глобально.
class MyClass { protected $_db; public function __construct($db) { $this->_db = $db; } public function doSomething() { $this->_db->query(...); } }
Я вижу, что многие люди предложили какую-то статическую переменную.
По сути, между глобальной переменной и статической переменной очень мало различий. За исключением синтаксиса, они имеют точно такие же характеристики. Таким образом, вы ничего не набираете, заменяя глобальную переменную статической переменной. В большинстве примеров существует уровень развязки в том, что статическая переменная не передается напрямую, а скорее через статический метод (например, одиночный или статический реестр). Хотя это немного лучше, у этого все еще есть проблемы глобального масштаба. Если вам когда-либо понадобится использовать более одного подключения к базе данных в вашем приложении, вы будете ввернуты. Если вы когда-либо захотите узнать, какие части вашего кода имеют побочные эффекты, вам необходимо вручную проверить реализацию. Это не то, что сделает или нарушит ваше приложение, но это будет затруднять его поддержку.
Я предлагаю вам выбрать между одним из:
Передайте экземпляр в качестве аргументов для функций, которые ему нужны. Это, безусловно, самое простое, и оно имеет все преимущества узкого масштаба, но может стать довольно громоздким. Это также источник для введения зависимостей, поскольку некоторые части вашего кода могут стать посредниками. Если это произойдет, переходите к ..
Поместите экземпляр в область действия объекта, у которого есть метод, который ему нужен. Например. если метод Foo->doStuff()
требует подключения к базе данных, передайте его в конструкторе Foo
и установите его как защищенную переменную экземпляра на Foo
. Вы все еще можете столкнуться с некоторыми проблемами, связанными с передачей в методе, но, как правило, это проблема не с громоздкими конструкторами, а с методами. Если ваше приложение становится достаточно большим, вы можете использовать контейнер для инъекций зависимостей, чтобы его автоматизировать.
Мой совет состоит в том, чтобы избежать глобального в целом объеме кода – это опасно, трудно отслеживать и будет укусить вас.
Способ, которым я должен был бы сделать это, – иметь функцию, называемую getDB (), которая может либо находиться на уровне класса, либо вставлять конструктор или статическую в общий класс.
Таким образом, код становится
class SomeClass { protected $dbc; public function __construct($db) { $this->dbc = $db; } public function getDB() { return $this->dbc; } function read_something() { $db = getDB(); $db->query(); } }
или используя общий общий класс.
function read_something() { $db = System::getDB(); $db->query(); }
Независимо от того, насколько элегантный дизайн системы вы делаете, всегда есть несколько элементов, которые обязательно являются глобальными по объему (например, DB, Session, Config), и я предпочитаю хранить их как статические методы в своем классе System .
Для каждого класса требуется соединение через конструктор, это лучший способ сделать это, лучше всего я имею в виду большинство надежных и изолированных.
Однако имейте в виду, что использование общего общего класса для этого может повлиять на способность полностью изолировать объекты, использующие его, а также возможность выполнять модульные тесты на этих объектах.
Ни один из вышеперечисленных.
Все функции mysql
необязательно принимают аргумент подключения к базе данных. Если вы оставите этот аргумент, предполагается последнее соединение mysql_connect ().
function usingFunc() { $connection = getConnection(); ... } function getConnection() { static $connectionObject = null; if ($connectionObject == null) { $connectionObject = connectFoo("whatever","connection","method","you","choose"); } return $connectionObject; }
Таким образом, статический объект $ connectionObject сохраняется между вызовами getConnection.