Heim >PHP-Framework >Laravel >Einführung in das Laden und Lesen von ENV unter dem Laravel-Framework

Einführung in das Laden und Lesen von ENV unter dem Laravel-Framework

不言
不言nach vorne
2018-10-22 14:17:043716Durchsuche

Der Inhalt dieses Artikels ist eine Einführung in das Laden und Lesen von ENV unter dem Laravel-Framework. Ich hoffe, dass er für Sie hilfreich ist.

Laravel lädt die .env-Datei beim Start in das Projekt. Oft ist es sinnvoll, unterschiedliche Konfigurationen für unterschiedliche Umgebungen zu haben, in denen die Anwendung ausgeführt wird. Beispielsweise möchten Sie möglicherweise eine Test-MySQL-Datenbank lokal verwenden und möchten, dass das Projekt automatisch zur MySQL-Produktionsdatenbank wechselt, nachdem es online geht. In diesem Artikel werden die Verwendung von Env-Dateien und die Quellcodeanalyse ausführlich vorgestellt.

Verwendung von Env-Dateien

Env-Einstellungen für mehrere Umgebungen

Die Anzahl der Env-Dateien in einem Projekt ist oft gleich der Anzahl der Umgebungen im Projekt Wenn ein Projekt über Entwicklungs-, Test- und Produktionsumgebungen verfügt, sollten im Projekt drei Umgebungskonfigurationsdateien vorhanden sein: .env.dev, .env.test und .env.prod, die der Umgebung entsprechen. Die Konfigurationselemente in den drei Dateien sollten genau gleich sein und die spezifischen Konfigurationswerte sollten entsprechend den Anforderungen jeder Umgebung festgelegt werden.

Der nächste Schritt besteht darin, dem Projekt das Laden unterschiedlicher Umgebungsdateien entsprechend der Umgebung zu ermöglichen. Es gibt drei spezifische Methoden, die je nach Nutzungsgewohnheiten ausgewählt werden können:

Setzen Sie die Umgebungsvariable APP_ENV fastcgi_param APP_ENV dev in der Nginx-Konfigurationsdatei der Umgebung;

Setzen Sie die Umgebungsvariable des Benutzer, der PHP auf dem Server ausführt, fügen beispielsweise export APP_ENV dev

im WWW-Benutzerverzeichnis /home/www/.bashrc hinzu und führen cp .env.dev .env

in der kontinuierlichen Integration aus Aufgabe oder Bereitstellungsskript des Bereitstellungsprojekts: Laravel lädt die entsprechenden Dateien .env.dev und .env.test basierend auf den in env('APP_ENV') geladenen Variablenwerten. Insbesondere besteht, wie später im Quellcode erläutert wird, die dritte Methode, die leichter zu verstehen ist, darin, die Konfigurationsdatei der Umgebung beim Bereitstellen des Projekts in die .env-Datei zu überschreiben, sodass keine zusätzlichen Einstellungen in der Umgebung vorgenommen werden müssen System und Nginx.

Der Pfad und Dateiname der benutzerdefinierten ENV-Datei

Die env-Datei wird standardmäßig im Stammverzeichnis des Projekts abgelegt und stellt Benutzern eine benutzerdefinierte ENV zur Verfügung Dateipfad oder Datei Die Funktion mit dem Namen

Wenn Sie beispielsweise den Umgebungspfad anpassen möchten, können Sie die Methode useEnvironmentPath der Anwendungsinstanz in app.php im Bootstrap-Ordner verwenden:

$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

$app->useEnvironmentPath('/customer/path')

Wenn Sie den Namen der Env-Datei anpassen möchten, können Sie die Methode „loadEnvironmentFrom“ der Anwendungsinstanz in app.php im Bootstrap-Ordner verwenden:

$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

$app->loadEnvironmentFrom('customer.env')

Laravel lädt die ENV-Konfiguration

Laravel lädt ENV in Dies geschieht in der LoadEnvironmentVariables-Phase des Bootstrap-Prozesses, bevor das Framework die Anfrage verarbeitet.

Werfen wir einen Blick auf den Quellcode von IlluminateFoundationBootstrapLoadEnvironmentVariables, um zu analysieren, wie Laravel die Konfiguration in env lädt.

<?php
namespace Illuminate\Foundation\Bootstrap;
use Dotenv\Dotenv;
use Dotenv\Exception\InvalidPathException;
use Symfony\Component\Console\Input\ArgvInput;
use Illuminate\Contracts\Foundation\Application;
class LoadEnvironmentVariables
{
    /**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        if ($app->configurationIsCached()) {
            return;
        }

        $this->checkForSpecificEnvironmentFile($app);

        try {
            (new Dotenv($app->environmentPath(), $app->environmentFile()))->load();
        } catch (InvalidPathException $e) {
            //
        }
    }

    /**
     * Detect if a custom environment file matching the APP_ENV exists.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    protected function checkForSpecificEnvironmentFile($app)
    {
        if ($app->runningInConsole() && ($input = new ArgvInput)->hasParameterOption('--env')) {
            if ($this->setEnvironmentFilePath(
                $app, $app->environmentFile().'.'.$input->getParameterOption('--env')
            )) {
                return;
            }
        }

        if (! env('APP_ENV')) {
            return;
        }

        $this->setEnvironmentFilePath(
            $app, $app->environmentFile().'.'.env('APP_ENV')
        );
    }

    /**
     * Load a custom environment file.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @param  string  $file
     * @return bool
     */
    protected function setEnvironmentFilePath($app, $file)
    {
        if (file_exists($app->environmentPath().'/'.$file)) {
            $app->loadEnvironmentFrom($file);

            return true;
        }

        return false;
    }
}

Laravel prüft in seiner Startmethode Bootstrap, ob die Konfiguration zwischengespeichert wurde und bestimmt, welche Umgebungsdatei angewendet werden soll. Für die ersten beiden der drei Methoden zum Laden von Konfigurationsdateien basierend auf der oben genannten Umgebung: Da APP_ENV in der System- oder Nginx-Umgebungsvariablen festgelegt ist, legt Laravel den korrekten spezifischen Pfad der Konfigurationsdatei entsprechend dem Wert von APP_ENV in der Methode checkForSpecificEnvironmentFile fest, z. B. .env.dev oder .env.test, und für Im dritten Fall handelt es sich um die Standard-.env. Einzelheiten finden Sie in der folgenden checkForSpecificEnvironmentFile und im Quellcode der beiden Methoden in der zugehörigen Anwendung:

protected function checkForSpecificEnvironmentFile($app)
{
    if ($app->runningInConsole() && ($input = new ArgvInput)->hasParameterOption('--env')) {
        if ($this->setEnvironmentFilePath(
            $app, $app->environmentFile().'.'.$input->getParameterOption('--env')
        )) {
            return;
        }
    }

    if (! env('APP_ENV')) {
        return;
    }

    $this->setEnvironmentFilePath(
        $app, $app->environmentFile().'.'.env('APP_ENV')
    );
}

namespace Illuminate\Foundation;
class Application ....
{

    public function environmentPath()
    {
        return $this->environmentPath ?: $this->basePath;
    }
    
    public function environmentFile()
    {
        return $this->environmentFile ?: '.env';
    }
}

Nachdem der Pfad der zu lesenden Konfigurationsdatei ermittelt wurde , der nächste Schritt besteht darin, die konfigurierte Umgebung zu laden.

(new Dotenv($app->environmentPath(), $app->environmentFile()))->load();

Laravel verwendet die PHP-Version von Dotenv vlucas/phpdotenv

class Dotenv
{
    public function __construct($path, $file = '.env')
    {
        $this->filePath = $this->getFilePath($path, $file);
        $this->loader = new Loader($this->filePath, true);
    }

    public function load()
    {
        return $this->loadData();
    }

    protected function loadData($overload = false)
    {
        $this->loader = new Loader($this->filePath, !$overload);

        return $this->loader->load();
    }
}

Es verlässt sich auf /Dotenv/Loader, um Daten zu laden:

class Loader
{
    public function load()
    {
        $this->ensureFileIsReadable();

        $filePath = $this->filePath;
        $lines = $this->readLinesFromFile($filePath);
        foreach ($lines as $line) {
            if (!$this->isComment($line) && $this->looksLikeSetter($line)) {
                $this->setEnvironmentVariable($line);
            }
        }

        return $lines;
    }
}

Wenn Loader die Konfiguration liest, wird die readLinesFromFile Funktion wird die Dateifunktion verwenden, um die Konfiguration zeilenweise aus der Datei in das Array einzulesen, dann die Kommentare, die mit # beginnen, auszuschließen und die setEnvironmentVariable-Methode für die Zeilen aufzurufen, die = im Inhalt enthalten, um die Umgebungsvariablen in den Dateizeilen zu konfigurieren in das Projekt. :

namespace Dotenv;
class Loader
{
    public function setEnvironmentVariable($name, $value = null)
    {
        list($name, $value) = $this->normaliseEnvironmentVariable($name, $value);

        $this->variableNames[] = $name;

        // Don't overwrite existing environment variables if we're immutable
        // Ruby's dotenv does this with `ENV[key] ||= value`.
        if ($this->immutable && $this->getEnvironmentVariable($name) !== null) {
            return;
        }

        // If PHP is running as an Apache module and an existing
        // Apache environment variable exists, overwrite it
        if (function_exists('apache_getenv') && function_exists('apache_setenv') && apache_getenv($name)) {
            apache_setenv($name, $value);
        }

        if (function_exists('putenv')) {
            putenv("$name=$value");
        }

        $_ENV[$name] = $value;
        $_SERVER[$name] = $value;
    }
    
    public function getEnvironmentVariable($name)
    {
        switch (true) {
            case array_key_exists($name, $_ENV):
                return $_ENV[$name];
            case array_key_exists($name, $_SERVER):
                return $_SERVER[$name];
            default:
                $value = getenv($name);
                return $value === false ? null : $value; // switch getenv default to null
        }
    }
}

<span style="font-family: 微软雅黑, Microsoft YaHei;">Dotenv实例化Loader的时候把Loader对象的$immutable属性设置成了false,Loader设置变量的时候如果通过getEnvironmentVariable方法读取到了变量值,那么就会跳过该环境变量的设置。所以Dotenv默认情况下不会覆盖已经存在的环境变量,这个很关键,比如说在docker的容器编排文件里,我们会给PHP应用容器设置关于Mysql容器的两个环境变量</span><br>

    environment:
      - "DB_PORT=3306"
      - "DB_HOST=database"

Nach dem Festlegen der Umgebungsvariablen im Container wird dies auch dann der Fall sein, wenn der DB_HOST in der env-Datei von Homestead mithilfe der env-Funktion gelesen wird immer noch der Wert sein, der zuvor im Container festgelegt wurde. Der Wert der Umgebungsvariablen DB_HOST ist „Datenbank“ (der Container-Link in Docker verwendet standardmäßig den Dienstnamen. In der Orchestrierungsdatei habe ich den Dienstnamen des MySQL-Containers auf „Datenbank“ festgelegt Der PHP-Container muss über den Datenbankhost eine Verbindung zum MySQL-Container herstellen. Denn wenn wir automatisierte Tests in der kontinuierlichen Integration durchführen, testen wir normalerweise im Container, daher ist es sehr wichtig, dass Dotenv keine vorhandenen Umgebungsvariablen überschreibt. Auf diese Weise kann ich nur den Wert der Umgebungsvariablen im Container festlegen, um den Test abzuschließen Es ist nicht erforderlich, die Env-Datei im Projekt zu ändern. Stellen Sie das Projekt einfach direkt nach Abschluss des Tests in der Umgebung bereit.

Wenn die Umgebungsvariable überprüft wird und nicht vorhanden ist, setzt Dotenv die Umgebungsvariable über die in PHP integrierte Funktion putenv auf die Umgebung und speichert sie außerdem in den beiden globalen Variablen $_ENV und $_SERVER .

Env-Konfiguration im Projekt lesen

In der Laravel-Anwendung können Sie die Funktion env() verwenden, um den Wert der Umgebungsvariablen zu lesen, z. B. get der HOST der Datenbank:

env('DB_HOST`, 'localhost');

Der zweite an die env-Funktion übergebene Wert ist der „Standardwert“. Wenn für den angegebenen Schlüssel keine Umgebungsvariable vorhanden ist, wird dieser Wert verwendet.

Werfen wir einen Blick auf den Quellcode der env-Funktion:

function env($key, $default = null)
{
    $value = getenv($key);

    if ($value === false) {
        return value($default);
    }

    switch (strtolower($value)) {
        case 'true':
        case '(true)':
            return true;
        case 'false':
        case '(false)':
            return false;
        case 'empty':
        case '(empty)':
            return '';
        case 'null':
        case '(null)':
            return;
    }

    if (strlen($value) > 1 && Str::startsWith($value, '"') && Str::endsWith($value, '"')) {
        return substr($value, 1, -1);
    }

    return $value;
}

Sie liest Umgebungsvariablen direkt über die in PHP integrierte Funktion getenv.

Wir haben gesehen, dass beim Laden der Konfiguration und beim Lesen der Konfiguration zwei Funktionen putenv und getenv verwendet werden. Die von putenv festgelegten Umgebungsvariablen bleiben nur während der Anforderung bestehen und die vorherigen Einstellungen der Umgebung werden nach Ende der Anforderung wiederhergestellt. Denn wenn das Konfigurationselement „variables_order“ in php.ini zu GPCS wird und kein E enthält, können die Umgebungsvariablen nicht über $_ENV im PHP-Programm gelesen werden. Daher wird putenv verwendet, um die Umgebungsvariablen dynamisch festzulegen, sodass Entwickler dies nicht tun müssen Achten Sie auf die Serverkonfiguration. Darüber hinaus werden die für den laufenden Benutzer auf dem Server konfigurierten Umgebungsvariablen mit allen vom Benutzer gestarteten Prozessen geteilt, wodurch private Umgebungsvariablen wie DB_PASSWORD und API_KEY nicht gut geschützt werden können Mithilfe dieser Konfigurationsinformationen kann die Methode getenv die Umgebungsvariablen des Systems und die von putenv dynamisch festgelegten Umgebungsvariablen abrufen.

Das obige ist der detaillierte Inhalt vonEinführung in das Laden und Lesen von ENV unter dem Laravel-Framework. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen