Creazione di un file di configurazione in PHP


101

Voglio creare un file di configurazione per il mio progetto PHP, ma non sono sicuro di quale sia il modo migliore per farlo.

Finora ho 3 idee.

1-Usa variabile

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

2-Usa Const

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

3-Usa database

Userò la configurazione nelle classi, quindi non sono sicuro di quale sia il modo migliore o se esista un modo migliore.


12
4) Usa un file ini. 5) Usa un file YAML. 6) Usa un file JSON. 7) ... Ci sono tanti modi ... Definisci almeno dei criteri in base ai quali giudicare, non esiste un "migliore" complessivo.
inganno

@deceze qual è il modo di digiuno? (memoria e veloce)
Ali Akbar Azizi

Questo dovrebbe essere una lettura interessante per voi allora: stackoverflow.com/questions/823352/...
eithed

1
Uso il modo in cui lo fa Laravel (quando non lo uso). Creo una classe che carica un file di configurazione specifico a seconda del nome host. Quindi lo chiamo usando Config::get('key');. pastebin.com/4iTnjEuM
MisterBla

Risposte:


217

Un modo semplice ma elegante è creare un config.phpfile (o come lo chiami) che restituisce solo un array:

<?php

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

E poi:

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

10
Mi piace anche questo metodo - penso che sia più pulito della semplice dichiarazione di una variabile in un file incluso e supponendo che sia presente nel tuo script
Colin M

Dov'è questo metodo di risposta per creare il file di configurazione? Per i principianti di php come me?
Luka

@Luka Puoi usare la funzione var_export .
Hasan Bayat,

77

Utilizzare un file INI è una soluzione flessibile e potente! PHP ha una funzione nativa per gestirlo correttamente. Ad esempio, è possibile creare un file INI come questo:

app.ini

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

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

Quindi l'unica cosa che devi fare è chiamare:

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

Quindi puoi accedere facilmente alle definizioni usando l' $iniarray.

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

IMPORTANTE: per motivi di sicurezza il file INI deve trovarsi in una cartella non pubblica


Anche questo è sicuro da usare? Se un utente indovinasse il percorso del file ini e vi accedesse nel browser, vedrebbe cosa c'è nel file?
NickGames

1
@ NickGames, devi mettere il file in una cartella non pubblica, altrimenti sarai esposto a un serio rischio per la sicurezza
Marcio Mazzucato

2
@ NickGames, per favore guarda il 1 commento in Docs of parse_ini_file ()
R Picheta

19
Mi piace questo approccio. Suggerimento bonus: rinomina il file in app.ini.php. Quindi aggiungi alla prima riga ;<?php die(); ?>. Nel caso in cui questo file appaia accidentalmente in una cartella pubblica, verrà trattato come file PHP e morirà alla prima riga. Se il file viene letto con parse_ini_file, tratterà la prima riga come un commento a causa del ;.
andreas

1
Nota: se un valore nel file ini contiene caratteri non alfanumerici , deve essere racchiuso tra virgolette doppie ( "). Ad esempio, qualsiasi password contiene caratteri non alfanumerici.
Key Shang

24

Io uso una leggera evoluzione del @hugo_leonardo 's soluzione :

<?php

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

?>

Ciò ti consente di utilizzare la sintassi dell'oggetto quando includi php: $configs->hostinvece di $configs['host'].

Inoltre, se la tua app ha delle configurazioni necessarie sul lato client (come per un'app Angular), puoi fare in modo che questo config.phpfile contenga tutte le tue configurazioni (centralizzate in un file invece di uno per JavaScript e uno per PHP). Il trucco sarebbe quindi avere un altro file PHP che contenga echosolo le informazioni lato client (per evitare di mostrare informazioni che non si desidera mostrare come stringa di connessione al database). Chiamalo dire get_app_info.php:

<?php

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

?>

Quanto sopra assumendo che config.phpcontenga un app_infoparametro:

<?php

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

?>

Quindi le informazioni del tuo database rimangono sul lato server, ma le informazioni della tua app sono accessibili dal tuo JavaScript, ad esempio con un $http.get('get_app_info.php').then(...);tipo di chiamata.


perché renderlo un oggetto?
TheCrazyProfessor

4
Rendendolo un oggetto rende la gestione dei dati molto più semplice. Consente, ad esempio, di ottenere tutti i app_infoparametri in JavaScript come JSON con righe di codice minime.
BoDeX

Gli oggetti hanno anche un effetto collaterale di essere passati per riferimento a partire da PHP 5. Può essere o non essere una buona cosa. Gli array vengono passati per valore (ma implementati come COW), quindi potrebbe essere meglio usare gli array di configurazione invece degli oggetti di configurazione.
Mikko Rantalainen

@BoDeX mi piace sempre in questo modo e sembra essere l'approccio preferito nella maggior parte degli articoli, ma come potrei accedervi tramite il corso? Ho letto nell'articolo sulla sicurezza che la creazione di variabili globali non è una buona idea, quindi cosa suggerisci?
Kevlwig,

22

Le opzioni che vedo con relativi meriti / punti deboli sono:

Meccanismi basati su file

Questi richiedono che il codice cerchi in posizioni specifiche per trovare il file ini. Questo è un problema difficile da risolvere e che si presenta sempre nelle grandi applicazioni PHP. Tuttavia, probabilmente dovrai risolvere il problema per trovare il codice PHP che viene incorporato / riutilizzato in fase di esecuzione.

Gli approcci comuni a questo sono usare sempre le directory relative, o cercare dalla directory corrente verso l'alto per trovare un file denominato esclusivamente nella directory di base dell'applicazione.

I formati di file comuni utilizzati per i file di configurazione sono codice PHP, file formattati ini, JSON, XML, YAML e PHP serializzato

Codice PHP

Ciò fornisce un'enorme quantità di flessibilità per rappresentare diverse strutture di dati e (supponendo che venga elaborato tramite include o require) il codice analizzato sarà disponibile dalla cache del codice operativo, offrendo un vantaggio in termini di prestazioni.

L'include_path fornisce un mezzo per astrarre i potenziali posizioni dei file senza fare affidamento su codice aggiuntivo.

D'altra parte, uno dei motivi principali per separare la configurazione dal codice è separare le responsabilità. Fornisce un percorso per l'inserimento di codice aggiuntivo nel runtime.

Se la configurazione viene creata da uno strumento, potrebbe essere possibile convalidare i dati nello strumento, ma non esiste una funzione standard per sfuggire ai dati da incorporare nel codice PHP come esiste per HTML, URL, istruzioni MySQL, comandi shell ... .

Dati serializzati Questo è relativamente efficiente per piccole quantità di configurazione (fino a circa 200 elementi) e consente l'uso di qualsiasi struttura dati PHP. Richiede pochissimo codice per creare / analizzare il file di dati (quindi puoi invece spendere i tuoi sforzi per garantire che il file sia scritto solo con l'autorizzazione appropriata).

L'escape del contenuto scritto nel file viene gestita automaticamente.

Poiché è possibile serializzare gli oggetti, crea un'opportunità per invocare il codice semplicemente leggendo il file di configurazione (il metodo magico __wakeup).

File strutturato

Archiviarlo come file INI come suggerito da Marcel o JSON o XML fornisce anche una semplice API per mappare il file in una struttura dati PHP (e con l'eccezione di XML, per sfuggire ai dati e creare il file) eliminando la chiamata del codice vulnerabilità utilizzando dati PHP serializzati.

Avrà caratteristiche di prestazione simili ai dati serializzati.

Archiviazione del database

Questo è meglio considerato quando si dispone di un'enorme quantità di configurazione ma si è selettivi in ​​ciò che è necessario per l'attività corrente: sono stato sorpreso di scoprire che con circa 150 elementi di dati era più veloce recuperare i dati da un'istanza MySQL locale rispetto a deserializzare un file di dati.

OTOH non è un buon posto per archiviare le credenziali che usi per connetterti al tuo database!

L'ambiente di esecuzione

Puoi impostare i valori nell'ambiente di esecuzione in cui è in esecuzione PHP.

Ciò rimuove qualsiasi requisito per il codice PHP di cercare in un luogo specifico per la configurazione. OTOH non si adatta bene a grandi quantità di dati ed è difficile da modificare universalmente in fase di esecuzione.

Sul cliente

Un posto che non ho menzionato per memorizzare i dati di configurazione è nel client. Anche in questo caso il sovraccarico di rete significa che questo non si adatta bene a grandi quantità di configurazione. E poiché l'utente finale ha il controllo sui dati, questi devono essere archiviati in un formato in cui qualsiasi manomissione sia rilevabile (ovvero con una firma crittografica) e non deve contenere alcuna informazione compromessa dalla sua divulgazione (ovvero crittografata in modo reversibile).

Al contrario, questo ha molti vantaggi per la memorizzazione di informazioni sensibili di proprietà dell'utente finale: se non le si memorizza sul server, non possono essere rubate da lì.

Directory di rete Un altro luogo interessante per memorizzare le informazioni di configurazione è in DNS / LDAP. Questo funzionerà per un piccolo numero di piccole informazioni - ma non è necessario attenersi alla prima forma normale - considera, ad esempio, SPF .

L'infrastruttura supporta la memorizzazione nella cache, la replica e la distribuzione. Quindi funziona bene per infrastrutture molto grandi.

Sistemi di controllo della versione

La configurazione, come il codice, dovrebbe essere gestita e la versione controllata, quindi ottenere la configurazione direttamente dal tuo sistema VC è una soluzione praticabile. Ma spesso ciò comporta un notevole sovraccarico delle prestazioni, quindi la memorizzazione nella cache potrebbe essere consigliabile.


6

Bene, sarebbe un po 'difficile memorizzare i dati di configurazione del database in un database, non credi?

Ma in realtà, questa è una domanda piuttosto ostinata perché qualsiasi stile funziona davvero ed è tutta una questione di preferenza. Personalmente, preferirei una variabile di configurazione piuttosto che delle costanti, generalmente perché non mi piacciono le cose nello spazio globale a meno che non sia necessario. Nessuna delle funzioni nella mia base di codice dovrebbe essere in grado di accedere facilmente alla password del mio database (tranne la mia logica di connessione al database), quindi la userei lì e probabilmente la distruggerei.

Modifica : per rispondere al tuo commento - nessuno dei meccanismi di analisi sarebbe il più veloce (ini, json, ecc.) - Ma non sono nemmeno le parti della tua applicazione su cui dovresti davvero concentrarti sull'ottimizzazione poiché la differenza di velocità lo sarebbe essere trascurabile su file così piccoli.


2

Define renderà la costante disponibile ovunque nella tua classe senza bisogno di usare global, mentre la variabile richiede global nella classe, io userei DEFINE. ma ancora una volta, se i parametri db dovessero cambiare durante l'esecuzione del programma potresti voler restare con la variabile.


qual è il modo più veloce per eseguire il php? const o var?
Ali Akbar Azizi

1
@CooPer La definizione delle costanti è notevolmente più lenta della definizione delle variabili. Ma usarli è leggermente più veloce. Poiché questi verranno utilizzati in un unico luogo, le variabili offrirebbero nel complesso prestazioni più elevate.
Colin M

"Significativamente" è una parola un po 'pesante per questo, se la guardi in questo modo, forse dovresti contattare i ragazzi di php dev e chiedere loro di rimuovere il supporto costante!
phpalix

@phpalix La definizione di una costante può essere da 10 a 20 volte più lenta rispetto alla definizione di una variabile con lo stesso valore. Direi che è significativo. Tuttavia, se utilizzi la costante in modo intenso in tutta l'applicazione, potrebbe essere molto utile. Ma creare una costante per usarlo una volta non è consigliato.
Colin M

2

Se pensi di utilizzare più di 1 db per qualsiasi motivo, vai con la variabile perché sarai in grado di modificare un parametro per passare a un db completamente diverso. Vale a dire per test, backup automatico, ecc.


2

È possibile creare una classe di configurazione con proprietà statiche

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

quindi puoi usarlo semplicemente:

Config::$dbHost  

A volte nei miei progetti utilizzo un design pattern SINGLETON per accedere ai dati di configurazione. È molto comodo da usare.

Perché?

Ad esempio, hai 2 origini dati nel tuo progetto. E puoi scegliere la strega di loro è abilitata.

  • mysql
  • json

Da qualche parte nel file di configurazione che scegli:

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

Quando si cambia l'origine dell'intera app, passare alla nuova origine dati, funziona bene e non è necessario modificare il codice.

Esempio:

Configurazione:

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

Classe Singleton:

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;
    }
}

... e da qualche parte nel codice (ad es. in qualche classe di servizio):

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

Possiamo ottenere un oggetto AppConfig da qualsiasi punto del sistema e ottenere sempre la stessa copia (grazie a static). Il metodo init () della classe è chiamato In the constructor, che garantisce una sola esecuzione. Init () body controlla il valore di config $ dataSource e crea un nuovo oggetto di una specifica classe di origine dati. Ora il nostro script può ottenere l'oggetto e operare su di esso, non sapendo nemmeno quale implementazione specifica esista effettivamente.


1

Normalmente finisco per creare un singolo file conn.php che ha le mie connessioni al database. Quindi includo quel file in tutti i file che richiedono query sul database.


1
lo so, ma come si salva il file del database, con variabile o const? e perché?
Ali Akbar Azizi

0

Ecco la mia strada.

<?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";

?>

Eventuali dubbi si prega di commentare


3
Ciao! Potresti per favore mettere un esempio di utilizzo? Grazie
Nick
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.