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

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

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

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

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

$dp = webconfig::defaultPageIdCode();

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

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

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

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

Ответы [ 11 ]

36 голосов
/ 16 сентября 2010

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

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


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

Назначение:

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

Доступ:

  • $object = new MyObject(CONFIG_DIRECTIVE);

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

  • Имеет глобальный охват.
  • Автозаполнение большинством IDE.
  • Имеет согласованное соглашение об именах (UPPERCASE_UNDERSCORE_SEPARATED) .

Недостатки:

  • Директивы не могут содержать массивы (до v7.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'));

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

  • Может быть загружен автоматически.

Недостатки:

  • Имеет тенденцию быть немного многословным.
  • Может быть сложно поддерживать, если класс контейнера не используется.
23 голосов
/ 16 сентября 2010

Я склонен использовать статический класс 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вы можете автоматически обновить базу данных новыми настройками.
  • Вы можете автоматически заполнить класс конфигурацией из этой базы данных.
  • Вы можете реализовать итераторы, чтобы сделать его совместимым с циклом.
  • Много больше.

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

5 голосов
/ 16 сентября 2010

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

<?php

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

?>

Это то, как большинство PHP-фреймворков, таких как Wordpress и т. Д., Делают это.

2 голосов
/ 16 сентября 2010

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

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

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

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

Возможным недостатком большинства хранилищ file-base-config являются проблемы с некоторыми символами utf8.

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

2 голосов
/ 16 сентября 2010

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

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

Edit:

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

1 голос
/ 16 сентября 2010

Так как PHP может использовать ОО, мне нравится использовать «класс конфигурации»:

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. Не нужно включать файл, так как автозагрузчик приложения сделает это за вас. Конечно, защита файла все еще должна быть сделана.

1 голос
/ 16 сентября 2010

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

0 голосов
/ 21 марта 2016

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

0 голосов
/ 16 сентября 2010

Telnet? Боже мой, я попал в хронометраж и прибыл в 1992 году!

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

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

НТН

0 голосов
/ 16 сентября 2010

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

  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, вы можете заключить его в класс как свойства - у вас нет метода получения для каждого свойства, выможет иметь только:

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

($ c = новый Config (); печать $ c-> var1)

или

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

(печать c ::$ var1)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...