Lumen does not read env from system during request - laravel

Lumen 5.4, MySql & Docker. I have following variables in global env
$ printenv
DB_HOST=127.0.0.1
DB_DATABASE=database
etc
.env in my project the are present also, but they have different values.
If I type in tinker env('DB_HOST'), it prints value from the global environment, but when application runs, it takes from the specified .env file. I think the problem exists within following function in Laravel\Lumen\Application :
/**
* Load a configuration file into the application.
*
* #param string $name
* #return void
*/
public function configure($name)
{
if (isset($this->loadedConfigurations[$name])) {
return;
}
$this->loadedConfigurations[$name] = true;
$path = $this->getConfigurationPath($name);
if ($path) {
$this->make('config')->set($name, require $path);
}
}
How to override those values or make it to avoid those conditions: isset($this->loadedConfigurations[$name]) ?

I still think that, regarding my comment, the answer remains the same. If you wish to utilize the docker environment variables as opposed to your local .env variables, then the config directory is still the way to go. In this case, it looks like you wish to target the database host. So let's do that:
In your config/database.php file, change the following:
'mysql' => [
//...
'host' => getenv('DB_HOST') ?: env('DB_HOST', 'defaultvalue')
]
Then only make reference to the host through the config file.
config("database.mysql.host");
You will get the ENV from your docker container if it exists, otherwise you will get the DB_HOST declaration from your .env file.

Related

Cannot get value from config in Lumen

I want to change the timezone in lumen, but I cannot get the value from config, it always give the default value UTC.
I've tried everything I know, to the point changing the default value to what I wanted. But still the timezone wont change
AppServiceProvider
public function register()
{
//set local timezone
date_default_timezone_set(config('app.timezone'));
//set local date name
setLocale(LC_TIME, $this->app->getLocale());
URL::forceRootUrl(Config::get('app.url'));
}
Bootstrap.app
(new Laravel\Lumen\Bootstrap\LoadEnvironmentVariables(
dirname(__DIR__)
))->bootstrap();
date_default_timezone_set(env('APP_TIMEZONE', 'Asia/Jakarta'));
$app->configure('app');
Config.app
'timezone' => env("APP_TIMEZONE", "Asia/Jakarta"),
.env
APP_TIMEZONE="Asia/Jakarta"
APP_LOCALE="id"
Also if I make a variable inside config.app such as:
'tes_var' => 'Test'
And using it like this:
\Log::info(config('app.tes_var'));
The result in Log is null, I can't get the value from tes_var.
I don't have any idea what's wrong here, if it's in Laravel maybe this is happened because cached config, but there's no cached config in Lumen. Maybe I miss some configuration here?
Thanks
First, you should create the config/ directory in your project root folder.
Then create a new file app.php under the config directory i.e. config/app.php
Now add whatever config values you want to access later in your application in the config/app.php file.
So, instead of creating a config.php file you should make a config directory and can create multiple config files under the config directory.
So final code will be like this:
config/app.php will have:
<?PHP
return [
'test_var' => 'Test'
];
Can access it anywhere like this:
config('app.tes_var');
Although Lumen bootstrap/app.php has already loaded the app.php config file (can check here: https://github.com/laravel/lumen/blob/9.x/bootstrap/app.php)
If not loaded in your case, you can add the below line in bootstrap/app.php file:
$app->configure('app');
Hope it will help you.
In order to use the env file while caching the configs, you need to create a env.php inside the config folder. Then, load all env variables and read as "env.VARIABLE_FROM_ENV". Example env.php:
<?php
use Dotenv\Dotenv;
$envVariables = [];
$loaded = Dotenv::createArrayBacked(base_path())->load();
foreach ($loaded as $key => $value) {
$envVariables[$key] = $value;
}
return $envVariables;
then read in your code:
$value = config('env.VARIABLE_FROM_ENV', 'DEFAULT_VALUE_IF_YOU_WANT');

How to change storage settings after reload custom .env file in Laravel?

I run into this issue after I loaded my custom .env.custom file in AppServiceProvider:
class AppServiceProvider extends ServiceProvider
{
// ...
public function boot()
{
$host = request()->getHost();
// read domain based .env file, like: .env.example.com
$dotenv = \Dotenv\Dotenv::createMutable(base_path(), '.env.' . $host);
$dotenv->load();
}
}
(I tried with \Dotenv\Dotenv::createImmutable() too, with same result.)
Then in a controller:
dd(
env('S3_ENDPOINT'),
Storage::disk('s3'),
);
The env() return with the new value, but the Storage::disk('s3') contains the old value.
How can I force the whole Laravel system to reload the configuration from the .env.custome file?
There are two ways
1. Clear the cache using Artisan class
But it will clear the cache & add again & takes some time.
$host = request()->getHost();
$dotenv = \Dotenv\Dotenv::createMutable(base_path(), '.env.' . $host);
$dotenv->load();
// clear it after loading the env
Artisan::call('config:clear'); // if gives error Artisan class not found then use \Artisan::call('config:clear');
2. Set that particular config
Much better as you do not change all config files just the one you want to change. Will takes lesser time.
$host = request()->getHost();
$dotenv = \Dotenv\Dotenv::createMutable(base_path(), '.env.' . $host);
$dotenv->load();
Config::set('filesystems.disks.s3', env("S3_ENDPOINT"));

Laravel - timezone - Config null

I installed laravel-timezone as described here: https://github.com/jamesmills/laravel-timezone
also added teh configuration file, and in the configuraiton file there is this:
timezone.php
'lookup' => [
'server' => [
'REMOTE_ADDR',
],
'headers' => [
],
],
After the login, the script is suposed to update the timezone automatically, but I get Invalid argument supplied for foreach() in the file \vendor\jamesmills\laravel-timezone\src\Listeners\Auth\UpdateUsersTimezone.php:111
the function is this:
/**
* #return mixed
*/
private function getFromLookup()
{
$result = null;
foreach (config('timezone.lookup') as $type => $keys) {
if (empty($keys)) {
continue;
}
$result = $this->lookup($type, $keys);
if (is_null($result)) {
continue;
}
}
return $result;
}
I tried to put a dd() there, and config('timezone.lookup') is null..
why does it return null, if the file exists, and a value is assigned in the file?
Is there anything I have to do to make this timezone.php accesisble?
When you are caching the configuration Laravel creates a file in bootstrap/cache/config.php with all the configuration. After this is done the individual cache files and the .env file are no longer read.
You therefore need to clear your config cache, and I recommend to not cache it while in development. Only cache the config in production.
Just run:
php artisan cache:clear
Sorry you’re having issues using the package. As far as I’m aware you don’t have to publish the config for the package to work after initial install. It should pick up defaults so you should be able to install it and go! However, like others have said, if you do publish the config then please try to flush your config cache php artisan cache:clear
Thank you #apokryfos for your help on this issue.
If you have any further issues please don’t hesitate to reply.
James

Not all variables in .env are cached after run php artisan config:cache

GOOGLE_APPLICATION_CREDENTIALS=../storage/app/service-account.json
I have a google api credential key in the .env file. However, after I run php artisan config:cache, the credential could not be loaded. It works fine before rhe caching the configuration.
I found the following function in the google api auth file in vendor folder. It seems the google service use the .env by default. So after config:cache, the fromEnv function breaks.
Use another auth method setAuthConfig('/path/to/client_credentials.json') solve the problem.
/**
* Load a JSON key from the path specified in the environment.
*
* Load a JSON key from the path specified in the environment
* variable GOOGLE_APPLICATION_CREDENTIALS. Return null if
* GOOGLE_APPLICATION_CREDENTIALS is not specified.
*
* #return array JSON key | null
*/
public static function fromEnv()
{
$path = getenv(self::ENV_VAR);
if (empty($path)) {
return;
}
if (!file_exists($path)) {
$cause = 'file ' . $path . ' does not exist';
throw new \DomainException(self::unableToReadEnv($cause));
}
$jsonKey = file_get_contents($path);
return json_decode($jsonKey, true);
}
The reason is the way you load the file.
You probably have this in your view/controller: env('GOOGLE_APPLICATION_CREDENTIALS ');. But this will break when you do php artisan config:cache. You should only use the config() helper in your views/controller. So in order to make that work, you should make a extra google-config file or add the following to your config/services.php:
'google' => [
'application-credentials' => env('GOOGLE_APPLICATION_CREDENTIALS'),
]
Now you can fetch that inside your views/controller:
config('services.google.application-credentials');
If your value for env contains space then you need to enclose it in quote. i.e. APP_NAME="This is myapp". Please confirm it first.
In your case try with GOOGLE_APPLICATION_CREDENTIALS="../storage/app/service-account.json"
First run
php artisan cache:clear
Then
php artisan config:cache

Symfony 1.4: Override doctrine:build-schema command

Is it possible to override a Symfony 1.4 CLI command?
More specifically, I was wondering if it's possible to override this command:
php symfony doctrine:build-schema
What I want to do is to add a new option in the database.yml file for each connection I find in it.
The option I want to add is a package option
So, an hypothetical connection could be:
all:
doctrine:
class: sfDoctrineDatabase
package: myPackageOption
param:
dsn: 'mysql:host=localhost;dbname=my_db_name'
username: db_user
password: db_password
If it would be possible, where can i find the code to override?
I suggest you to use some shell script that pre-generate the databses.yml and then auto-invoque the php symfony doctrine:build-schema. Something like:
build.sh, in project root folder:
#!/bin/bash
cp config/databases_1.yml config/databases.yml
php symfony doctrine:build
then, type ./build.sh (after added execution permissions) in your console.
The copy/replace of multiple databases_xxx.yml it's the easiest example. But you can do any processing you want.
If you don't know about shell scripting, you can do the file modification even with a php script, so your build.sh should looks like:
#!/bin/bash
php pregenerate_databases.php
php symfony doctrine:build
I'm trying to override the task but I can't make it work, but:
You can create your own task that inherits the doctrine task and do your stuff:
in lib/task add sfDoctrineBuildSchemaCustomTask.class.php:
class sfDoctrineBuildSchemaCustomTask extends sfDoctrineBuildSchemaTask
{
/**
* #see sfTask
*/
protected function configure()
{
$this->addOptions(array(
new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
));
$this->namespace = 'doctrine';
$this->name = 'build-schema-custom';
$this->briefDescription = 'Creates a schema from an existing database';
$this->detailedDescription = <<<EOF
The [doctrine:build-schema|INFO] task introspects a database to create a schema:
[./symfony doctrine:build-schema|INFO]
The task creates a yml file in [config/doctrine|COMMENT]
EOF;
}
/**
* #see sfTask
*/
protected function execute($arguments = array(), $options = array())
{
// do your stuff before original call
parent::execute($arguments,$options);
// do your stuff after original call
}
}
Then, you can call php symfony doctrine:build-schema-custom, and go!
Or, maybe, you can edit the original task located in lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/task/sfDoctrineBuildSchemaTask.class.php

Resources