How to set .env values in laravel programmatically

2019-01-18 00:03发布

I have a custom CMS that I am writing from scratch in Laravel and want to set env values i.e. database details, mailer details, general configuration, etc from controller once the user sets up and want to give user the flexibility to change them on the go using the GUI that I am making.

So my question is how do I write the values received from user to the .env file as an when I need from the controller.

And is it a good idea to build the .env file on the go or is there any other way around it?

Thanks in advance.

8条回答
时光不老,我们不散
2楼-- · 2019-01-18 00:23

Based on totymedli's answer.

Where it is required to change multiple enviroment variable values at once, you could pass an array (key->value). Any key not present previously will be added and a bool is returned so you can test for success.

public function setEnvironmentValue(array $values)
{

    $envFile = app()->environmentFilePath();
    $str = file_get_contents($envFile);

    if (count($values) > 0) {
        foreach ($values as $envKey => $envValue) {

            $str .= "\n"; // In case the searched variable is in the last line without \n
            $keyPosition = strpos($str, "{$envKey}=");
            $endOfLinePosition = strpos($str, "\n", $keyPosition);
            $oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition);

            // If key does not exist, add it
            if (!$keyPosition || !$endOfLinePosition || !$oldLine) {
                $str .= "{$envKey}={$envValue}\n";
            } else {
                $str = str_replace($oldLine, "{$envKey}={$envValue}", $str);
            }

        }
    }

    $str = substr($str, 0, -1);
    if (!file_put_contents($envFile, $str)) return false;
    return true;

}
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-01-18 00:25

Watch out! Not all variables in the laravel .env are stored in the config environment. To overwrite real .env content use simply:

putenv ("CUSTOM_VARIABLE=hero");

To read as usual, env('CUSTOM_VARIABLE') or env('CUSTOM_VARIABLE', 'devault')

查看更多
我想做一个坏孩纸
4楼-- · 2019-01-18 00:36

tl;dr

Based on vesperknight's answer I created a solution that doesn't use strtok or env().

private function setEnvironmentValue($envKey, $envValue)
{
    $envFile = app()->environmentFilePath();
    $str = file_get_contents($envFile);

    $str .= "\n"; // In case the searched variable is in the last line without \n
    $keyPosition = strpos($str, "{$envKey}=");
    $endOfLinePosition = strpos($str, PHP_EOL, $keyPosition);
    $oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition);
    $str = str_replace($oldLine, "{$envKey}={$envValue}", $str);
    $str = substr($str, 0, -1);

    $fp = fopen($envFile, 'w');
    fwrite($fp, $str);
    fclose($fp);
}

Explanation

This doesn't use strtok that might not work for some people, or env() that won't work with double-quoted .env variables which are evaluated and also interpolates embedded variables

KEY="Something with spaces or variables ${KEY2}"
查看更多
神经病院院长
5楼-- · 2019-01-18 00:39

More simplified:

public function putPermanentEnv($key, $value)
{
    $path = app()->environmentFilePath();

    $escaped = preg_quote('='.env($key), '/');

    file_put_contents($path, preg_replace(
        "/^{$key}{$escaped}/m",
        "{$key}={$value}",
        file_get_contents($path)
    ));
}

or as helper:

if ( ! function_exists('put_permanent_env'))
{
    function put_permanent_env($key, $value)
    {
        $path = app()->environmentFilePath();

        $escaped = preg_quote('='.env($key), '/');

        file_put_contents($path, preg_replace(
            "/^{$key}{$escaped}/m",
           "{$key}={$value}",
           file_get_contents($path)
        ));
    }
}
查看更多
对你真心纯属浪费
6楼-- · 2019-01-18 00:40

Based on josh's answer. I needed a way to replace the value of a key inside the .env file.

But unlike josh's answer, I did not want to depend on knowing the current value or the current value being accessible in a config file at all.

Since my goal is to replace values that are used by Laravel Envoy which doesn't use a config file at all but instead uses the .env file directly.

Here's my take on it:

public function setEnvironmentValue($envKey, $envValue)
{
    $envFile = app()->environmentFilePath();
    $str = file_get_contents($envFile);

    $oldValue = strtok($str, "{$envKey}=");

    $str = str_replace("{$envKey}={$oldValue}", "{$envKey}={$envValue}\n", $str);

    $fp = fopen($envFile, 'w');
    fwrite($fp, $str);
    fclose($fp);
}

Usage:

$this->setEnvironmentValue('DEPLOY_SERVER', 'forge@122.11.244.10');
查看更多
老娘就宠你
7楼-- · 2019-01-18 00:40

In the event that you want these settings to be persisted to the environment file so they be loaded again later (even if the configuration is cached), you can use a function like this. I'll put the security caveat in there, that calls to a method like this should be gaurded tightly and user input should be sanitized properly.

private function setEnvironmentValue($environmentName, $configKey, $newValue) {
    file_put_contents(App::environmentFilePath(), str_replace(
        $environmentName . '=' . Config::get($configKey),
        $environmentName . '=' . $newValue,
        file_get_contents(App::environmentFilePath())
    ));

    Config::set($configKey, $newValue);

    // Reload the cached config       
    if (file_exists(App::getCachedConfigPath())) {
        Artisan::call("config:cache");
    }
}

An example of it's use would be;

$this->setEnvironmentValue('APP_LOG_LEVEL', 'app.log_level', 'debug');

$environmentName is the key in the environment file (example.. APP_LOG_LEVEL)

$configKey is the key used to access the configuration at runtime (example.. app.log_level (tinker config('app.log_level')).

$newValue is of course the new value you wish to persist.

查看更多
登录 后发表回答