Php 如何以编程方式动态设置laravel中的.env值
我有一个自定义CMS,我正在用Laravel从头开始编写,并希望在用户设置后从controller设置Php 如何以编程方式动态设置laravel中的.env值,php,laravel,environment-variables,Php,Laravel,Environment Variables,我有一个自定义CMS,我正在用Laravel从头开始编写,并希望在用户设置后从controller设置env值,即数据库详细信息、邮件详细信息、常规配置等,并希望给用户灵活性,以便使用我正在制作的GUI在移动中更改它们 所以我的问题是,当我需要控制器时,如何将从用户接收到的值写入.env文件 在运行中构建.env文件是一个好主意,还是有其他方法 提前感谢。由于Laravel使用配置文件访问和存储.env数据,您可以使用config()方法动态设置此数据: config(['database.co
env
值,即数据库详细信息、邮件详细信息、常规配置等,并希望给用户灵活性,以便使用我正在制作的GUI在移动中更改它们
所以我的问题是,当我需要控制器时,如何将从用户接收到的值写入.env
文件
在运行中构建.env
文件是一个好主意,还是有其他方法
提前感谢。由于Laravel使用配置文件访问和存储
.env
数据,您可以使用config()
方法动态设置此数据:
config(['database.connections.mysql.host' => '127.0.0.1']);
要获取此数据,请使用config()
:
要在运行时设置配置值,请将数组传递给config
helper
如果希望将这些设置持久化到环境文件中,以便以后再次加载(即使配置已缓存),则可以使用如下函数。我将把安全警告放在那里,对这样一个方法的调用应该严格控制,用户输入应该被适当地消毒
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");
}
}
其用途的一个例子是:
$this->setEnvironmentValue('APP_LOG_LEVEL', 'app.log_level', 'debug');
$environmentName
是环境文件中的键(例如..应用程序日志级别)
$configKey
是用于在运行时访问配置的密钥(例如..app.log\u级别(tinkerconfig('app.log\u级别')
)
$newValue
当然是您希望保留的新值。基于josh的回答。我需要一种方法来替换.env
文件中键的值
但与josh的回答不同,我根本不想依赖于知道当前值或当前值在配置文件中是可访问的
因为我的目标是替换Laravel特使使用的值,它根本不使用配置文件,而是直接使用.env
文件
以下是我对它的看法:
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);
}
用法:
$this->setEnvironmentValue('DEPLOY_SERVER', 'forge@122.11.244.10');
注意!并非laravel.env中的所有变量都存储在配置环境中。 要覆盖real.env内容,只需使用: putenv(“自定义变量=英雄”); 如往常一样读取env('CUSTOM_VARIABLE')或env('CUSTOM_VARIABLE','devault')) 注意:根据应用程序的哪个部分使用env设置,您可能需要将变量提前设置到index.php或bootstrap.php文件中。在应用程序服务提供商中设置该变量对于某些包/使用env设置来说可能太晚了。tl;dr 基于此,我创建了一个不使用或的解决方案 解释 这不使用可能对某些人不起作用的
strtok
,或不使用双引号.env
变量的env()
,这些变量被计算并插入嵌入变量
KEY="Something with spaces or variables ${KEY2}"
更简化:
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)
));
}
或作为助手:
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)
));
}
}
替换.env文件函数中的单个值:
/**
* @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);
}
本地(laravel)使用示例:set\u env('APP\u VERSION',1.8)
使用自定义路径的示例:
set_env('APP_VERSION',1.8,$envfilepath)
基于totymedli的答案
如果需要一次更改多个环境变量值,您可以传递一个数组(key->value)。将添加以前不存在的任何键,并返回bool,以便测试是否成功
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;
}
你可以使用这个软件包
然后使用Artisan Facade调用Artisan命令,例如:
Artisan::call('php artisan env:set app_name Example')
此解决方案建立在Elias Tutungi提供的解决方案的基础上,它接受多个值更改并使用Laravel集合,因为foreach的值太大
函数集\u环境\u值($values=[])
{
$path=app()->environmentFilePath();
收集($values)->map(函数($value,$key)使用($path){
$escape=preg_quote('='.env($key),'/');
文件内容($path,preg\u replace)(
“/^{$key}{$escaped}/m”,
“{$key}={$value}”,
文件获取内容($path)
));
});
返回true;
}
基于totymedli和Oluwafisayo的答案
我设置了一些修改来更改.env文件,它在Laravel 5.8中工作得太好了,但是当我更改了.env文件后,我可以看到变量在使用php artisan serve重新启动后没有更改,所以我尝试清除缓存和其他文件,但我看不到解决方案
public function setEnvironmentValue(array $values)
{
$envFile = app()->environmentFilePath();
$str = file_get_contents($envFile);
$str .= "\r\n";
if (count($values) > 0) {
foreach ($values as $envKey => $envValue) {
$keyPosition = strpos($str, "$envKey=");
$endOfLinePosition = strpos($str, "\n", $keyPosition);
$oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition);
if (is_bool($keyPosition) && $keyPosition === false) {
// variable doesnot exist
$str .= "$envKey=$envValue";
$str .= "\r\n";
} else {
// variable exist
$str = str_replace($oldLine, "$envKey=$envValue", $str);
}
}
}
$str = substr($str, 0, -1);
if (!file_put_contents($envFile, $str)) {
return false;
}
app()->loadEnvironmentFrom($envFile);
return true;
}
因此,它使用Function setEnvironmentValue正确地重写了.env文件,但是Laravel如何在不重新启动系统的情况下重新加载新的.env呢
我在查找有关信息时发现
Artisan::call('cache:clear');
但在本地它不起作用!对我来说,但当我上传代码并在我的服务器上测试时,它工作得很好
我在Larave 5.8中测试了它,并在我的发球区工作
这可能是一个提示,当你有一个包含多个单词的变量,并且单独包含一个空格时,我的解决方案就是这样
public function update($variable, $value)
{
if ($variable == "APP_NAME" || $variable == "MAIL_FROM_NAME") {
$value = "\"$value\"";
}
$values = array(
$variable=>$value
);
$this->setEnvironmentValue($values);
Artisan::call('config:clear');
return true;
}
您可以使用我在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;
}
}
#覆盖.env的更简单方法可以这样做
$_ENV['key'] = 'value';
Tailor Otwell使用此代码生成laravel应用程序密钥并设置其值(例如修改代码): 您可以在密钥生成类中找到代码:
illumb\Foundation\Console\KeyGenerateCommand
PHP8解决方案
此解决方案使用的是env()
,因此应仅在未缓存配置时运行
/**
* @param string $key
* @param string $value
*/
protected function setEnvValue(string $key, string $value)
{
$path = app()->environmentFilePath();
$env = file_get_contents($path);
$old_value = env($key);
if (!str_contains($env, $key.'=')) {
$env .= sprintf("%s=%s\n", $key, $value);
} else if ($old_value) {
$env = str_replace(sprintf('%s=%s', $key, $old_value), sprintf('%s=%s', $key, $value), $env);
} else {
$env = str_replace(sprintf('%s=', $key), sprintf('%s=%s',$key, $value), $env);
}
file_put_contents($path, $env);
}
如果不需要将更改保存到.env文件,只需使用以下代码:
\Illuminate\Support\Env::getRepository()->set('APP_NAME','New app name');
config(['something'=>'data']);return env('something');
这是我在controller中设置它的方式,但它不返回任何内容。您不需要使用env()
。只需使用config()
设置数据,然后使用config('something')
获取数据。我设置了数据库凭据
$escaped = preg_quote('='.config('broadcasting.default'), '/');
file_put_contents(app()->environmentFilePath(), preg_replace("/^BROADCAST_DRIVER{$escaped}/m", 'BROADCAST_DRIVER='.'pusher',
file_get_contents(app()->environmentFilePath())
));
/**
* @param string $key
* @param string $value
*/
protected function setEnvValue(string $key, string $value)
{
$path = app()->environmentFilePath();
$env = file_get_contents($path);
$old_value = env($key);
if (!str_contains($env, $key.'=')) {
$env .= sprintf("%s=%s\n", $key, $value);
} else if ($old_value) {
$env = str_replace(sprintf('%s=%s', $key, $old_value), sprintf('%s=%s', $key, $value), $env);
} else {
$env = str_replace(sprintf('%s=', $key), sprintf('%s=%s',$key, $value), $env);
}
file_put_contents($path, $env);
}
\Illuminate\Support\Env::getRepository()->set('APP_NAME','New app name');