1.Глобал.Работает как шарм.Глобалы ненавидят, поэтому мои мысли не использовать его.
Ну, глобалы не просто ненавидят.Их ненавидят по причине.Если вы не зашли слишком далеко к проблемам, которые вызывают глобалы, хорошо.Вам не нужно реорганизовывать свой код.
2.Определите константу в моем файле config.php.
На самом деле это похоже на глобал, но с другим именем.Вы бы также сэкономили $
и использовали global
в начале функций.Wordpress сделал это для их конфигурации, я бы сказал, что это хуже, чем использование глобальных переменных.Это значительно усложняет введение швов.Также нельзя присвоить объект постоянной.
3.Включите файл конфигурации в функцию.
Я бы посчитал это издержками.Вы сегментируете кодовую базу для небольшого выигрыша.«Глобальный» здесь станет именем файла, который вы вводите между прочим.
Примите во внимание эти три мысли о вас и мои комментарии к ним, я бы сказал: если вы не столкнетесь с актуальными проблемамис некоторыми глобальными переменными, вы можете придерживаться их.Глобальные затем работают как локатор вашего сервиса (конфигурация, база данных).Другие делают гораздо больше, чтобы создать то же самое.
Если у вас возникнут проблемы (например, вы, вероятно, хотите разработать тестовый метод), я предлагаю вам начать с тестирования одной части за другой, а затем вы узнаете, какчтобы избежать глобальных значений.
Внедрение зависимостей
Поскольку внутри комментариев выяснилось, что вы ищете внедрение зависимостей, и если вы не можете редактировать определение параметра функции, вы можете - если вы используетеобъекты - вводить зависимости через конструктор или используя так называемые методы установки .В следующем примере кода я сделаю и то, и другое для демонстрационных целей, как вы уже догадались, бесполезно использовать оба сразу:
Допустим, массив конфигурации - это зависимость, которую мы хотели бы внедрить,Давайте назовем это config
и назовем переменную $config
.Поскольку это массив, мы можем указать его как array
.Прежде всего, определите конфигурацию во включаемом файле. Может быть, вы также можете использовать parse_ini_file
, если предпочитаете формат ini-файла.Я думаю, что это даже быстрее.
config.php
:
<?php
/**
* configuration file
*/
return array(
'db_user' => 'root',
'db_pass' => '',
);
Этот файл может просто потребоваться в вашем приложении, где бы вы ни захотели:
$config = require('/path/to/config.php');
Так что его можно легко превратить в переменную массива где-нибудь в вашем коде.Ничего впечатляющего и абсолютно не связанного с внедрением зависимости.Давайте рассмотрим примерный класс базы данных, который должен иметь конфигурацию здесь, он должен иметь имя пользователя и пароль, в противном случае он не может подключиться, скажем:
class DBLayer
{
private $config;
public function __construct(array $config)
{
$this->setConfig($config);
}
public function setConfig(array $config)
{
$this->config = $config;
}
public function oneICanNotChange($paramFixed1, $paramFixed2)
{
$user = $this->config['db_user'];
$password = $this->config['db_pass'];
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
throw new DBLayerException('Connection failed: ' . $e->getMessage());
}
...
}
Этот пример немного грубоват, ноимеет два примера внедрения зависимости.Сначала через конструктор:
public function __construct(array $config)
Этот тип является очень распространенным, все зависимости, необходимые классу для работы, внедряются во время создания.Это также гарантирует, что при вызове любого другого метода этого объекта этот объект будет находиться в предварительно определяемом состоянии, что несколько важно для системы.
Второй пример - использование открытого метод установки :
public function setConfig(array $config)
Позволяет добавить зависимость позже, но некоторым методам может потребоваться проверить наличие доступных объектов перед выполнением их работы.Например, если бы вы могли создать объект DBLayer
без предоставления конфигурации, метод oneICanNotChange
можно было бы вызвать без того, чтобы этот объект имел конфигурацию, и ему пришлось бы иметь дело с этим (что не показано в этом примере).
Сервисный локатор
Поскольку вам, вероятно, нужно интегрировать код на лету, и вы хотите, чтобы ваш новый код тестировался с помощью внедрения зависимостей, и всего того, что делает нашу жизнь проще, вам, возможно, придется объединить это с вашим древним / устаревшим кодом.Я думаю, что это сложно.Самостоятельное внедрение зависимостей довольно просто, но объединить его со старым кодом не так просто.
Здесь я могу предложить вам создать одну глобальную переменную, которая называется так называемым сервисным локатором..Он содержит центральную точку для выборки объектов (или даже массивов, подобных вашему $config
).Тогда его можно использовать, и контракт - это имя этой единственной переменной.Таким образом, чтобы удалить глобальные переменные, мы используем глобальную переменную.Звучит немного неэффективно, и даже если ваш новый код использует его слишком много.Однако вам нужен какой-то инструмент, чтобы соединить старое и новое.Итак, вот самая простая реализация локатора сервисов PHP, которую я только мог себе представить.
Он состоит из одного Services
объекта, который предлагает все ваши сервисы, например config
сверху.Поскольку при запуске сценария PHP мы еще не знаем, нужен ли вообще какой-либо сервис (например, мы не можем выполнить какой-либо запрос к базе данных, поэтому нам не нужно создавать экземпляр базы данных), он также предлагает некоторую ленивую функцию инициализации.Это делается с помощью фабричных скриптов, которые являются просто PHP-файлами, которые устанавливают службу и возвращают ее.
Первый пример: допустим, функция oneICanNotChange
была бы не частью объекта, а простофункция в глобальном пространстве имен.Мы не смогли бы внедрить config
зависимость.Вот где появляется объект Services
Service Locator:
$services = new Services(array(
'config' => '/path/to/config.php',
));
...
function oneICanNotChange($paramFixed1, $paramFixed2)
{
global $services;
$user = $services['config']['db_user'];
$password = $services['config']['db_pass'];
...
Как уже показывает пример, объект Services
отображает строку 'config'
в путь к файлу PHP, который определяет$config
массив: /path/to/config.php
.Он использует интерфейс ArrayAccess
, чем предоставляет эту службу внутри функции oneICanNotChange
.
Я предлагаю здесь интерфейс ArrayAccess
, потому что он хорошо определен и показывает, что мы имеемкакой-то динамический характер здесь.С другой стороны, это позволяет нам ленивую инициализацию:
class Services implements ArrayAccess
{
private $config;
private $services;
public function __construct(array $config)
{
$this->config = $config;
}
...
public function offsetGet($name)
{
return @$this->services[$name] ?
: $this->services[$name] = require($this->config[$name]);
}
...
}
Эта примерная заглушка просто требует заводских сценариев, если она еще этого не сделала, в противном случае она вернет возвращаемое значение сценариев, как массив, объектили даже строку (но не NULL
, что имеет смысл).
Я надеюсь, что эти примеры полезны и показывают, что не нужно много кода, чтобы получить больше гибкости и выкачивать глобальные значения из вашего кода.Но вам должно быть ясно, что локатор службы вводит в ваш код глобальное состояние.Преимущество состоит в том, что легче отделить это от конкретных имен переменных и обеспечить немного большую гибкость.Возможно, вам удастся разделить объекты, которые вы используете в своем коде, на определенные группы, из которых только некоторые должны стать доступными через сервис-локатор, и вы можете сохранить небольшой размер кода, который зависит от локатора.