search
HomePHP FrameworkLaravelIntroduction to ENV loading and reading under the Laravel framework

Introduction to ENV loading and reading under the Laravel framework

Oct 22, 2018 pm 02:17 PM
laravelphpSource code analysis

This article brings you an introduction to loading and reading ENV under the Laravel framework. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

Laravel will load the .env file in the project when it starts. It is often useful to have different configurations for different environments in which the application is running. For example, you may want to use the test MySQL database locally and want the project to automatically switch to the production MySQL database after going online. This article will introduce in detail the use of env files and source code analysis.

Use of Env files

Multi-environment env settings

The number of env files in a project is often the same as the number of environments in the project. If a project has development , test, and production environments, then there should be three environment configuration files in the project, .env.dev, .env.test, and .env.prod, corresponding to the environment. The configuration items in the three files should be exactly the same, and the specific configuration values ​​should be set according to the needs of each environment.

The next step is to enable the project to load different env files according to the environment. There are three specific methods, which can be chosen according to usage habits:

Set the APP_ENV environment variable fastcgi_param APP_ENV dev in the nginx configuration file of the environment;

Set the environment variables of the user running PHP on the server , for example, add export APP_ENV dev

in the www user’s /home/www/.bashrc and execute cp .env.dev .env

in the continuous integration task or deployment script of the deployment project. For the first two methods, Laravel will load the corresponding files .env.dev and .env.test based on the variable values ​​loaded by env('APP_ENV'). Specifically, as will be said in the source code later, the third method that is easier to understand is to overwrite the environment's configuration file into the .env file when deploying the project, so that there is no need to make additional settings in the environment's system and nginx.

Customized env file path and file name

The env file is placed in the root directory of the project by default. Laravel provides users with a custom ENV file path or file function,

For example, if you want to customize the env path, you can use the useEnvironmentPath method of the Application instance in app.php in the bootstrap folder:

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

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

If you want to customize the env file name, you can use the loadEnvironmentFrom method of the Application instance in app.php in the bootstrap folder:

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

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

Laravel loads ENV configuration

Laravel loads ENV in This is done in the LoadEnvironmentVariables phase of the bootstrap process before the framework handles the request.

Let's take a look at the source code of \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables to analyze how Laravel loads the configuration in 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;
    }
}

In its startup method bootstrap, Laravel will check whether the configuration has been cached and determine which env file should be applied. For the first two of the three methods of loading configuration files based on the environment mentioned above, because APP_ENV is set in the system or nginx environment variable, so Laravel will set the correct specific path of the configuration file according to the value of APP_ENV in the checkForSpecificEnvironmentFile method, such as .env.dev or .env.test, and for the third case, it is the default .env, for details, please refer to the checkForSpecificEnvironmentFile below and the source code of the two methods in the related Application:

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

After determining the path of the configuration file to be read, the next step is to load the env. Configured.

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

Laravel uses the PHP version of 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();
    }
}

It relies on /Dotenv/Loader to load data:

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

When Loader reads the configuration, the readLinesFromFile function will Use the file function to read the configuration from the file into the array line by line, then exclude the comments starting with #, and call the setEnvironmentVariable method for the lines containing = in the content to configure the environment variables in the file lines into the project. :

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;">When Dotenv instantiates Loader, set the $immutable property of the Loader object to false. When Loader sets the variable, if the variable value is read through the getEnvironmentVariable method, then it will Skip setting this environment variable. So Dotenv will not overwrite existing environment variables by default. This is very important. For example, in the docker container orchestration file, we will set two environment variables for the Mysql container for the PHP application container</span><br>

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

After setting the environment variables in the container, even if the DB_HOST in the env file is homestead and is read using the env function, it will still be the value of the DB_HOST environment variable previously set in the container database (in docker The container link uses the service name by default. In the orchestration file, I set the service name of the mysql container to database, so the php container needs to connect to the mysql container through the database host). Because when we do automated testing in continuous integration, we usually test in the container, so it is very important that Dotenv does not overwrite existing environment variables. This way I can only set the value of the environment variable in the container to complete the test. There is no need to change the env file in the project, just deploy the project to the environment directly after the test is completed.

If you check that the environment variable does not exist, then Dotenv will set the environment variable to the environment through the PHP built-in function putenv, and also store it in the two global variables $_ENV and $_SERVER.

Read env configuration in the project

In the Laravel application, you can use the env() function to read the value of the environment variable, such as obtaining the HOST of the database:

env('DB_HOST`, 'localhost');

The second value passed to the env function is the "default value". If no environment variable exists for the given key, this value will be used.

Let’s take a look at the source code of the env function:

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

It reads environment variables directly through the PHP built-in function getenv.

We saw that when loading configuration and reading configuration, two functions putenv and getenv are used. The environment variables set by putenv only survive during the request, and the previous settings of the environment will be restored after the request ends. Because if the variables_order configuration item in php.ini becomes GPCS and does not contain E, then the environment variables cannot be read through $_ENV in the PHP program, so putenv is used to dynamically set the environment variables so that developers do not need to pay attention to the server configuration. Moreover, the environment variables configured for the running user on the server will be shared with all processes started by the user, which cannot protect private environment variables such as DB_PASSWORD and API_KEY well. Therefore, this configuration can be better protected with putenv settings. For these configuration information, the getenv method can obtain the system's environment variables and the environment variables dynamically set by putenv.

The above is the detailed content of Introduction to ENV loading and reading under the Laravel framework. For more information, please follow other related articles on the PHP Chinese website!

Statement
This article is reproduced at:segmentfault思否. If there is any infringement, please contact admin@php.cn delete
Laravel's Impact: Simplifying Web DevelopmentLaravel's Impact: Simplifying Web DevelopmentApr 21, 2025 am 12:18 AM

Laravel stands out by simplifying the web development process and delivering powerful features. Its advantages include: 1) concise syntax and powerful ORM system, 2) efficient routing and authentication system, 3) rich third-party library support, allowing developers to focus on writing elegant code and improve development efficiency.

Laravel: Frontend or Backend? Clarifying the Framework's RoleLaravel: Frontend or Backend? Clarifying the Framework's RoleApr 21, 2025 am 12:17 AM

Laravelispredominantlyabackendframework,designedforserver-sidelogic,databasemanagement,andAPIdevelopment,thoughitalsosupportsfrontenddevelopmentwithBladetemplates.

Laravel vs. Python: Exploring Performance and ScalabilityLaravel vs. Python: Exploring Performance and ScalabilityApr 21, 2025 am 12:16 AM

Laravel and Python have their own advantages and disadvantages in terms of performance and scalability. Laravel improves performance through asynchronous processing and queueing systems, but due to PHP limitations, there may be bottlenecks when high concurrency is present; Python performs well with the asynchronous framework and a powerful library ecosystem, but is affected by GIL in a multi-threaded environment.

Laravel vs. Python (with Frameworks): A Comparative AnalysisLaravel vs. Python (with Frameworks): A Comparative AnalysisApr 21, 2025 am 12:15 AM

Laravel is suitable for projects that teams are familiar with PHP and require rich features, while Python frameworks depend on project requirements. 1.Laravel provides elegant syntax and rich features, suitable for projects that require rapid development and flexibility. 2. Django is suitable for complex applications because of its "battery inclusion" concept. 3.Flask is suitable for fast prototypes and small projects, providing great flexibility.

Frontend with Laravel: Exploring the PossibilitiesFrontend with Laravel: Exploring the PossibilitiesApr 20, 2025 am 12:19 AM

Laravel can be used for front-end development. 1) Use the Blade template engine to generate HTML. 2) Integrate Vite to manage front-end resources. 3) Build SPA, PWA or static website. 4) Combine routing, middleware and EloquentORM to create a complete web application.

PHP and Laravel: Building Server-Side ApplicationsPHP and Laravel: Building Server-Side ApplicationsApr 20, 2025 am 12:17 AM

PHP and Laravel can be used to build efficient server-side applications. 1.PHP is an open source scripting language suitable for web development. 2.Laravel provides routing, controller, EloquentORM, Blade template engine and other functions to simplify development. 3. Improve application performance and security through caching, code optimization and security measures. 4. Test and deployment strategies to ensure stable operation of applications.

Laravel vs. Python: The Learning Curves and Ease of UseLaravel vs. Python: The Learning Curves and Ease of UseApr 20, 2025 am 12:17 AM

Laravel and Python have their own advantages and disadvantages in terms of learning curve and ease of use. Laravel is suitable for rapid development of web applications. The learning curve is relatively flat, but it takes time to master advanced functions. Python's grammar is concise and the learning curve is flat, but dynamic type systems need to be cautious.

Laravel's Strengths: Backend DevelopmentLaravel's Strengths: Backend DevelopmentApr 20, 2025 am 12:16 AM

Laravel's advantages in back-end development include: 1) elegant syntax and EloquentORM simplify the development process; 2) rich ecosystem and active community support; 3) improved development efficiency and code quality. Laravel's design allows developers to develop more efficiently and improve code quality through its powerful features and tools.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.