Maison  >  Article  >  cadre php  >  Introduction au chargement et à la lecture d'ENV sous le framework Laravel

Introduction au chargement et à la lecture d'ENV sous le framework Laravel

不言
不言avant
2018-10-22 14:17:043702parcourir

Le contenu de cet article est une introduction au chargement et à la lecture d'ENV sous le framework Laravel. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Laravel chargera le fichier .env dans le projet au démarrage. Il est souvent utile d'avoir différentes configurations pour différents environnements dans lesquels l'application s'exécute. Par exemple, vous souhaiterez peut-être utiliser la base de données MySQL de test localement et souhaiter que le projet bascule automatiquement vers la base de données MySQL de production après sa mise en ligne. Cet article présentera en détail l'utilisation des fichiers env et l'analyse du code source.

Utilisation des fichiers Env

Paramètres d'environnement multi-environnements

Le nombre de fichiers d'environnement dans un projet est souvent le même que le nombre d'environnements dans le projet . Si un projet comporte des environnements de développement, de test et de production, le projet doit contenir trois fichiers de configuration d'environnement, .env.dev, .env.test et .env.prod, correspondant à l'environnement. Les éléments de configuration dans les trois fichiers doivent être exactement les mêmes et les valeurs de configuration spécifiques doivent être définies en fonction des besoins de chaque environnement.

L'étape suivante consiste à permettre au projet de charger différents fichiers d'environnement en fonction de l'environnement. Il existe trois méthodes spécifiques, qui peuvent être choisies en fonction des habitudes d'utilisation :

Définissez la variable d'environnement APP_ENV fastcgi_param APP_ENV dev dans le fichier de configuration nginx de l'environnement

Définissez la variable d'environnement de l'environnement ; utilisateur exécutant PHP sur le serveur, par exemple, ajoutez export APP_ENV dev

dans le /home/www/.bashrc de l'utilisateur www et exécutez cp .env.dev .env

dans l'intégration continue tâche ou script de déploiement du projet de déploiement. Pour les deux premières méthodes, Laravel chargera les fichiers correspondants .env.dev et .env.test en fonction des valeurs des variables chargées dans env('APP_ENV'). Plus précisément, comme nous le dirons plus tard dans le code source, la troisième méthode la plus facile à comprendre consiste à écraser le fichier de configuration de l'environnement dans le fichier .env lors du déploiement du projet, afin qu'il ne soit pas nécessaire de définir des paramètres supplémentaires dans le fichier de configuration de l'environnement. système et nginx.

Le chemin et le nom du fichier env personnalisé

Le fichier env est placé par défaut dans le répertoire racine du projet. Laravel fournit aux utilisateurs un ENV personnalisé. chemin de fichier ou fonction de fichier du nom,

Par exemple, si vous souhaitez personnaliser le chemin d'environnement, vous pouvez utiliser la méthode useEnvironmentPath de l'instance d'application dans app.php dans le dossier bootstrap :

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

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

Si vous souhaitez personnaliser, définissez le nom du fichier env et vous pouvez utiliser la méthode loadEnvironmentFrom de l'instance d'application dans app.php dans le dossier bootstrap :

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

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

Laravel se charge Configuration ENV

Laravel charge ENV est terminé dans la phase LoadEnvironmentVariables du processus d'amorçage avant que le framework ne traite la demande.

Jetons un coup d'œil au code source d'IlluminateFoundationBootstrapLoadEnvironmentVariables pour analyser comment Laravel charge la configuration dans env.

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

Dans sa méthode de démarrage bootstrap, Laravel vérifiera si la configuration a été mise en cache et déterminera quel fichier env doit être appliqué. Pour les deux premières des trois méthodes mentionnées ci-dessus, chargez le fichier de configuration selon. l'environnement., car APP_ENV est défini dans la variable d'environnement système ou nginx, Laravel définira le chemin spécifique correct du fichier de configuration en fonction de la valeur de APP_ENV dans la méthode checkForSpecificEnvironmentFile, telle que .env.dev ou .env.test, et pour le troisième cas, il s'agit du .env par défaut. Pour plus de détails, veuillez vous référer au checkForSpecificEnvironmentFile ci-dessous et au code source des deux méthodes dans l'application associée :

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

Après avoir déterminé le chemin du .env. fichier de configuration à lire, l'étape suivante est le chargement de la configuration dans env.

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

Laravel utilise la version PHP de 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();
    }
}

Il s'appuie sur /Dotenv/Loader pour charger les données :

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

Le chargeur lit Lors de la récupération de la configuration, la fonction readLinesFromFile utilisera la fonction file pour lire la configuration ligne par ligne du fichier dans le tableau, puis exclura les commentaires commençant par # et appellera la méthode setEnvironmentVariable pour les lignes contenant = dans le contenu pour définir le environnement dans la ligne du fichier. Configurez les variables dans le projet :

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"

Après avoir défini les variables d'environnement dans le conteneur, même si DB_HOST dans le fichier env. est homestead, utilisez la fonction env pour le lire. Ce qui est également retiré est la base de données de valeurs de la variable d'environnement DB_HOST précédemment définie dans le conteneur (le lien du conteneur dans le docker utilise le nom du service par défaut. Dans le fichier d'orchestration, j'ai défini le nom du service du conteneur mysql à la base de données, le conteneur php doit donc transmettre l'hôte de la base de données pour se connecter au conteneur mysql). Parce que lorsque nous effectuons des tests automatisés en intégration continue, nous testons généralement dans le conteneur, il est donc très important que Dotenv n'écrase pas les variables d'environnement existantes. De cette façon, je ne peux définir la valeur de la variable d'environnement dans le conteneur que pour terminer le test. . Il n'est pas nécessaire de modifier le fichier env dans le projet, il suffit de déployer le projet dans l'environnement directement une fois le test terminé.

Si la variable d'environnement est cochée et n'existe pas, alors Dotenv définira la variable d'environnement sur l'environnement via la fonction intégrée PHP putenv, et la stockera également dans les deux variables globales $_ENV et $_SERVER .

Lire la configuration env dans le projet

Dans l'application Laravel, vous pouvez utiliser la fonction env() pour lire la valeur de la variable d'environnement, comme obtenir l'HOST de la base de données :

env('DB_HOST`, 'localhost');

La deuxième valeur passée à la fonction env est la "valeur par défaut". Si aucune variable d'environnement n'existe pour la clé donnée, cette valeur sera utilisée.

Jetons un coup d'œil au code source de la fonction env :

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

Elle lit les variables d'environnement directement via la fonction intégrée PHP getenv.

Nous avons vu que lors du chargement de la configuration et de la lecture de la configuration, deux fonctions putenv et getenv sont utilisées. Les variables d'environnement définies par putenv ne survivent que pendant la requête et les paramètres d'environnement précédents seront restaurés une fois la requête terminée. Parce que si l'élément de configuration variables_order dans php.ini devient GPCS et ne contient pas E, alors les variables d'environnement ne peuvent pas être lues via $_ENV dans le programme PHP, donc putenv est utilisé pour définir dynamiquement les variables d'environnement afin que les développeurs n'aient pas besoin de le faire. faites attention à la configuration du serveur. De plus, les variables d'environnement configurées pour l'utilisateur en cours d'exécution sur le serveur seront partagées avec tous les processus démarrés par l'utilisateur, ce qui ne peut pas bien protéger les variables d'environnement privées telles que DB_PASSWORD et API_KEY. Par conséquent, cette configuration peut être mieux protégée avec les paramètres putenv. Ces informations de configuration, la méthode getenv peut obtenir les variables d'environnement du système et les variables d'environnement définies dynamiquement par putenv.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer