Создание файла конфигурации на PHP


101

Я хочу создать файл конфигурации для своего проекта PHP, но не уверен, как это сделать лучше всего.

У меня пока есть 3 идеи.

1-использовать переменную

$config['hostname'] = "localhost";
$config['dbuser'] = "dbuser";
$config['dbpassword'] = "dbpassword";
$config['dbname'] = "dbname";
$config['sitetitle'] = "sitetitle";

2-Use Const

define('DB_NAME', 'test');
define('DB_USER', 'root');
define('DB_PASSWORD', '');
define('DB_HOST', 'localhost');
define('TITLE', 'sitetitle');

3-использование базы данных

Я буду использовать конфигурацию в классах, поэтому я не уверен, какой путь будет лучшим или есть ли лучший.


12
4) Используйте ini-файл. 5) Используйте файл YAML. 6) Используйте файл JSON. 7) ... Есть так много способов ... Определите несколько критериев, по которым можно судить, по крайней мере, не существует общего "лучшего".
deceze

@deceze какой способ поста? (на память и быстро)
Али Акбар Азизи

Тогда это должно быть для вас интересным
чтивом

1
Я использую способ, которым это делает Laravel (когда не использую Laravel). Я создаю класс, который загружает определенный файл конфигурации в зависимости от имени хоста. Затем я вызываю его с помощью Config::get('key');. pastebin.com/4iTnjEuM
MisterBla

Ответы:


220

Один простой, но элегантный способ - создать config.phpфайл (или как вы его называете), который просто возвращает массив:

<?php

return array(
    'host' => 'localhost',
    'username' => 'root',
);

А потом:

$configs = include('config.php');

10
Мне также нравится этот метод - я думаю, что он чище, чем просто объявление переменной во включенном файле и предположение, что она будет там в вашем скрипте
Колин М.

Где в этом ответе метод создания файла конфигурации? Для начинающих PHP, как я?
Лука

@Luka Вы можете использовать функцию var_export .
Хасан Баят,

77

Использование файла INI - гибкое и мощное решение! PHP имеет встроенную функцию для правильной обработки. Например, можно создать файл INI следующим образом:

app.ini

[database]
db_name     = mydatabase
db_user     = myuser
db_password = mypassword

[application]
app_email = mailer@myapp.com
app_url   = myapp.com

Итак, единственное, что вам нужно сделать, это позвонить:

$ini = parse_ini_file('app.ini');

Затем вы можете легко получить доступ к определениям с помощью $iniмассива.

echo $ini['db_name'];     // mydatabase
echo $ini['db_user'];     // myuser
echo $ini['db_password']; // mypassword
echo $ini['app_email'];   // mailer@myapp.com

ВАЖНО: по соображениям безопасности файл INI должен находиться в непубличной папке.


Это тоже безопасно? Если бы пользователь угадал путь к ini-файлу и перешел туда в своем браузере, увидели бы они, что находится в файле?
NickGames

1
@NickGames, вы должны поместить файл в не общедоступную папку, иначе вы подвергнетесь серьезной угрозе безопасности,
Марсио Маццукато,

2
@NickGames, пожалуйста, посмотрите 1 комментарий в документации к parse_ini_file ()
R Picheta

20
Мне нравится такой подход. Бонусный совет: переименуйте файл в app.ini.php. Затем добавьте в первую строку ;<?php die(); ?>. Если этот файл случайно появится в общей папке, он будет обработан как файл PHP и умрет в первой строке. Если файл читается с помощью parse_ini_file, первая строка будет рассматриваться как комментарий из-за наличия ;.
andreas

1
Примечание. Если значение в ini-файле содержит какие - либо не буквенно-цифровые символы, его необходимо заключить в двойные кавычки ( "). Например, любой пароль содержит не буквенно-цифровые символы.
Key Shang

25

Я использую небольшую эволюцию @hugo_leonardo «s решения :

<?php

return (object) array(
    'host' => 'localhost',
    'username' => 'root',
    'pass' => 'password',
    'database' => 'db'
);

?>

Это позволяет вам использовать синтаксис объекта, когда вы включаете php: $configs->hostвместо $configs['host'].

Кроме того, если у вашего приложения есть необходимые вам конфигурации на стороне клиента (например, для приложения Angular), вы можете иметь этот config.phpфайл, содержащий все ваши конфигурации (централизованно в одном файле вместо одного для JavaScript и одного для PHP). Тогда уловка будет заключаться в том, чтобы иметь другой файл PHP, который будет содержать echoтолько информацию на стороне клиента (чтобы избежать отображения информации, которую вы не хотите отображать, например строки подключения к базе данных). Назовите это, скажите get_app_info.php:

<?php

    $configs = include('config.php');
    echo json_encode($configs->app_info);

?>

Приведенное выше, если у вас config.phpесть app_infoпараметр:

<?php

return (object) array(
    'host' => 'localhost',
    'username' => 'root',
    'pass' => 'password',
    'database' => 'db',
    'app_info' => array(
        'appName'=>"App Name",
        'appURL'=> "http://yourURL/#/"
    )
);

?>

Таким образом, информация вашей базы данных остается на стороне сервера, но информация вашего приложения доступна из вашего JavaScript, например, с помощью $http.get('get_app_info.php').then(...);типа вызова.


зачем делать из него объект?
TheCrazyProfessor 09

4
Превращение его в объект значительно упрощает обработку данных. Это позволяет, например, получить все app_infoпараметры в JavaScript как JSON с минимумом строк кода.
BoDeX

У объектов также есть побочный эффект - они передаются по ссылке, начиная с PHP 5. Это может быть хорошо, а может и нет. Массивы передаются по значению (но реализованы как COW), поэтому может быть лучше использовать массивы конфигурации вместо объектов конфигурации.
Микко Ранталайнен

@BoDeX Мне всегда нравится этот способ, и он, кажется, является предпочтительным в большинстве статей, но как мне получить к нему доступ через класс? Я читал в статье по безопасности, что создание глобальных переменных - не лучшая идея, что вы предлагаете?
Кевлвиг

22

Варианты, которые я вижу с относительными достоинствами / недостатками, следующие:

Файловые механизмы

Это требует, чтобы ваш код просматривал определенные места, чтобы найти ini-файл. Это сложная для решения проблема, которая всегда возникает в больших PHP-приложениях. Однако вам, вероятно, потребуется решить проблему, чтобы найти код PHP, который будет включен / повторно использован во время выполнения.

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

Общие форматы файлов, используемые для файлов конфигурации, - это код PHP, файлы в формате ini, JSON, XML, YAML и сериализованный PHP.

Код PHP

Это обеспечивает огромную гибкость для представления различных структур данных, и (при условии, что он обрабатывается с помощью include или require) проанализированный код будет доступен из кеша кодов операций, что дает преимущество в производительности.

Include_path предоставляет средства для абстрагирования потенциальных местоположений файла , не полагаясь на дополнительном коде.

С другой стороны, одна из основных причин отделения конфигурации от кода - разделение ответственности. Он обеспечивает путь для внедрения дополнительного кода в среду выполнения.

Если конфигурация создается с помощью инструмента, можно проверить данные в инструменте, но нет стандартной функции для экранирования данных для встраивания в код PHP, которая существует для HTML, URL-адресов, операторов MySQL, команд оболочки ... .

Сериализованные данные Это относительно эффективно для небольших объемов конфигурации (примерно до 200 элементов) и позволяет использовать любую структуру данных PHP. Для создания / анализа файла данных требуется очень мало кода (так что вместо этого вы можете приложить усилия для того, чтобы файл был записан только с соответствующей авторизацией).

Экранирование содержимого, записанного в файл, выполняется автоматически.

Поскольку вы можете сериализовать объекты, это создает возможность для вызова кода, просто читая файл конфигурации (магический метод __wakeup).

Структурированный файл

Сохранение его в виде файла INI, как было предложено Марселем, или JSON, или XML, также предоставляет простой API для сопоставления файла со структурой данных PHP (и, за исключением XML, для экранирования данных и создания файла), при этом исключая вызов кода. уязвимость, использующая сериализованные данные PHP.

Он будет иметь характеристики производительности, аналогичные сериализованным данным.

Хранилище базы данных

Это лучше всего рассматривать, когда у вас есть огромное количество настроек, но вы избирательно выбираете то, что необходимо для текущей задачи - я был удивлен, обнаружив, что примерно со 150 элементами данных было быстрее получить данные из локального экземпляра MySQL, чем из десериализовать файл данных.

OTOH - не лучшее место для хранения учетных данных, которые вы используете для подключения к базе данных!

Среда исполнения

Вы можете установить значения в среде выполнения, в которой работает PHP.

Это устраняет любые требования к PHP-коду искать конфигурацию в определенном месте. OTOH плохо масштабируется для больших объемов данных и его трудно повсеместно изменить во время выполнения.

На клиенте

Одно место, которое я не упомянул для хранения данных конфигурации, - это клиент. Опять же, накладные расходы сети означают, что это плохо масштабируется для больших объемов конфигурации. И поскольку конечный пользователь имеет контроль над данными, они должны храниться в формате, в котором любое вмешательство может быть обнаружено (например, с помощью криптографической подписи), и не должен содержать никакой информации, которая подвергается риску в результате ее раскрытия (например, с обратимым шифрованием).

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

Сетевые каталоги Еще одно интересное место для хранения информации о конфигурации - это DNS / LDAP. Это будет работать для небольшого количества небольших фрагментов информации, но вам не нужно придерживаться 1-й нормальной формы - рассмотрите, например, SPF .

Инфраструктура поддерживает кэширование, репликацию и распространение. Следовательно, он хорошо работает для очень больших инфраструктур.

Системы контроля версий

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


6

Ну, было бы сложно хранить данные конфигурации вашей базы данных в базе данных - не так ли?

Но на самом деле это довольно самоуверенный вопрос, потому что любой стиль действительно работает, и все дело в предпочтениях. Лично я бы выбрал переменную конфигурации, а не константы - обычно потому, что мне не нравятся вещи в глобальном пространстве, если это не необходимо. Ни одна из функций в моей кодовой базе не должна иметь возможность легко получить доступ к моему паролю базы данных (кроме логики подключения к базе данных), поэтому я бы использовал его здесь, а затем, вероятно, уничтожил бы его.

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


2

Define сделает константу доступной везде в вашем классе без необходимости использования global, в то время как переменная требует global в классе, я бы использовал DEFINE. но опять же, если параметры db должны измениться во время выполнения программы, вы можете придерживаться переменной.


каков самый быстрый способ выполнить PHP? константа или вар?
Али Акбар Азизи

1
@CooPer Определение констант происходит значительно медленнее, чем определение переменных. Но пользоваться ими немного быстрее. Поскольку они будут использоваться в одном месте, переменные в целом будут обеспечивать более высокую производительность.
Colin M

"Значительно" - это немного тяжелое слово для этого, если вы посмотрите на это с этой точки зрения, возможно, вам стоит связаться с ребятами из php-разработчиков и попросить их удалить постоянную поддержку!
phpalix

@phpalix Определение константы может быть в 10-20 раз медленнее, чем определение переменной с тем же значением. Я бы сказал, это важно. Однако, если вы часто используете константу в своем приложении, это может окупиться. Но не рекомендуется создавать константу для ее однократного использования.
Colin M

2

Если вы думаете, что по какой-либо причине вы будете использовать более 1 дБ, используйте переменную, потому что вы сможете изменить один параметр, чтобы переключиться на совершенно другой db. Т.е. для тестирования, автобэкапа и т.д.


2

Вы можете создать статические свойства класса конфигурации

class Config 
{
    static $dbHost = 'localhost';
    static $dbUsername = 'user';
    static $dbPassword  = 'pass';
}

тогда вы можете просто использовать его:

Config::$dbHost  

Иногда в своих проектах я использую шаблон проектирования SINGLETON для доступа к данным конфигурации. Очень удобно в использовании.

Зачем?

Например, в вашем проекте есть 2 источника данных. И вы можете выбрать, какая из них включена.

  • mysql
  • json

Где-то в файле конфигурации вы выбираете:

$dataSource = 'mysql' // or 'json'

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

Пример:

Конфиг:

class Config 
{
  // ....
  static $dataSource = 'mysql';
  / .....
}

Синглтон-класс:

class AppConfig
{
    private static $instance;
    private $dataSource;

    private function __construct()
    {
        $this->init();
    }

    private function init()
    {
        switch (Config::$dataSource)
        {
            case 'mysql':
                $this->dataSource = new StorageMysql();
                break;
            case 'json':
                $this->dataSource = new StorageJson();
                break;
            default:
                $this->dataSource = new StorageMysql();
        }
    }

    public static function getInstance()
    {
        if (empty(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function getDataSource()
    {
        return $this->dataSource;
    }
}

... и где-то в вашем коде (например, в каком-то классе обслуживания):

$container->getItemsLoader(AppConfig::getInstance()->getDataSource()) // getItemsLoader need Object of specific data source class by dependency injection

Мы можем получить объект AppConfig из любого места в системе и всегда получать одну и ту же копию (благодаря static). В конструкторе вызывается метод init () класса, который гарантирует только одно выполнение. Тело Init () проверяет значение config $ dataSource и создает новый объект определенного класса источника данных. Теперь наш скрипт может получить объект и работать с ним, даже не зная, какая конкретная реализация существует на самом деле.


1

Обычно я создаю один файл conn.php, содержащий подключения к моей базе данных. Затем я включаю этот файл во все файлы, требующие запросов к базе данных.


1
я знаю это, но как вы сохраняете файл базы данных с переменной или константой? и почему?
Али Акбар Азизи

0

Вот мой путь.

<?php

define('DEBUG',0);

define('PRODUCTION',1);



#development_mode : DEBUG / PRODUCTION

$development_mode = PRODUCTION;



#Website root path for links

$app_path = 'http://192.168.0.234/dealer/';



#User interface files path

$ui_path = 'ui/';

#Image gallery path

$gallery_path = 'ui/gallery/';


$mysqlserver = "localhost";
$mysqluser = "root";
$mysqlpass = "";
$mysqldb = "dealer_plus";

?>

Любые сомнения, пожалуйста, прокомментируйте


3
Здравствуйте! Не могли бы вы привести пример использования? Спасибо
Ник
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.