Подтвердить что ты не робот

Каков наилучший способ сохранить переменные конфигурации в веб-приложении 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, каковы другие способы сохранения конфигурационных переменных и их преимуществ и недостатков?

4b9b3361

Ответ 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