Erstellen einer Konfigurationsdatei in PHP

101

Ich möchte eine Konfigurationsdatei für mein PHP-Projekt erstellen, bin mir jedoch nicht sicher, wie dies am besten funktioniert.

Ich habe bisher 3 Ideen.

1-Use Variable

$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-Datenbank verwenden

Ich werde die Konfiguration in Klassen verwenden, daher bin ich mir nicht sicher, welcher Weg der beste wäre oder ob es einen besseren gibt.

Ali Akbar Azizi
quelle
12
4) Verwenden Sie eine INI-Datei. 5) Verwenden Sie eine YAML-Datei. 6) Verwenden Sie eine JSON-Datei. 7) ... Es gibt so viele Möglichkeiten ... Definieren Sie einige Kriterien, anhand derer Sie zumindest beurteilen können, dass es insgesamt kein "Bestes" gibt.
Täuschung
@deceze was ist der fastete Weg? (Erinnerung und schnell)
Ali Akbar Azizi
Dies sollte dann eine interessante Lektüre für Sie sein: stackoverflow.com/questions/823352/…
Uhr
1
Ich benutze die Art und Weise, wie Laravel es macht (wenn ich Laravel nicht benutze). Ich erstelle eine Klasse, die abhängig vom Hostnamen eine bestimmte Konfigurationsdatei lädt. Ich nenne es dann mit Config::get('key');. pastebin.com/4iTnjEuM
MisterBla

Antworten:

217

Eine einfache, aber elegante Möglichkeit besteht darin, eine config.phpDatei (oder wie auch immer Sie sie nennen) zu erstellen , die nur ein Array zurückgibt:

<?php

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

Und dann:

$configs = include('config.php');
Hugo Mota
quelle
10
Ich mag diese Methode auch - ich denke, sie ist sauberer, als nur eine Variable in einer enthaltenen Datei zu deklarieren und davon auszugehen, dass sie in Ihrem Skript enthalten sein wird
Colin M
Wo befindet sich in dieser Antwort die Methode zum Erstellen einer Konfigurationsdatei? Für PHP-Anfänger wie mich?
Luka
@Luka Sie können die Funktion var_export verwenden.
Hasan Bayat
76

Die Verwendung einer INI-Datei ist eine flexible und leistungsstarke Lösung! PHP hat eine native Funktion , um richtig damit umzugehen. Zum Beispiel ist es möglich, eine INI-Datei wie folgt zu erstellen:

app.ini

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

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

Das einzige, was Sie tun müssen, ist anzurufen:

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

Dann können Sie mit dem $iniArray einfach auf die Definitionen zugreifen .

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

WICHTIG: Aus Sicherheitsgründen muss sich die INI-Datei in einem nicht öffentlichen Ordner befinden

Marcio Mazzucato
quelle
Ist das auch sicher zu bedienen? Wenn ein Benutzer den Pfad zur INI-Datei erraten und in seinem Browser dorthin gehen würde, würde er dann sehen, was in der Datei enthalten ist?
NickGames
1
@ NickGames, Sie müssen die Datei in einem nicht öffentlichen Ordner ablegen, sonst sind Sie einem ernsthaften Sicherheitsrisiko ausgesetzt
Marcio Mazzucato
2
@ NickGames, bitte schauen Sie sich den 1 Kommentar in Docs von parse_ini_file ()
R Picheta
19
Ich mag diesen Ansatz. Bonus-Tipp: Benennen Sie die Datei in app.ini.php um. Fügen Sie dann zur ersten Zeile hinzu ;<?php die(); ?>. Falls diese Datei versehentlich in einem öffentlichen Ordner angezeigt wird, wird sie als PHP-Datei behandelt und stirbt in der ersten Zeile. Wenn die Datei mit gelesen wird parse_ini_file, wird die erste Zeile aufgrund der Datei als Kommentar behandelt ;.
Andreas
1
Hinweis: Wenn ein Wert in der INI-Datei nicht alphanumerische Zeichen enthält, muss er in doppelte Anführungszeichen ( ") gesetzt werden. Beispielsweise enthält jedes Kennwort nicht alphanumerische Zeichen.
Key Shang
24

Ich verwende eine leichte Weiterentwicklung der Lösung von @hugo_leonardo :

<?php

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

?>

Auf diese Weise können Sie die Objektsyntax verwenden, wenn Sie php: $configs->hostanstelle von einfügen $configs['host'].

Wenn Ihre App Konfigurationen enthält, die Sie auf der Clientseite benötigen (wie bei einer Angular-App), können config.phpSie festlegen , dass diese Datei alle Ihre Konfigurationen enthält (zentral in einer Datei anstelle einer für JavaScript und einer für PHP). Der Trick wäre dann, eine andere PHP-Datei zu haben, die echonur die clientseitigen Informationen enthält (um zu vermeiden, dass Informationen angezeigt werden, die nicht wie eine Datenbankverbindungszeichenfolge angezeigt werden sollen). Nennen wir es sagen get_app_info.php:

<?php

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

?>

Die obige Annahme, dass Ihr config.phpeinen app_infoParameter enthält :

<?php

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

?>

Die Informationen Ihrer Datenbank bleiben also auf der Serverseite, aber auf Ihre App-Informationen kann über Ihr JavaScript zugegriffen werden, beispielsweise mit einer $http.get('get_app_info.php').then(...);Art von Anruf.

BoDeX
quelle
warum es zu einem Objekt machen?
TheCrazyProfessor
4
Wenn Sie es zu einem Objekt machen, wird der Umgang mit den Daten erheblich vereinfacht. Es ermöglicht beispielsweise, alle app_infoParameter als JSON mit minimalen Codezeilen in das JavaScript zu übernehmen.
BoDeX
Objekte haben auch den Nebeneffekt, dass sie seit PHP 5 als Referenz übergeben werden. Dies kann eine gute Sache sein oder auch nicht. Arrays werden als Wert übergeben (aber als COW implementiert), daher ist es möglicherweise besser, Konfigurationsarrays anstelle von Konfigurationsobjekten zu verwenden.
Mikko Rantalainen
@BoDeX Ich mag diesen Weg immer und scheint der bevorzugte Ansatz in den meisten Artikeln zu sein, aber wie würde ich über die Klasse darauf zugreifen? Ich habe in einem Sicherheitsartikel gelesen, dass das Erstellen globaler Variablen keine gute Idee ist. Was schlagen Sie also vor?
Kevlwig
22

Die Optionen, die ich mit relativen Vorzügen / Schwächen sehe, sind:

Dateibasierte Mechanismen

Dazu muss Ihr Code an bestimmten Stellen suchen, um die INI-Datei zu finden. Dies ist ein schwer zu lösendes Problem, das in großen PHP-Anwendungen immer wieder auftritt. Sie müssen das Problem jedoch wahrscheinlich lösen, um den PHP-Code zu finden, der zur Laufzeit integriert / wiederverwendet wird.

Übliche Ansätze hierfür sind die Verwendung relativer Verzeichnisse oder die Suche ab dem aktuellen Verzeichnis nach einer Datei, die ausschließlich im Basisverzeichnis der Anwendung benannt ist.

Übliche Dateiformate für Konfigurationsdateien sind PHP-Code, ini-formatierte Dateien, JSON, XML, YAML und serialisiertes PHP

PHP-Code

Dies bietet eine enorme Flexibilität bei der Darstellung verschiedener Datenstrukturen, und (vorausgesetzt, er wird über include oder require verarbeitet) der analysierte Code wird aus dem Opcode-Cache verfügbar sein, was einen Leistungsvorteil bietet.

Der include_path bietet eine Möglichkeit, die potenziellen Speicherorte der Datei zu abstrahieren, ohne auf zusätzlichen Code angewiesen zu sein.

Andererseits ist einer der Hauptgründe für die Trennung von Konfiguration und Code die Trennung von Verantwortlichkeiten. Es bietet eine Route zum Einfügen von zusätzlichem Code in die Laufzeit.

Wenn die Konfiguration aus einem Tool erstellt wird, können die Daten im Tool möglicherweise überprüft werden. Es gibt jedoch keine Standardfunktion, um Daten für die Einbettung in PHP-Code zu umgehen, wie sie für HTML, URLs, MySQL-Anweisungen, Shell-Befehle ... vorhanden sind. .

Serialisierte Daten Dies ist für kleine Konfigurationsmengen (bis zu etwa 200 Elemente) relativ effizient und ermöglicht die Verwendung einer beliebigen PHP-Datenstruktur. Das Erstellen / Analysieren der Datendatei erfordert nur sehr wenig Code (Sie können sich also stattdessen darum bemühen, sicherzustellen, dass die Datei nur mit entsprechender Berechtigung geschrieben wird).

Das Escaping von Inhalten, die in die Datei geschrieben wurden, erfolgt automatisch.

Da Sie Objekte serialisieren können, besteht die Möglichkeit, Code einfach durch Lesen der Konfigurationsdatei (die magische Methode __wakeup) aufzurufen.

Strukturierte Datei

Das Speichern als INI-Datei, wie von Marcel oder JSON oder XML vorgeschlagen, bietet auch eine einfache API, um die Datei einer PHP-Datenstruktur zuzuordnen (und mit Ausnahme von XML die Daten zu maskieren und die Datei zu erstellen), während der Code-Aufruf eliminiert wird Sicherheitslücke mit serialisierten PHP-Daten.

Es weist ähnliche Leistungsmerkmale wie die serialisierten Daten auf.

Datenbankspeicher

Dies wird am besten in Betracht gezogen, wenn Sie eine große Menge an Konfiguration haben, aber selektiv entscheiden, was für die aktuelle Aufgabe benötigt wird. Ich war überrascht, dass es bei etwa 150 Datenelementen schneller war, die Daten von einer lokalen MySQL-Instanz abzurufen als zu unserialisieren Sie eine Datendatei.

OTOH ist kein guter Ort, um die Anmeldeinformationen zu speichern, mit denen Sie eine Verbindung zu Ihrer Datenbank herstellen!

Die Ausführungsumgebung

Sie können Werte in der Ausführungsumgebung festlegen, in der PHP ausgeführt wird.

Dadurch entfällt die Notwendigkeit, dass der PHP-Code an einer bestimmten Stelle nach der Konfiguration sucht. OTOH lässt sich nicht gut auf große Datenmengen skalieren und ist zur Laufzeit nur schwer universell zu ändern.

Auf dem Client

Ein Ort, den ich zum Speichern von Konfigurationsdaten nicht erwähnt habe, ist der Client. Wiederum bedeutet der Netzwerk-Overhead, dass dies nicht gut auf große Konfigurationsmengen skaliert werden kann. Und da der Endbenutzer die Kontrolle über die Daten hat, müssen diese in einem Format gespeichert werden, in dem Manipulationen erkennbar sind (dh mit einer kryptografischen Signatur), und sollten keine Informationen enthalten, die durch ihre Offenlegung gefährdet sind (dh reversibel verschlüsselt sind).

Umgekehrt hat dies viele Vorteile beim Speichern vertraulicher Informationen, die dem Endbenutzer gehören. Wenn Sie diese nicht auf dem Server speichern, können sie von dort nicht gestohlen werden.

Netzwerkverzeichnisse Ein weiterer interessanter Ort zum Speichern von Konfigurationsinformationen ist DNS / LDAP. Dies funktioniert für eine kleine Anzahl kleiner Informationen - Sie müssen sich jedoch nicht an die erste Normalform halten - berücksichtigen Sie beispielsweise SPF .

Die Infrastruktur unterstützt das Zwischenspeichern, Replizieren und Verteilen. Daher funktioniert es gut für sehr große Infrastrukturen.

Versionskontrollsysteme

Konfiguration wie Code sollte verwaltet und versioniert werden - daher ist es eine praktikable Lösung, die Konfiguration direkt von Ihrem VC-System zu erhalten. Dies ist jedoch häufig mit einem erheblichen Leistungsaufwand verbunden, weshalb das Zwischenspeichern ratsam sein kann.

symcbean
quelle
6

Nun - es wäre schwierig, Ihre Datenbankkonfigurationsdaten in einer Datenbank zu speichern - finden Sie nicht?

Aber wirklich, dies ist eine ziemlich stark meinungsgebundene Frage, da jeder Stil wirklich funktioniert und alles eine Frage der Präferenz ist. Persönlich würde ich mich eher für eine Konfigurationsvariable als für Konstanten entscheiden - im Allgemeinen, weil ich Dinge im globalen Raum nicht mag, es sei denn, dies ist erforderlich. Keine der Funktionen in meiner Codebasis sollte leicht auf mein Datenbankkennwort zugreifen können (außer auf meine Datenbankverbindungslogik) - also würde ich es dort verwenden und es dann wahrscheinlich zerstören.

Bearbeiten : Um Ihren Kommentar zu beantworten - keiner der Analysemechanismen wäre der schnellste (ini, json usw.) -, aber sie sind auch nicht die Teile Ihrer Anwendung, auf die Sie sich wirklich konzentrieren müssten, da der Geschwindigkeitsunterschied dies tun würde bei so kleinen Dateien vernachlässigbar sein.

Colin M.
quelle
2

Durch Definieren wird die Konstante überall in Ihrer Klasse verfügbar, ohne dass global verwendet werden muss, während für die Variable global in der Klasse erforderlich ist. Ich würde DEFINE verwenden. Wenn sich die db-Parameter während der Programmausführung ändern sollten, möchten Sie möglicherweise bei der Variablen bleiben.

phpalix
quelle
Was ist der schnellste Weg, um das PHP auszuführen? const oder var?
Ali Akbar Azizi
1
@CooPer Das Definieren von Konstanten ist erheblich langsamer als das Definieren von Variablen. Aber mit ihnen geht es etwas schneller. Da diese an einem Ort verwendet werden, bieten Variablen insgesamt eine höhere Leistung.
Colin M
"Signifikant" ist ein etwas schweres Wort dafür. Wenn Sie es so sehen würden, sollten Sie sich vielleicht an die PHP-Entwickler wenden und sie bitten, die ständige Unterstützung zu entfernen!
Phpalix
@phpalix Das Definieren einer Konstante kann 10 bis 20 Mal langsamer sein als das Definieren einer Variablen mit demselben Wert. Ich würde sagen, das ist wichtig. Wenn Sie die Konstante jedoch während Ihrer gesamten Anwendung häufig verwenden, kann sich dies sehr gut auszahlen. Es wird jedoch nicht empfohlen, eine Konstante zu erstellen, um sie einmal zu verwenden.
Colin M
2

Wenn Sie glauben, dass Sie aus irgendeinem Grund mehr als 1 Datenbank verwenden, wählen Sie die Variable, da Sie einen Parameter ändern können, um zu einer völlig anderen Datenbank zu wechseln. Dh zum Testen, Autobackup usw.

trigun0x2
quelle
2

Sie können eine Konfigurationsklasse mit statischen Eigenschaften erstellen

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

dann können Sie es einfach verwenden:

Config::$dbHost  

Manchmal verwende ich in meinen Projekten ein Entwurfsmuster SINGLETON, um auf Konfigurationsdaten zuzugreifen. Es ist sehr bequem zu bedienen.

Warum?

Zum Beispiel haben Sie 2 Datenquellen in Ihrem Projekt. Und Sie können wählen, welche davon aktiviert ist.

  • MySQL
  • json

Irgendwo in der Konfigurationsdatei wählen Sie:

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

Wenn Sie die Quelle der gesamten App ändern, sollten Sie zu einer neuen Datenquelle wechseln. Funktionieren Sie einwandfrei und müssen Sie den Code nicht ändern.

Beispiel:

Konfiguration:

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

Singleton-Klasse:

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

... und irgendwo in Ihrem Code (z. B. in einer Serviceklasse):

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

Wir können ein AppConfig-Objekt von jedem Ort im System erhalten und immer dieselbe Kopie erhalten (dank statischer Aufladung). Die init () -Methode der Klasse heißt Im Konstruktor, was nur eine Ausführung garantiert. Init () body prüft den Wert der config $ dataSource und erstellt ein neues Objekt einer bestimmten Datenquellenklasse. Jetzt kann unser Skript ein Objekt abrufen und es bearbeiten, ohne zu wissen, welche spezifische Implementierung tatsächlich vorhanden ist.

Sebastian Skurnóg
quelle
1

Normalerweise erstelle ich eine einzelne conn.php-Datei mit meinen Datenbankverbindungen. Dann füge ich diese Datei in alle Dateien ein, die Datenbankabfragen erfordern.

Mihir Chhatre
quelle
1
Ich weiß das, aber wie speichern Sie Ihre Datenbankdatei, mit Variable oder const? und warum?
Ali Akbar Azizi
0

Hier ist mein Weg.

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

?>

Alle Zweifel bitte kommentieren

Alok Rajasukumaran
quelle
3
Hallo! Könnten Sie bitte ein Beispiel für die Verwendung nennen? Vielen Dank
Nick