Створення конфігураційного файлу в PHP


101

Я хочу створити конфігураційний файл для мого PHP-проекту, але я не впевнений, що найкращий спосіб це зробити.

У мене поки що 3 ідеї.

Одноразова змінна

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

Конст

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 що таке пост? (пам’ять і швидко)
Алі Акбар Азізі

Це повинно бути цікаво читати для вас , то: stackoverflow.com/questions/823352 / ...
eithed

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

Відповіді:


218

Один простий, але елегантний спосіб - створити 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, ти повинен помістити файл у папку, що не є загальнодоступною, інакше ти будеш серйозно загрожувати безпеці
Marcio Mazzucato,

2
@NickGames, подивіться на 1 коментар у Документах parse_ini_file ()
R Picheta

19
Мені подобається такий підхід. Бонусна порада: перейменуйте файл на app.ini.php. Потім додайте до першого рядка ;<?php die(); ?>. У випадку, якщо цей файл випадково з'явиться у загальнодоступній папці, він буде розглядатися як файл PHP і загине в першому рядку. Якщо файл читається за допомогою parse_ini_file, він буде розглядати перший рядок як коментар через ;.
andreas

1
Примітка: Якщо значення у файлі ini містить будь -які буквено-цифрові символи, його потрібно укласти у подвійні лапки ( "). Наприклад, будь-який пароль містить нелітерально-цифрові символи.
Key Shang

24

Я використовую невелику еволюцію @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

4
Якщо зробити його об’єктом, це значно полегшує обробку даних. Це дозволяє, наприклад, отримати всі app_infoпараметри до JavaScript як JSON з мінімальними рядками коду.
BoDeX

Об'єкти також мають побічний ефект передачі за посиланням з PHP 5. Це може бути, а може і не добре. Масиви передаються за значенням (але реалізовані як COW), тому може бути краще використовувати масиви конфігурації замість конфігураційних об'єктів.
Мікко Ранталайнен

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

22

Варіанти, які я бачу з відносними достоїнствами та недоліками:

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

Вони вимагають, щоб ваш код шукав певні місця, щоб знайти файл ini. Цю проблему важко вирішити, і вона завжди виникає у великих програмах PHP. Однак вам, ймовірно, доведеться вирішити проблему, щоб знайти код PHP, який включається / повторно використовується під час виконання.

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

Загальними форматами файлів, що використовуються для конфігураційних файлів, є PHP-код, відформатовані файли ini, JSON, XML, YAML та серіалізований PHP

PHP-код

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

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

З іншого боку, однією з головних причин відокремлення конфігурації від коду є розділення відповідальності. Він надає маршрут для введення додаткового коду в середовище виконання.

Якщо конфігурація створюється за допомогою інструменту, можливо, можливо перевірити дані в інструменті, але не існує стандартної функції для виходу даних для вбудовування в PHP-код, яка існує для HTML, URL-адрес, операторів MySQL, команд оболонки ... .

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

Екранування вмісту, записаного у файл, обробляється автоматично.

Оскільки ви можете серіалізувати об'єкти, це створює можливість для виклику коду, просто прочитавши файл конфігурації (магічний метод __wakeup).

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

Зберігання його як файлу INI, як запропоновано Marcel або JSON або XML, також забезпечує простий API для відображення файлу в структурі даних PHP (і, за винятком XML, для уникнення даних та створення файлу), усуваючи при цьому виклик коду вразливість із використанням серіалізованих даних PHP.

Він буде мати характеристики, подібні до серіалізованих даних.

Зберігання бази даних

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

OTOH - це не найкраще місце для зберігання облікових даних, які ви використовуєте для підключення до бази даних!

Середовище виконання

Ви можете встановити значення у середовищі виконання, в якому працює PHP.

Це усуває будь-які вимоги щодо пошуку коду PHP у певному місці для конфігурації. OTOH він погано масштабується до великих обсягів даних і його важко змінити універсально під час виконання.

На клієнта

Одне місце, про яке я не згадував для зберігання даних конфігурації, знаходиться у клієнта. Знову ж накладні витрати на мережу означають, що це не дуже добре масштабується до великої кількості конфігурації. І оскільки кінцевий користувач має контроль над даними, він повинен зберігатися у форматі, де будь-яке втручання можна виявити (тобто за допомогою криптографічного підпису), і не повинно містити жодної інформації, яка загрожує його розкриттям (тобто оборотно зашифрована).

І навпаки, це має багато переваг для зберігання конфіденційної інформації, якою володіє кінцевий користувач - якщо ви не зберігаєте її на сервері, її неможливо вкрасти звідти.

Мережеві каталоги Ще одне цікаве місце для зберігання інформації про конфігурацію - це DNS / LDAP. Це буде працювати для невеликої кількості невеликих частин інформації - але вам не потрібно дотримуватися 1-ї звичайної форми - розгляньте, наприклад, SPF .

Інфраструктура підтримує кешування, реплікацію та розподіл. Отже, він добре працює для дуже великих інфраструктур.

Системи контролю версій

Конфігурацією, як і кодом, слід керувати та контролювати версію - отже, отримання конфігурації безпосередньо з вашої системи VC є життєздатним рішенням. Але часто це пов'язано зі значними накладними витратами, тому кешування може бути доцільним.


6

Ну - це було б якось важко зберігати дані конфігурації бази даних у базі даних - не думаєте?

Але насправді, це досить вдумливе питання, оскільки будь-який стиль працює насправді, і все це питання переваг. Особисто я б скористався змінною конфігурації, а не константами - загалом тому, що мені не подобаються речі у глобальному просторі, якщо це не потрібно. Жодна з функцій в моїй кодовій базі не повинна мати легкого доступу до мого пароля бази даних (крім логіки підключення до бази даних) - тому я б використовував його там, а потім, ймовірно, знищив.

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


2

Define зробить константу доступною скрізь у вашому класі без необхідності використовувати глобальну, тоді як змінна вимагає глобальної в класі, я б використовував DEFINE. але знову ж таки, якщо параметри db повинні змінитися під час виконання програми, ви можете дотримуватися змінної.


який швидкий спосіб виконати php? const чи var?
Алі Акбар Азізі

1
@CooPer Визначення констант значно повільніше, ніж визначення змінних. Але використовувати їх трохи швидше. Оскільки вони будуть використовуватися в одному місці, змінні загалом пропонують більш високу продуктивність.
Колін М

"Істотно" - це трохи важке слово для цього, якщо ви хочете дивитись на це так, можливо, вам слід зв'язатися з хлопцями php dev і попросити їх усунути постійну підтримку!
phpalix

@phpalix Визначення константи може бути в 10-20 разів повільнішим, ніж визначення змінної з однаковим значенням. Я б сказав, що це важливо. Однак, якщо ви постійно використовуєте константу протягом усього додатку - це цілком може окупитися. Але створювати константу, щоб використовувати її один раз, не рекомендується.
Колін М

2

Якщо ви вважаєте, що з якихось причин ви будете використовувати більше 1 дБ, перейдіть до змінної, оскільки ви зможете змінити один параметр, щоб перейти на зовсім інший дБ. Тобто для тестування, автозавантаження тощо.


2

Ви можете створити статичні властивості відьми класу config

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 з будь-якого місця в системі і завжди отримати однакову копію (завдяки статичному). Метод init () класу називається In конструктор, який гарантує лише одне виконання. Тело Init () перевіряє значення config $ dataSource і створює новий об'єкт певного класу джерела даних. Тепер наш скрипт може отримати об’єкт і оперувати ним, навіть не знаючи, яка конкретна реалізація насправді існує.


1

Зазвичай я створюю єдиний файл conn.php, який має підключення до бази даних. Потім я включаю цей файл у всі файли, які потребують запитів до бази даних.


1
я це знаю, але як ви зберігаєте файл бази даних зі змінною чи const? і чому?
Алі Акбар Азізі

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.