Каков наилучший способ сохранить переменные конфигурации в веб-приложении PHP?

Я часто переключаюсь между .NET и PHP. С сайтами ASP.NET я сохраняю информацию о конфигурации (например, строки подключения, каталоги, параметры приложения) в файле web.config, который надлежащим образом защищен и легко доступен для значений и т. Д.

В PHP я решаю это с классом, который имеет статические методы для каждой переменной:

class webconfig { public static function defaultPageIdCode() { return 'welcome'; } } 

Файл, включенный в переменные приложения, доступен с помощью одной строки:

 $dp = webconfig::defaultPageIdCode(); 

И поскольку PHP не скомпилирован, в любом случае легко подключиться к telnet и изменить значение для веб-сайта, поэтому это решение работает достаточно хорошо и дает мне следующие два преимущества :

  • Я могу добавить логику в конфигурационную переменную без нарушения ее интерфейса с приложением
  • эти переменные конфигурации отображаются как intellisense в моем, например, Eclipse, NetBeans и т. д.

Но я могу представить себе, что есть другие способы решения проблемы сохранения настроек веб-конфигурации в PHP, которые могут иметь другие преимущества.

Особенно те, кто имеет опыт работы с несколькими фреймворками PHP, каковы другие способы сохранения конфигурационных переменных и их преимуществ и недостатков?

Solutions Collecting From Web of "Каков наилучший способ сохранить переменные конфигурации в веб-приложении PHP?"

Я решил перечислить все известные методы вместе с их преимуществами и недостатками.

Я отметил этот ответ в качестве вики-сообщества, поэтому сотрудничество стало проще.


Глобальные константы

Назначение:

  • define('CONFIG_DIRECTIVE', 'value');

Доступ:

  • $object = new MyObject(CONFIG_DIRECTIVE);

Преимущества:

  • Обладает глобальным охватом.
  • Autocompleted большинством IDE.
  • Имеет согласованное соглашение об именах (UPPERCASE_UNDERSCORE_SEPARATED) .

Недостатки:

  • Директивы не могут содержать массивы (до версии 7.0.0).

Особые примечания:

  • Нельзя переназначить.

Альтернативные файлы синтаксиса

Например: XML, INI, YAML и т. Д.

Назначение:

  • Просто отредактируйте файл на определенном языке. (Например, для файлов INI: config_directive = value .)

Доступ:

  • Файл конфигурации должен быть проанализирован. (Например, для INI: parse_ini_file() .)

Преимущества:

  • Скорее всего, синтаксис больше подходит для файла конфигурации.

Недостатки:

  • Возможные накладные расходы на доступ и анализ файла.

массив

Назначение:

  • $config['directive'] = 'value';

Доступ:

  • Самый чистый способ доступа к значениям конфигурации с помощью этого метода – передать требуемые значения объекту, который им нужен при создании, или передать их в объект-контейнер и позволить ему обрабатывать их внутренне.
    • $object = new MyObject($config['directive']);
    • $container = new MyContainer($config);

Преимущества:

  • Директивами могут быть массивы.

Недостатки:

  • Нет автозаполнения.

Особые примечания:

  • Могут произойти переменные столкновения. Если это вызывает беспокойство, укажите свой массив соответствующим образом, чтобы избежать их.

Класс

Назначение:

  • Существует множество различных реализаций на основе классов.
    • Статический класс.
      • myCfgObj::setDirective('DIRECTIVE', 'value');
    • Экзистенциальный класс.
      • myCfgObj->setDirective('DIRECTIVE', 'value');

Доступ:

  • Опять же существуют различные реализации на основе классов.
    • Статический класс.
      • $object = new MyObject(myCfgObj::getDirective('DIRECTIVE'));
    • Экзистенциальный класс.
      • $object = new MyObject(myCfgObj->getDirective('DIRECTIVE'));

Преимущества:

  • Может быть автозагрузкой.

Недостатки:

  • Как правило, он немного подробный.
  • Может быть трудно поддерживать, если класс контейнера не используется.

Я обычно использую статический класс Settings в PHP, это потому, что

  • Он имеет глобальный охват.
  • Вы можете включить / отключить изменения для защищенных конфигураций.
  • Вы можете добавлять любые настройки в любой момент времени выполнения.
  • Вы можете сделать класс автоматическим для извлечения общедоступных конфигураций из файла / базы данных.

Пример:

 abstract class Settings { static private $protected = array(); // For DB / passwords etc static private $public = array(); // For all public strings such as meta stuff for site public static function getProtected($key) { return isset(self::$protected[$key]) ? self::$protected[$key] : false; } public static function getPublic($key) { return isset(self::$public[$key]) ? self::$public[$key] : false; } public static function setProtected($key,$value) { self::$protected[$key] = $value; } public static function setPublic($key,$value) { self::$public[$key] = $value; } public function __get($key) {//$this->key // returns public->key return isset(self::$public[$key]) ? self::$public[$key] : false; } public function __isset($key) { return isset(self::$public[$key]); } } 

Затем в пределах вашей среды выполнения, если вы сначала загрузили этот файл, а затем ваш файл конфигурации базы данных, ваш файл конфигурации базы данных выглядел бы так:

 <?php Settings::setProtected('db_hostname', 'localhost'); Settings::setProtected('db_username', 'root'); Settings::setProtected('db_password', ''); Settings::setProtected('db_database', 'root'); Settings::setProtected('db_charset', 'UTF-8'); //... echo Settings::getProtected('db_hostname'); // localhost //... Settings::setPublic('config_site_title', 'MySiteTitle'); Settings::setPublic('config_site_charset', 'UTF-8'); Settings::setPublic('config_site_root', 'http://localhost/dev/'); 

Поскольку вы можете видеть, что у нас есть метод __get , которому разрешено допускать публичные переменные, пример того, почему мы имеем это, выглядит следующим образом:

 $template = new Template(); $template->assign('settings', new Settings()); 

Независимо от того, что мы использовали этот объект как статический объект, значения должны оставаться в пределах шаблона, который вы теперь можете сделать, скажем.

 <html> <head> <?php echo isset($settings->config_site_title) ? $settings->config_site_title : 'Fallback Title'; ?> </head> </html> 

И это позволит вам иметь доступ к общедоступным данным в течение инициализированного периода.

Это может стать намного более сложным, но более системным, а некоторые примеры:

  • Метод loadConfig для автоматического анализа файла конфигурации, xml, php, yaml.
  • Если вы зарегистрируете shutdown_function вы можете автоматически обновить базу данных новыми настройками.
  • Вы можете автоматически заполнить класс конфигурацией из этой базы данных.
  • Вы можете реализовать итераторы, чтобы сделать его совместимым с циклом.
  • Еще больше.

Это тоже я, безусловно, лучший способ завершить эту работу.

То, как я это делаю, прямо хранит их в array и сохраняет файл как config.php

 <?php $config['dbname'] = "mydatabase"; $config['WebsiteName'] = "Fundoo Site"; $config['credits'] = true; $config['version'] = "4.0.4"; ?> 

Thi – это способ большинства PHP-фреймворков, таких как WordPress и т. Д.

Примечание: «Лучший способ» никогда не существует. Каждое приложение и каркас делают свой стиль. Пока ваш пример делает трюк, я думаю, что он немного ресурсоемкий для простого конфигурационного файла.

  • Вы можете сделать это с помощью отдельных переменных, таких как Amber.
  • Вы можете сделать это с помощью массивов, это самый распространенный подход, и вы всегда можете легко редактировать свой файл конфигурации.
  • Вы можете сделать это с .ini-файлами, которые PHP легко анализирует

Редактировать:

Эдвард, пожалуйста, взгляните на примеры parse_ini_file. Вы можете загрузить файл .ini с помощью простой команды, тогда вы можете использовать переменные в классе, как в вашем примере.

Есть много возможностей, которые я думаю, но наиболее распространенные методы хранятся в виде обычного текста в таких файлах, как .csv, .ini, .xml. С небольшими трюками вы можете защитить эти файлы, чтобы никто не мог напрямую загружать файлы.

пример INI-файла:

 ;<?php die(); ?> [config1] var1 = 'value1'; var2 = 'value2'; ... [config2] ... 

; считается комментарием в ini-файлах. Поэтому, когда вы читаете файл с помощью ini-parser, эта строка будет проигнорирована. Если кто-то обратится к файлу напрямую через url, будет выполняться функция die() . Это работает только, если INI-файл носит расширение файла, например .php, чтобы сервер знал, что это должно выполняться, а не дублироваться как обычный текст.

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

Zend_Config является компонентом Zend-Framework, который предоставляет возможности для нескольких адаптеров хранения с простым в использовании api.

В PHP я всегда использую «.htaccess» для защиты моего файла конфигурации (двойная защита)

Поскольку PHP способен использовать OO, мне нравится идти с «классом конфигурации»:

 class Config { /** * --------------------------------- * Database - Access * --------------------------------- */ /** * @var String */ const DB_DRIVER = 'pgsql'; const DB_USER = 'postgres'; const DB_PASSWORD = 'postgres'; const DB_NAME = 'postgres'; } 

Его легко получить с помощью Config :: DB_DRIVER. Не нужно включать файл, так как автозагрузчик приложений сделает это за вас. Конечно, защита файла еще должна быть выполнена.

Telnet? OMG Я попал в timewarp и прибыл в 1992 году!

Но серьезно, IIRC есть инструменты, которые позволяют asp.net (и другим языкам) анализировать данные сеанса – это всего лишь сериализованный php-массив. Я бы попытался реализовать глобальные настройки как своего рода теневую сессию в PHP. Даже если вы не храните свои настройки конфигурации в виде сериализованного массива PHP, вы можете отобразить их в сеансе во время выполнения, используя собственный обработчик сеанса.

С точки зрения того, где вы храните данные – это более сложно, когда вы предположительно работаете на платформе Microsoft. Очевидно, что вы не хотите, чтобы расходы на доступ к диску для каждого запроса. Хотя NT делает некоторое кэширование диска, это не так (IME) настолько же эффективно, как и другие ОС. Memcached – это одно из решений. Кажется, он доступен из asp.net.

НТН

Обычный маршрут – использовать define :

 define('MYSQL_USER', 'ROOT'); 

и получить доступ ко всем приложениям через MYSQL_USER :

 $user = MYSQL_USER; 

Однако массивы не поддерживаются таким образом.

Есть несколько возможностей:

  1. Вы можете использовать конфигурационный файл (ini, json, xml или yaml). Для ini у вас есть parse_ini_file , для JSON есть json_decode (+ file_get_contents), для YAML вам нужно использовать внешнюю библиотеку (поиск sfYaml)

  2. У вас может быть файл конфигурации с переменными или константами (лучше для неизменяемой конфигурации и доступен во всех областях), которые вы включаете в свой скрипт:

    define ('ROOT_DIR', '\ home \ www');

    $ sRootDir = '\ home \ www';

Если вы ориентированы на OO, вы можете обернуть его в класс, как свойства – у вас нет метода getter для каждого свойства, вы можете просто иметь:

 class Config { public $var1 = 'xxx'; public $var2 = 'yyy'; } 

($ c = new Config (); print $ c-> var1)

или

 static class Config { public static $var1 = 'xxx'; public static $var2 = 'yyy'; } 

(print c :: $ var1)

Лучше всего иметь класс типа реестра, реализующий singleton pattern и способный читать конфигурацию из данного файла.

Для проверки можно использовать класс Config который содержит фактические данные конфигурации и статический класс AppConfig который содержит ссылку на объект Config загруженный при загрузке из файлов конфигурации приложения (зависимость, введенная при загрузке). В среде тестов я изменяю только объект Config . См. https://github.com/xprt64/Config