Как установить значения.env в laravel программно "на лету"
У меня есть пользовательская CMS, которую я пишу с нуля в Laravel и хочу установить значения env
то есть данные базы данных, данные о почтовом отправлении, общую конфигурацию и т.д. Из контроллера после того, как пользователь настроится и хочет дать пользователю гибкость, чтобы изменить их на ходу используя графический интерфейс, который я создаю.
Поэтому мой вопрос заключается в том, как написать значения, полученные от пользователя, в .env
файл, когда мне нужно от контроллера.
И неплохо ли построить файл .env
на ходу или есть ли что-нибудь еще?
Заранее спасибо.
Ответы
Ответ 1
На основании тотемедли ответ.
Там, где требуется изменить несколько значений переменных среды, вы можете передать массив (key-> значение). Любой ключ, отсутствующий ранее, будет добавлен, и будет возвращено значение 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;
}
Ответ 2
Поскольку Laravel использует конфигурационные файлы для доступа и хранения данных .env
, вы можете установить эти данные "на лету" с помощью метода config()
:
config(['database.connections.mysql.host' => '127.0.0.1']);
Чтобы получить эти данные, используйте config()
:
config('database.connections.mysql.host')
Чтобы установить значения конфигурации во время выполнения, передайте массив в config
хелпер
https://laravel.com/docs/5.3/configuration#accessing-configuration-values
Ответ 3
Осторожно! Не все переменные в laravel.env хранятся в среде конфигурации.
Для перезаписи реального содержимого .env используйте просто:
putenv ("CUSTOM_VARIABLE = hero");
Чтобы читать как обычно, env ('CUSTOM_VARIABLE') или env ('CUSTOM_VARIABLE', 'devault')
ПРИМЕЧАНИЕ. В зависимости от того, какая часть вашего приложения использует настройку env, вам может потребоваться установить переменную заранее, поместив ее в файл index.php или bootstrap.php. Установка его в вашем сервис-провайдере приложения может быть слишком поздней для некоторых пакетов/использования настроек env.
Ответ 4
На основе ответа Джоша. Мне нужен был способ заменить значение ключа внутри .env
файла.
Но в отличие от ответа josh, я не хотел зависеть от того, что текущее значение или текущее значение доступно в файле конфигурации вообще.
Поскольку моя цель - заменить значения, которые используются Laravel Envoy, который вообще не использует файл конфигурации, но вместо этого использует файл .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', '[email protected]');
Ответ 5
Более упрощенный:
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)
));
}
}
Ответ 6
Если вы хотите, чтобы эти параметры сохранялись в файле среды, чтобы они были загружены позже (даже если кеширование конфигурации), вы можете использовать такую функцию. Я поставлю там предостережение о безопасности, которое вызывает метод, подобный этому, должен быть жестко закрыт, а пользовательский ввод должен быть правильно обработан.
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
- это ключ в файле среды (пример.. APP_LOG_LEVEL)
$configKey
- это ключ, используемый для доступа к конфигурации во время выполнения (пример.. app.log_level (tinker config('app.log_level')
).
$newValue
- это, конечно, новое значение, которое вы хотите сохранить.
Ответ 7
ТЛ; др
На основе ответа vesperknight я создал решение, которое не использует strtok
или 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);
}
объяснение
Это не использует strtok
который может не работать для некоторых людей, или env()
, который не будет работать с переменными .env
с двойными .env
которые оцениваются, а также интерполирует встроенные переменные
KEY="Something with spaces or variables ${KEY2}"
Ответ 8
Вы можете использовать этот пакет
https://github.com/ImLiam/laravel-env-set-command
затем используйте Artisan Facade для вызова команд ремесленника, например:
Artisan::call('php artisan env:set app_name Example')
Ответ 9
Это решение основано на решении, предоставленном Элиасом Тутунги, оно принимает множественные изменения значений и использует коллекцию Laravel, потому что foreach являются грубыми
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;
}
Ответ 10
На основании тотемедли ответа и ответа Олувафисайо.
Я установил небольшую модификацию, чтобы изменить файл .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;
}
Таким образом, он корректно перезаписывает файл .env с помощью функции setEnvironmentValue, но как 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;
}
Ответ 11
Замените значение signle в файловой функции .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_env ('APP_VERSION', 1.8)
Пример использования пользовательского пути: set_env ('APP_VERSION', 1.8, $ envfilepath)