How to edit env dynamically in laravel?

In this post we will learn how to update or add new variables in .env file in laravel, We will update smtp credentials in env, So lets get started, First we will create a controller named settings, So to create a controller run the command below.

php artisan make:controller SettingsController

Now we will create a get route to display smtp form and other will be post route to save data, So we will add routes in web.php and create a function in SettingsController.php

Route::get('smtp', [\App\Http\Controllers\SettingsController::class, 'smtp'])->name('smtp');
Route::post('smtp', [\App\Http\Controllers\SettingsController::class, 'storeSmtp'])->name('smtp.store');
class SettingsController extends Controller
{
    public function smtp()
    {
        return view('settings.smtp');
    }
}

Now we will create a form which will have smtp credentials fields


resources/views/settings/smtp.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>SMTP</title>

    <!-- BOOTSTRAP -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
    <!-- Styles -->
    <style>
        body {
            background: #f7f7f7;
        }

        .form-box {
            max-width: 80%;
            margin: auto;
            padding: 50px;
            background: #ffffff;
            border: 10px solid #f2f2f2;
            margin-top: 100px;
        }

        h1, p {
            text-align: center;
        }

        input, textarea {
            width: 100%;
        }
        form{
            padding-top: 40px;
        }
    </style>
</head>
<body>
    <div class="form-box">
        <h1>SMTP</h1>
        <form action="{{ route('smtp.store') }}" method="post" enctype="multipart/form-data">
            @csrf
            <div class="form-group col-md-6">
                <label for="mail_driver" class="form-control-label">Driver</label>
                <input type="text" name="mail_driver" class="form-control" id="mail_driver" value="{{ env('MAIL_DRIVER') }}">
            </div>
            <div class="form-group col-md-6">
                <label for="mail_host" class="form-control-label">Host</label>
                <input type="text" name="mail_host" class="form-control" id="mail_host" value="{{ env('MAIL_HOST') }}">
            </div>
            <div class="form-group col-md-6">
                <label for="mail_port" class="form-control-label">Port</label>
                <input type="text" name="mail_port" class="form-control" id="mail_port" value="{{ env('MAIL_PORT') }}">
            </div>
            <div class="form-group col-md-6">
                <label for="mail_username" class="form-control-label">Username</label>
                <input type="text" name="mail_username" class="form-control" id="mail_username" value="{{ env('MAIL_USERNAME') }}">
            </div>
            <div class="form-group col-md-6">
                <label for="mail_password" class="form-control-label">Password</label>
                <input type="text" name="mail_password" class="form-control" id="mail_password" value="{{ env('MAIL_PASSWORD') }}">
            </div>
            <div class="form-group col-md-6">
                <label for="mail_encryption" class="form-control-label">Encryption</label>
                <input type="text" name="mail_encryption" class="form-control" id="mail_encryption" value="{{ env('MAIL_ENCRYPTION') }}">
            </div>
            <div class="form-group col-md-6">
                <label for="mail_from_address" class="form-control-label">From Address</label>
                <input type="text" name="mail_from_address" class="form-control" id="mail_from_address" value="{{ env('MAIL_FROM_ADDRESS') }}">
            </div>
            <div class="form-group col-md-6">
                <label for="mail_from_name" class="form-control-label">From Name</label>
                <input type="text" name="mail_from_name" class="form-control" id="mail_from_name" value="{{ env('MAIL_FROM_NAME') }}">
            </div>
            <input class="btn btn-primary" type="submit" value="Submit" />
        </form>
    </div>
</body>
</html>

Now we will create code to set env varibales, I have created a custom helper file and in that file ill write this code but you can create a static function in a model or even in the controller you are working on, But if you wish to create a custom helper file than please check this post

// This function is used to set environment variables in a .env file.
function setEnv($array)
{
    // Get the path of the .env file.
    $envFile = app()->environmentFilePath();
    
    // Read the content of the .env file.
    $str     = file_get_contents($envFile);
    
    // If the array is not empty, iterate over it.
    if(count($array) > 0)
    {
        foreach($array as $envKey => $envValue)
        {
            // Find the position of the key in the .env file.
            $keyPosition       = strpos($str, "{$envKey}=");
            
            // Find the end of the line where the key is located.
            $endOfLinePosition = strpos($str, "\n", $keyPosition);
            
            // Get the line with the key.
            $oldLine           = substr($str, $keyPosition, $endOfLinePosition - $keyPosition);
            
            // If the key is not found or the line is not found, append the key-value pair to the .env file.
            if(!$keyPosition || !$endOfLinePosition || !$oldLine)
            {
                $str .= "{$envKey}='{$envValue}'\n";
            }
            else
            {
                // If the key is found, replace the old line with the new key-value pair.
                $str = str_replace($oldLine, "{$envKey}='{$envValue}'", $str);
            }
        }
    }
    
    // Append a newline character to the string.
    $str .= "\n";
    
    // Remove the last character from the string.
    $str = substr($str, 0, -1);
    
    // Append a newline character to the string.
    $str .= "\n";
    
    // Write the string to the .env file. If the write operation fails, return false.
    if(!file_put_contents($envFile, $str))
    {
        return false;
    }
    
    // If the write operation is successful, return true.
    return true;
}

Now we will work in storeSmtp function in SettingsController.

public function storeSmtp(Request $request)
{
    $smtpData = $request->except('_token');
    // pass data in array eg : $smtpData = ['mail_from_name' => $request->mail_from_name];
    setEnv($smtpData);
    return redirect()->back()->with('success','SMTP credentials saved successfully');
}

If you wish to use model or controller for the function, Then pass data like this.

Remember if you use model or controller you should create a static function.

// for model
Settings::setEnv($smtpData)

// for SettingsController 
$this->setEnv($smtpData) 
        //or
self::setEnv($smtpData)