How to set .env values in laravel programmatically on the fly

前端 未结 14 928
忘掉有多难
忘掉有多难 2020-12-01 09:05

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

相关标签:
14条回答
  • 2020-12-01 09:45

    You can use this custom method i located from internet ,

      /**
     * Calls the method 
     */
    public function something(){
        // some code
        $env_update = $this->changeEnv([
            'DB_DATABASE'   => 'new_db_name',
            'DB_USERNAME'   => 'new_db_user',
            'DB_HOST'       => 'new_db_host'
        ]);
        if($env_update){
            // Do something
        } else {
            // Do something else
        }
        // more code
    }
    
    protected function changeEnv($data = array()){
            if(count($data) > 0){
    
                // Read .env-file
                $env = file_get_contents(base_path() . '/.env');
    
                // Split string on every " " and write into array
                $env = preg_split('/\s+/', $env);;
    
                // Loop through given data
                foreach((array)$data as $key => $value){
    
                    // Loop through .env-data
                    foreach($env as $env_key => $env_value){
    
                        // Turn the value into an array and stop after the first split
                        // So it's not possible to split e.g. the App-Key by accident
                        $entry = explode("=", $env_value, 2);
    
                        // Check, if new key fits the actual .env-key
                        if($entry[0] == $key){
                            // If yes, overwrite it with the new one
                            $env[$env_key] = $key . "=" . $value;
                        } else {
                            // If not, keep the old one
                            $env[$env_key] = $env_value;
                        }
                    }
                }
    
                // Turn the array back to an String
                $env = implode("\n", $env);
    
                // And overwrite the .env with the new data
                file_put_contents(base_path() . '/.env', $env);
    
                return true;
            } else {
                return false;
            }
        }
    
    0 讨论(0)
  • 2020-12-01 09:47

    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}"
    
    0 讨论(0)
  • 2020-12-01 09:48

    This solution builds upon the one provided by Elias Tutungi, it accepts multiple value changes and uses a Laravel Collection because foreach's are gross

        function set_environment_value($values = [])
        {
            $path = app()->environmentFilePath();
    
            collect($values)->map(function ($value, $key) use ($path) {
                $escaped = preg_quote('='.env($key), '/');
    
                file_put_contents($path, preg_replace(
                    "/^{$key}{$escaped}/m",
                   "{$key}={$value}",
                   file_get_contents($path)
                ));
            });
    
            return true;
        }
    
    0 讨论(0)
  • 2020-12-01 09:52

    Replace single value in .env file function:

    /**
     * @param string $key
     * @param string $value
     * @param null $env_path
     */
    function set_env(string $key, string $value, $env_path = null)
    {
        $value = preg_replace('/\s+/', '', $value); //replace special ch
        $key = strtoupper($key); //force upper for security
        $env = file_get_contents(isset($env_path) ? $env_path : base_path('.env')); //fet .env file
        $env = str_replace("$key=" . env($key), "$key=" . $value, $env); //replace value
        /** Save file eith new content */
        $env = file_put_contents(isset($env_path) ? $env_path : base_path('.env'), $env);
    }
    

    Example to local (laravel) use: set_env('APP_VERSION', 1.8).

    Example to use custom path: set_env('APP_VERSION', 1.8, $envfilepath).

    0 讨论(0)
  • 2020-12-01 09:54

    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.

    0 讨论(0)
  • 2020-12-01 09:56

    #more simple way to cover .env you can do like this

    $_ENV['key'] = 'value';
    
    0 讨论(0)
提交回复
热议问题