Каков наилучший способ сохранить переменные конфигурации в веб-приложении 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, каковы другие способы сохранения конфигурационных переменных и их преимуществ и недостатков?
Ответы
Ответ 1
Я решил перечислить все известные методы вместе с их преимуществами и недостатками.
Я отметил этот ответ в качестве вики-сообщества, поэтому сотрудничество проще.
Глобальные константы
Назначение:
-
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'));
Преимущества:
- Может быть загружена автоматически.
Недостатки:
- Как правило, он немного подробный.
- Может быть сложно поддерживать, если класс контейнера не используется.
Ответ 2
Я стараюсь использовать статический класс 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>
И это позволит вам иметь доступ к общедоступным данным в течение инициализированного периода.
Это может стать намного более сложным, но более дружественным к системе, некоторые примеры:
- A
loadConfig
метод автоматического анализа файла конфигурации, xml, php, yaml.
- Если вы зарегистрируете
shutdown_function
, вы можете автоматически обновить базу данных новыми настройками.
- Вы можете автоматически заполнить класс конфигурацией из этой базы данных.
- Вы можете реализовать итераторы, чтобы сделать его совместимым с циклом.
- Больше.
Это тоже я, безусловно, лучший способ завершить эту работу.
Ответ 3
То, как я это делаю, прямо хранит их в array
и сохраняет файл как config.php
<?php
$config['dbname'] = "mydatabase";
$config['WebsiteName'] = "Fundoo Site";
$config['credits'] = true;
$config['version'] = "4.0.4";
?>
Thi - это способ использования большинства PHP-фреймворков, таких как Wordpress и т.д.
Ответ 4
Примечание: "Лучший способ" никогда не существует. Каждое приложение и каркас делают свой стиль. Пока ваш пример делает трюк, я думаю, что он немного ресурсоемкий для простого конфигурационного файла.
- Вы можете сделать это с помощью отдельных переменных, например Amber
- Вы можете сделать это с помощью массивов, это самый распространенный подход, и вы всегда можете легко редактировать свой файл конфигурации.
- Вы можете сделать это с .ini файлами, что PHP легко разбирается
Edit:
Эдвард, пожалуйста, взгляните на примеры parse_ini_file. Вы можете загрузить файл .ini с помощью простой команды, тогда вы можете использовать переменные в классе, как в вашем примере.
Ответ 5
Есть много возможностей, которые я думаю, но наиболее распространенные методы хранятся в виде обычного текста в таких файлах, как .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.
Ответ 6
В PHP я всегда использую ".htaccess" для защиты моего файла конфигурации (двойная защита)
Ответ 7
Поскольку 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. Не нужно включать файл, так как автозагрузчик приложений сделает это за вас. Конечно, защита файла все равно должна быть выполнена.
Ответ 8
Обычный маршрут - использовать define
:
define('MYSQL_USER', 'ROOT');
и получить доступ ко всем приложениям через MYSQL_USER
:
$user = MYSQL_USER;
Однако массивы не поддерживаются таким образом.
Ответ 9
Существует несколько возможностей:
-
Вы можете использовать конфигурационный файл (ini, json, xml или yaml). Для ini у вас есть parse_ini_file
, для JSON есть json_decode
(+ file_get_contents), для YAML вам нужно использовать внешнюю библиотеку (поиск sfYaml)
-
У вас может быть файл конфигурации с переменными или константами (лучше для неизменяемой конфигурации и доступен во всех областях), которые вы включаете в свой script:
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 и способный читать конфигурацию из заданного файла.
Ответ 10
Telnet? OMG Я попал в timewarp и прибыл в 1992 году!
Но серьезно, у IIRC есть инструменты, которые позволяют asp.net(и другим языкам) анализировать данные сеанса - это всего лишь сериализованный php-массив. Я бы попытался реализовать глобальные настройки как своего рода теневую сессию в PHP. Даже если вы не сохраняете свои настройки конфигурации в виде сериализованного массива PHP, вы можете сопоставить их в сеансе во время выполнения, используя собственный обработчик сеанса.
С точки зрения того, где вы храните данные, это более сложная задача, когда вы предположительно работаете на платформе Microsoft. Очевидно, что вы не хотите, чтобы расходы на доступ к диску для каждого запроса. Хотя NT делает некоторое кэширование диска, а не (IME), столь же эффективно, как и другие ОС. Memcached представляется одним из решений этого. Он делает доступным для использования из asp.net.
НТН
Ответ 11
Для проверки можно использовать класс Config
, содержащий фактические данные конфигурации и статический класс AppConfig
, который содержит ссылку на объект Config
, загруженный в бутстрап из файлов конфигурации приложения (зависимая инъекция при загрузке). В среде тестов я изменяю только объект Config
. См. https://github.com/xprt64/Config