Een configuratiebestand maken in PHP

Ik wil een configuratiebestand maken voor mijn PHP-project, maar ik weet niet zeker hoe ik dit het beste kan doen.

Ik heb tot nu toe 3 ideeën.

1-Gebruik variabele

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

Constante 2 keer gebruiken

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

3-Gebruik database

Ik zal de configuratie in klassen gebruiken, dus ik weet niet zeker welke manier de beste is of dat er een betere manier is.


Antwoord 1, autoriteit 100%

Een eenvoudige maar elegante manier is om een config.php-bestand (of hoe je het ook noemt) te maken dat alleen een array retourneert:

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

En dan:

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

Antwoord 2, autoriteit 36%

Gebruik een INI-bestand is een flexibele en krachtige oplossing! PHP heeft een native functieom het correct af te handelen. Het is bijvoorbeeld mogelijk om een INI-bestand als volgt te maken:

app.ini

[database]
db_name     = mydatabase
db_user     = myuser
db_password = mypassword
[application]
app_email = [email protected]
app_url   = myapp.com

Dus het enige dat u hoeft te doen is bellen:

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

Dan kun je gemakkelijk toegang krijgen tot de definities met behulp van de $iniarray.

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

BELANGRIJK:Om veiligheidsredenen moet het INI-bestand in een niet-openbare map staan


Antwoord 3, autoriteit 12%

Ik gebruik een kleine evolutie van de oplossingvan @hugo_leonardo:

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

Hierdoor kunt u de objectsyntaxis gebruiken wanneer u de php : $configs->hostopneemt in plaats van $configs['host'].

Als je app configuraties heeft die je nodig hebt aan de clientzijde (zoals voor een Angular-app), kun je dit config.php-bestand al je configuraties laten bevatten (gecentraliseerd in één bestand in plaats van één voor JavaScript en één voor PHP). De truc zou dan zijn om een ander PHP-bestand te hebben dat alleen de client-side-info zou echo(om te voorkomen dat informatie wordt weergegeven die u niet wilt weergeven, zoals een databaseverbindingsreeks). Noem het, zeg get_app_info.php:

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

Het bovenstaande, ervan uitgaande dat uw config.phpeen app_infoparameter bevat:

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

Dus de informatie van uw database blijft aan de serverzijde, maar uw app-informatie is toegankelijk vanuit uw JavaScript, met bijvoorbeeld een $http.get('get_app_info.php').then(...);type oproep.


Antwoord 4, autoriteit 10%

De opties die ik zie met relatieve voordelen/zwakheden zijn:

Op bestanden gebaseerde mechanismen

Deze vereisen dat uw code op specifieke locaties zoekt om het ini-bestand te vinden. Dit is een moeilijk op te lossen probleem en een die altijd opduikt in grote PHP-applicaties. U zult echter waarschijnlijk het probleem moeten oplossen om de PHP-code te vinden die tijdens runtime wordt opgenomen/hergebruikt.

Veelgebruikte benaderingen hiervoor zijn om altijd relatieve mappen te gebruiken, of om vanaf de huidige map naar boven te zoeken om een bestand te vinden dat uitsluitend in de basismap van de toepassing wordt genoemd.

Veelgebruikte bestandsindelingen voor configuratiebestanden zijn PHP-code, ini-geformatteerde bestanden, JSON, XML, YAML en geserialiseerde PHP

PHP-code

Dit biedt een enorme hoeveelheid flexibiliteit voor het weergeven van verschillende gegevensstructuren, en (ervan uitgaande dat het wordt verwerkt via include of required) zal de geparseerde code beschikbaar zijn vanuit de opcode-cache – wat een prestatievoordeel oplevert.

De include_pathbiedt een manier om te abstraheren de potentiële locaties van het bestand zonder te vertrouwen op aanvullende code.

Aan de andere kant is een van de belangrijkste redenen om configuratie en code te scheiden, het scheiden van verantwoordelijkheden. Het biedt een route voor het injecteren van extra code in de runtime.

Als de configuratie is gemaakt op basis van een tool, is het misschien mogelijk om de gegevens in de tool te valideren, maar er is geen standaardfunctie om gegevens te ontsnappen voor insluiting in PHP-code, zoals die bestaat voor HTML, URL’s, MySQL-instructies, shell-opdrachten ….

Geserialiseerde gegevens
Dit is relatief efficiënt voor kleine hoeveelheden configuratie (tot ongeveer 200 items) en maakt het gebruik van elke PHP-datastructuur mogelijk. Er is heel weinig code nodig om het gegevensbestand te maken/parseren (u kunt er in plaats daarvan voor zorgen dat het bestand alleen met de juiste autorisatie wordt geschreven).

Ontsnappen van inhoud die naar het bestand is geschreven, wordt automatisch afgehandeld.

Omdat je objecten kunt serialiseren, ontstaat er een mogelijkheid om code aan te roepen door simpelweg het configuratiebestand te lezen (de __wakeup magic-methode).

Gestructureerd bestand

Het opslaan als een INI-bestand zoals voorgesteld door Marcel of JSON of XML biedt ook een eenvoudige api om het bestand toe te wijzen aan een PHP-gegevensstructuur (en met uitzondering van XML, om aan de gegevens te ontsnappen en het bestand te maken) terwijl het elimineren de kwetsbaarheid voor het aanroepen van code met behulp van geserialiseerde PHP-gegevens.

Het zal vergelijkbare prestatiekenmerken hebben als de geserialiseerde gegevens.

Databaseopslag

Dit kan het beste worden overwogen wanneer u een enorme hoeveelheid configuratie hebt, maar selectief bent in wat nodig is voor de huidige taak. Ik was verrast toen ik ontdekte dat het met ongeveer 150 gegevensitems sneller was om de gegevens op te halen uit een lokale MySQL instantie dan om een gegevensbestand te deserialiseren.

OTOH is geen goede plek om de inloggegevens op te slaan die u gebruikt om verbinding te maken met uw database!

De uitvoeringsomgeving

Je kunt waarden instellen in de uitvoeringsomgevingwaarin PHP wordt uitgevoerd.

Dit verwijdert elke vereiste voor de PHP-code om op een specifieke plaats naar de configuratie te zoeken. OTOH schaalt niet goed op grote hoeveelheden gegevens en is moeilijk universeel te wijzigen tijdens runtime.

Op de klant

Een plaats die ik niet heb genoemd voor het opslaan van configuratiegegevens is bij de client. Nogmaals, de netwerkoverhead betekent dat dit niet goed opschaalt naar grote hoeveelheden configuratie. En aangezien de eindgebruiker controle heeft over de gegevens, moet deze worden opgeslagen in een formaat waarin geknoei kan worden gedetecteerd (dwz met een cryptografische handtekening) en mag deze geen informatie bevatten die wordt aangetast door de openbaarmaking ervan (dwz omkeerbaar versleuteld).

Omgekeerd heeft dit veel voordelen voor het opslaan van gevoelige informatie die eigendom is van de eindgebruiker – als u dit niet op de server opslaat, kan het daar niet worden gestolen.

Netwerkmappen
Een andere interessante plaats om configuratie-informatie op te slaan is in DNS / LDAP. Dit werkt voor een klein aantal kleine stukjes informatie – maar u hoeft zich niet aan de 1e normaalvorm te houden – denk bijvoorbeeld aan SPF.

De infrastructuur ondersteunt caching, replicatie en distributie. Daarom werkt het goed voor zeer grote infrastructuren.

Versiecontrolesystemen

Configuratie, zoals code, moet worden beheerd en versiebeheerd – daarom is het een haalbare oplossing om de configuratie rechtstreeks van uw VC-systeem te krijgen. Maar vaak brengt dit een aanzienlijke prestatieoverhead met zich mee, dus caching kan aan te raden zijn.


Antwoord 5, autoriteit 3%

Nou – het zou nogal moeilijk zijn om uw databaseconfiguratiegegevens in een database op te slaan – vindt u niet?

Maar echt, dit is een behoorlijk eigenzinnige vraag, want elke stijl werkt echt en het is allemaal een kwestie van voorkeur. Persoonlijk zou ik voor een configuratievariabele gaan in plaats van constanten – in het algemeen omdat ik dingen in de globale ruimte niet leuk vind, tenzij dat nodig is. Geen van de functies in mijn codebase zou gemakkelijk toegang moeten hebben tot mijn databasewachtwoord (behalve mijn databaseverbindingslogica) – dus ik zou het daar gebruiken en het dan waarschijnlijk vernietigen.

Bewerken: om uw opmerking te beantwoorden – geen van de parseermechanismen zou de snelste zijn (ini, json, enz.) – maar het zijn ook niet de delen van uw toepassing die u echt zou moeten focussen op het optimaliseren, aangezien het snelheidsverschil verwaarloosbaar zou zijn bij zulke kleine bestanden.


Antwoord 6

U kunt een configuratieklasse maken met statische eigenschappen

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

dan kun je het eenvoudig gebruiken:

Config::$dbHost  

Soms gebruik ik in mijn projecten een ontwerppatroon SINGLETON om toegang te krijgen tot configuratiegegevens. Het is zeer comfortabel in gebruik.

Waarom?

U hebt bijvoorbeeld 2 gegevensbronnen in uw project. En u kunt kiezen welke van hen is ingeschakeld.

  • mysql
  • json

Ergens in het configuratiebestand dat u kiest:

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

Als je van bron verandert, moet de hele app overschakelen naar een nieuwe gegevensbron, werkt prima en hoeft de code niet te wijzigen.

Voorbeeld:

Config:

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

Eenpersoonsles:

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

… en ergens in uw code (bijv. in een bepaalde serviceklasse):

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

We kunnen een AppConfig-object vanaf elke plaats in het systeem verkrijgen en altijd dezelfde kopie krijgen (dankzij static). De methode init () van de klasse heet
In de constructor, die slechts één uitvoering garandeert. Init() lichaamscontroles
De waarde van de config $dataSource, en maak een nieuw object van een specifieke gegevensbronklasse. Nu kan ons script een object krijgen en erop werken, zonder het te weten
zelfs welke specifieke implementatie daadwerkelijk bestaat.


Antwoord 7

Define maakt de constante overal in uw klas beschikbaar zonder dat u globaal hoeft te gebruiken, terwijl de variabele globaal in de klas vereist, ik zou DEFINE gebruiken. maar nogmaals, als de db-parameters zouden veranderen tijdens de uitvoering van het programma, wil je misschien bij de variabele blijven.


Antwoord 8

Als je denkt dat je om wat voor reden dan ook meer dan 1 db gaat gebruiken, ga dan voor de variabele omdat je één parameter kunt wijzigen om over te schakelen naar een geheel andere db. D.w.z. voor testen, automatische back-up, enz.


Antwoord 9

Hier is mijn manier.

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

Bij twijfel graag commentaar


Antwoord 10

Normaal maak ik uiteindelijk een enkel conn.php-bestand met mijn databaseverbindingen.
Dan neem ik dat bestand op in alle bestanden waarvoor databasequery’s nodig zijn.


Antwoord 11

Hoe zit het met zoiets?

class Configuration
{
    private $config;
    public function __construct($configIniFilePath)
    {
        $this->config = parse_ini_file($configIniFilePath, true);
    }
    /**
     * Gets the value for the specified setting name.
     *
     * @param string $name the setting name
     * @param string $section optional, the name of the section containing the
     *     setting
     * @return string|null the value of the setting, or null if it doesn't exist
     */
    public function getConfiguration($name, $section = null)
    {
        $configValue = null;
        if ($section === null) {
            if (array_key_exists($name, $this->config)) {
                $configValue = $this->config[$name];
            }
        } else {
            if (array_key_exists($section, $this->config)) {
                $sectionSettings = $this->config[$section];
                if (array_key_exists($name, $sectionSettings)) {
                    $configValue = $sectionSettings[$name];
                }
            }
        }
        return $configValue;
    }
}

Antwoord 12

als ik een configuratiebestand heb zoals config.conf (het kan htttp://example.com/config.conf zijn)

user=cacom
version = 2021608
status= true

dit is mijn functie:

function readFileConfig($UrlOrFilePath){
    $lines = file($UrlOrFilePath);
    $config = array();
    foreach ($lines as $l) {
        preg_match("/^(?P<key>.*)=(\s+)?(?P<value>.*)/", $l, $matches);
        if (isset($matches['key'])) {
            $config[trim($matches['key'])] = trim($matches['value']);
        }
    }
    return $config;
}

we kunnen gebruiken:

$urlRemote = 'http://example.com/default-config.conf';
$localConfigFile = "/home/domain/public_html/config.conf";
$localConfigFile2 = "config.conf";
print_r(readFileConfig($localConfigFile2));
print_r(readFileConfig($localConfigFile));
print_r(readFileConfig($urlRemote));

Other episodes