Créer un fichier de configuration en PHP

101

Je souhaite créer un fichier de configuration pour mon projet PHP, mais je ne suis pas sûr de la meilleure façon de procéder.

J'ai jusqu'à présent 3 idées.

Variable à 1 utilisation

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

2-Utiliser Const

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

Base de données à 3 utilisations

J'utiliserai la configuration dans les classes, donc je ne suis pas sûr de la meilleure façon ou s'il existe une meilleure façon.

Ali Akbar Azizi
la source
12
4) Utilisez un fichier ini. 5) Utilisez un fichier YAML. 6) Utilisez un fichier JSON. 7) ... Il y a tellement de façons ... Définissez au moins quelques critères pour juger, il n'y a pas de «meilleur» global.
deceze
@deceze qu'est-ce que le jeûne? (mémoire et rapide)
Ali Akbar Azizi
Cela devrait être une lecture intéressante pour vous alors: stackoverflow.com/questions/823352
...
1
J'utilise la façon dont Laravel le fait (quand je n'utilise pas Laravel). Je crée une classe qui charge un fichier de configuration spécifique en fonction du nom d'hôte. Je l'appelle ensuite en utilisantConfig::get('key'); . pastebin.com/4iTnjEuM
MisterBla

Réponses:

218

Une manière simple mais élégante est de créer un config.phpfichier (ou ce que vous appelez) qui renvoie simplement un tableau:

<?php

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

Puis:

$configs = include('config.php');
Hugo Mota
la source
10
J'aime aussi cette méthode - je pense que c'est plus propre que de simplement déclarer une variable dans un fichier inclus et en supposant qu'elle sera là dans votre script
Colin M
Où se trouve cette méthode de réponse pour créer un fichier de configuration? Pour php novice comme moi?
Luka
@Luka Vous pouvez utiliser la fonction var_export .
Hasan Bayat
77

Utiliser un fichier INI est une solution flexible et puissante! PHP a une fonction native pour le gérer correctement. Par exemple, il est possible de créer un fichier INI comme celui-ci:

app.ini

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

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

Donc, la seule chose que vous devez faire est d'appeler:

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

Ensuite, vous pouvez accéder facilement aux définitions à l'aide du $initableau.

echo $ini['db_name'];     // mydatabase
echo $ini['db_user'];     // myuser
echo $ini['db_password']; // mypassword
echo $ini['app_email'];   // [email protected]

IMPORTANT: pour des raisons de sécurité, le fichier INI doit se trouver dans un dossier non public

Marcio Mazzucato
la source
Est-ce également sûr à utiliser? Si un utilisateur devinait le chemin d'accès au fichier ini et s'y rendait dans son navigateur, verrait-il ce qu'il y a dans le fichier?
NickGames
1
@NickGames, vous devez mettre le fichier dans un dossier non public, sinon vous serez sous un risque de sécurité sérieux
Marcio Mazzucato
2
@NickGames, s'il vous plaît regarder le 1 commentaire dans Docs de parse_ini_file ()
R Picheta
19
J'aime cette approche. Astuce bonus: renommez le fichier en app.ini.php. Puis ajoutez à la première ligne ;<?php die(); ?>. Dans le cas où ce fichier apparaît accidentellement dans un dossier public, il sera traité comme un fichier PHP et mourra à la première ligne. Si le fichier est lu avec parse_ini_file, il traitera la première ligne comme un commentaire en raison de l'extension ;.
andreas
1
Remarque: Si une valeur du fichier ini contient des caractères non alphanumériques , elle doit être placée entre guillemets ( "). Par exemple, tout mot de passe contient des caractères non alphanumériques.
Key Shang
24

J'utilise une légère évolution de l » @hugo_leonardo solution :

<?php

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

?>

Cela vous permet d'utiliser la syntaxe de l'objet lorsque vous incluez le php: $configs->hostau lieu de$configs['host'] .

De plus, si votre application a des configurations dont vous avez besoin côté client (comme pour une application Angular), vous pouvez avoir ce config.phpfichier contenant toutes vos configurations (centralisées dans un fichier au lieu d'un pour JavaScript et un pour PHP). L'astuce serait alors d'avoir un autre fichier PHP qui echone contiendrait que les informations côté client (pour éviter d'afficher des informations que vous ne voulez pas afficher comme une chaîne de connexion à la base de données). Appelez-le dire get_app_info.php:

<?php

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

?>

Ce qui précède en supposant que votre config.phpcontient un app_infoparamètre:

<?php

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

?>

Les informations de votre base de données restent donc côté serveur, mais les informations de votre application sont accessibles depuis votre JavaScript, avec par exemple un $http.get('get_app_info.php').then(...);type d'appel.

BoDeX
la source
pourquoi en faire un objet?
TheCrazyProfessor
4
En faire un objet facilite grandement la gestion des données. Il permet par exemple d'obtenir tous les app_infoparamètres du JavaScript sous forme de JSON avec un minimum de lignes de code.
BoDeX
Les objets ont aussi un effet secondaire d'être passés par référence depuis PHP 5. Cela peut ou non être une bonne chose. Les tableaux sont passés par valeur (mais implémentés en tant que COW), il peut donc être préférable d'utiliser des tableaux de configuration plutôt que des objets de configuration.
Mikko Rantalainen
@BoDeX J'aime toujours cette façon et semble être l'approche privilégiée dans la plupart des articles, mais comment y accéder via la classe? J'ai lu dans l'article sur la sécurité que la création de variables globales n'est pas une bonne idée, alors que suggérez-vous?
Kevlwig
22

Les options que je vois avec des avantages / faiblesses relatifs sont:

Mécanismes basés sur des fichiers

Ceux-ci nécessitent que votre code recherche dans des emplacements spécifiques pour trouver le fichier ini. C'est un problème difficile à résoudre et qui revient toujours dans les grandes applications PHP. Cependant, vous devrez probablement résoudre le problème afin de trouver le code PHP qui sera incorporé / réutilisé au moment de l'exécution.

Les approches courantes pour cela sont de toujours utiliser des répertoires relatifs, ou de rechercher à partir du répertoire courant vers le haut pour trouver un fichier nommé exclusivement dans le répertoire de base de l'application.

Les formats de fichiers courants utilisés pour les fichiers de configuration sont le code PHP, les fichiers au format ini, JSON, XML, YAML et PHP sérialisé

Code PHP

Cela offre une grande flexibilité pour représenter différentes structures de données et (en supposant qu'il soit traité via include ou require) le code analysé sera disponible à partir du cache d'opcode - ce qui donne un avantage en termes de performances.

Le include_path fournit un moyen pour extraire les emplacements potentiels du fichier sans s'appuyer sur du code supplémentaire.

D'autre part, l'une des principales raisons de séparer la configuration du code est de séparer les responsabilités. Il fournit une route pour injecter du code supplémentaire dans le runtime.

Si la configuration est créée à partir d'un outil, il peut être possible de valider les données dans l'outil, mais il n'y a pas de fonction standard pour échapper les données à intégrer dans le code PHP comme cela existe pour le HTML, les URL, les instructions MySQL, les commandes shell ... .

Données sérialisées Ceci est relativement efficace pour de petites quantités de configuration (jusqu'à environ 200 éléments) et permet d'utiliser n'importe quelle structure de données PHP. Il nécessite très peu de code pour créer / analyser le fichier de données (vous pouvez donc à la place consacrer vos efforts à vous assurer que le fichier n'est écrit qu'avec l'autorisation appropriée).

L'échappement du contenu écrit dans le fichier est géré automatiquement.

Puisque vous pouvez sérialiser des objets, cela crée une opportunité pour appeler du code simplement en lisant le fichier de configuration (la méthode magique __wakeup).

Fichier structuré

Le stocker en tant que fichier INI comme suggéré par Marcel ou JSON ou XML fournit également une simple api pour mapper le fichier dans une structure de données PHP (et à l'exception de XML, pour échapper aux données et créer le fichier) tout en éliminant l'invocation du code vulnérabilité utilisant des données PHP sérialisées.

Il aura des caractéristiques de performance similaires aux données sérialisées.

Stockage de base de données

Ceci est mieux pris en compte lorsque vous avez une énorme quantité de configuration mais que vous êtes sélectif dans ce qui est nécessaire pour la tâche actuelle - j'ai été surpris de constater qu'à environ 150 éléments de données, il était plus rapide de récupérer les données d'une instance MySQL locale que de désérialiser un fichier de données.

OTOH ce n'est pas un bon endroit pour stocker les informations d'identification que vous utilisez pour vous connecter à votre base de données!

L'environnement d'exécution

Vous pouvez définir des valeurs dans l' environnement d'exécution dans lequel PHP s'exécute.

Cela supprime toute exigence pour le code PHP de chercher dans un endroit spécifique pour la configuration. OTOH, il ne s'adapte pas bien à de grandes quantités de données et est difficile à changer universellement au moment de l'exécution.

Sur le client

Un endroit que je n'ai pas mentionné pour stocker les données de configuration est le client. Là encore, la surcharge du réseau signifie que cela ne s'adapte pas bien à de grandes quantités de configuration. Et puisque l'utilisateur final a le contrôle sur les données, elles doivent être stockées dans un format où toute falsification est détectable (c'est-à-dire avec une signature cryptographique) et ne doit contenir aucune information qui est compromise par leur divulgation (c'est-à-dire cryptée de manière réversible).

Inversement, cela présente de nombreux avantages pour stocker des informations sensibles appartenant à l'utilisateur final - si vous ne les stockez pas sur le serveur, elles ne peuvent pas être volées à partir de là.

Répertoires réseau Un autre endroit intéressant pour stocker les informations de configuration est DNS / LDAP. Cela fonctionnera pour un petit nombre de petites informations - mais vous n'avez pas besoin de vous en tenir à la 1ère forme normale - considérez, par exemple, SPF .

L'infrastructure prend en charge la mise en cache, la réplication et la distribution. Cela fonctionne donc bien pour les très grandes infrastructures.

Systèmes de contrôle de version

La configuration, tout comme le code, doit être gérée et contrôlée par version - par conséquent, obtenir la configuration directement à partir de votre système VC est une solution viable. Mais cela s'accompagne souvent d'une surcharge de performances significative, d'où la mise en cache peut être souhaitable.

symcbean
la source
6

Eh bien, il serait difficile de stocker les données de configuration de votre base de données dans une base de données, vous ne pensez pas?

Mais en réalité, c'est une question assez forte car n'importe quel style fonctionne vraiment et c'est une question de préférence. Personnellement, j'opterais pour une variable de configuration plutôt que des constantes - généralement parce que je n'aime pas les choses dans l'espace global sauf si nécessaire. Aucune des fonctions de ma base de code ne devrait pouvoir accéder facilement au mot de passe de ma base de données (à l'exception de ma logique de connexion à la base de données) - donc je l'utilise là-bas et je le détruirai probablement.

Edit : pour répondre à votre commentaire - aucun des mécanismes d'analyse ne serait le plus rapide (ini, json, etc.) - mais ce ne sont pas non plus les parties de votre application sur lesquelles vous auriez vraiment besoin de vous concentrer, car la différence de vitesse serait être négligeable sur ces petits fichiers.

Colin M
la source
2

Define rendra la constante disponible partout dans votre classe sans avoir besoin d'utiliser global, tandis que la variable nécessite global dans la classe, j'utiliserais DEFINE. mais encore une fois, si les paramètres db devaient changer pendant l'exécution du programme, vous voudrez peut-être vous en tenir à la variable.

phpalix
la source
quelle est la manière la plus rapide d'exécuter le php? const ou var?
Ali Akbar Azizi
1
@CooPer La définition de constantes est beaucoup plus lente que la définition de variables. Mais leur utilisation est légèrement plus rapide. Étant donné que ceux-ci seront utilisés en un seul endroit, les variables offriraient globalement de meilleures performances.
Colin M
"Significativement" est un mot un peu lourd pour cela, si vous le regardez de cette façon, vous devriez peut-être contacter les développeurs php et leur demander de supprimer le support constant!
phpalix
@phpalix La définition d'une constante peut être de 10 à 20 fois plus lente que la définition d'une variable avec la même valeur. Je dirais que c'est important. Cependant, si vous utilisez beaucoup la constante dans toute votre application, cela peut très bien porter ses fruits. Mais créer une constante pour l'utiliser une fois n'est pas conseillé.
Colin M
2

Si vous pensez que vous utiliserez plus de 1 db pour une raison quelconque, utilisez la variable car vous pourrez modifier un paramètre pour passer à une base de données entièrement différente. Ie pour les tests, la sauvegarde automatique, etc.

trigun0x2
la source
2

Vous pouvez créer une classe de configuration avec des propriétés statiques

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

alors vous pouvez simplement l'utiliser:

Config::$dbHost  

Parfois, dans mes projets, j'utilise un modèle de conception SINGLETON pour accéder aux données de configuration. Il est très confortable à utiliser.

Pourquoi?

Par exemple, vous avez 2 sources de données dans votre projet. Et vous pouvez choisir la sorcière d'entre eux est activée.

  • mysql
  • json

Quelque part dans le fichier de configuration, vous choisissez:

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

Lorsque vous changez la source entière de l'application, passez à une nouvelle source de données, fonctionne correctement et n'a pas besoin de changement de code.

Exemple:

Config:

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

... et quelque part dans votre code (par exemple dans une classe de service):

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

Nous pouvons obtenir un objet AppConfig à partir de n'importe quel endroit du système et toujours obtenir la même copie (grâce à statique). La méthode init () de la classe est appelée Dans le constructeur, ce qui garantit une seule exécution. Init () body checks La valeur de la config $ dataSource et crée un nouvel objet d'une classe de source de données spécifique. Maintenant, notre script peut obtenir un objet et opérer dessus, sans même savoir quelle implémentation spécifique existe réellement.

Sebastian Skurnóg
la source
1

Je finis normalement par créer un seul fichier conn.php qui a mes connexions à ma base de données. Ensuite, j'inclus ce fichier dans tous les fichiers qui nécessitent des requêtes de base de données.

Mihir Chhatre
la source
1
Je le sais, mais comment enregistrez-vous votre fichier de base de données, avec variable ou const? et pourquoi?
Ali Akbar Azizi
0

Voici mon chemin.

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

?>

Si vous avez des doutes, veuillez commenter

Alok Rajasukumaran
la source
3
salut! Pourriez-vous s'il vous plaît mettre un exemple d'utilisation? Merci
Nick