I stumbled across this https://laravel.com/docs/5.4/configuration#configuration-caching in the documentation and it confused me a bit.
When I want an environment variable I use the env() function to return what I want. According to the above link it says I should be using the config() function instead to ensure that on production I am accessing the values through a cache.
e.g. These both return the same thing
env('APP_URL')
vs
config('app.url')
So should I be using config() or env() inside my app?
I assume that if I add a new env variable I will also need to update my config files?
You should never use env() in the code directly. It's a good practice to use config(). In config files use env() to get the data from .env file.
In this case, you can easily override config values at runtime or during testing.
You also can use config caching.
To give your application a speed boost, you should cache all of your configuration files into a single file using the config:cache Artisan command.
Another reason is described in the docs:
You should typically run the php artisan config:cache command as part of your production deployment routine. If you execute the config:cache command during your deployment process, you should be sure that you are only calling the env function from within your configuration files.
Related
I'm using Laravel 8.0 in my application and I added a new .env variable:
APP_URL_FRONT=https://tmsv00008:6204
And how I use it:
To access the project use the following link: LINK
When I deploy the application I cache the config files:
php artisan config:cache
But the env files is not visible and the strange thing is that if I execute:
php artisan config:clear
The variable is visible.
What I'm doing wrong? Because it doesn't make sense to me.
Also, in this article they suggest to execute the commands in this order:
php artisan config:cache
php artisan config:clear
But this doesn't make sense to me. Shouldn't be the other way around? And I think the cache commands also clears the cache first.
The env() function is strongly recommended to be used only in configuration file, since caching the configurations, will make the env function to return null
In other words, crate a configuration file, with that environment variable, or add it to an existing one
It's hidden in an old update guide this "note"
I am using Laravel 6.x for client's project wherein I have built an API in the Artisan Command for syncing data.
Now client wants the configuration to be discreet, out of main source code and without any fallback values as possible. That means I must define the configs in the .env file and use the env() method without any fallback default values.
This must be possible inside Laravel Artisan command class files, but it is not working as intended when I use the env method in the code as below:
[siteroot]\.env:
APP_ENV=local
[siteroot]\app\Console\Commands\SyncSomeData.php:
use Illuminate\Console\Command;
class SyncSomeData extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'sync:some-data';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
exit(env('APP_ENV','staging1'));
}
}
This always prints staging1 in console and if I use this instead of the given env method, then it prints nothing:
exit(env('APP_ENV'));
As I know and can trust that Laravel is most secure, there must be way to have env method work without fallback value in the command file, can anyone help fulfilling this ?
There are a couple parts to this answer.
Caching Config
The issue in this question is only present if you have cached your config on your local environment. If you have ever run php artisan config:cache or php artisan optimize, you have cached your config.
As a result, laravel will no longer read your .env file and load all values for config and .env from cache.
It is best practice, to not use env() throughout your application but create config files for these values. This will speed up your application in production. If you want to take advantage of config cache, you CAN NOT use env() anywhere but in your config files.
In your local environment, the documentation recommends you should not be caching your configuration, since it will be updated frequently. I think this is good advice with one caveat: env(). If you aren't caching your config on local, but are in production, you won't come across errors like the one that was the impetus for this post in local. If you have a ci pipeline and good testing practices than this hurdle is overcome.
If you stick with cache config in local, every time you update your config files or your .env file you will need to run php artisan config:cache.
Disabling config cache
By running php artisan config:clear or removing /bootstrap/cache/config.php laravel will no longer to attempt to read config from cache, and .env will work outside of config files. If you do this, as I stated in (1) make sure there is a part of your pipeline that will catch these errors, if you are caching config in production.
After more discussion with OP, I will make one more thing clear:
Cache config does not automatically just cache your .env keys so you can access them like config('SOME_CUSTOM_DOT_ENV_KEY'). When using cache config, if you need to access environment variables inside of your application, you must reference them in a config file.
Again, once config cache is enabled,.env becomes useless, but it is used to build the cache.
So if you in .env say:
GOOGLE_API_TOKEN=xxxx
You would maybe create a config file like:
google.php
return [
'api_token' => env('GOOGLE_API_TOKEN', 'some-default-value'),
];
And in your application, you will only reference config('google.api_token') and never env('GOOGLE_API_TOKEN').
After upgrade from 5.0 to 5.8, laravel stopped reading env variables if the env is different than .env file.
For example, if i have .env file with the USE_SSL=true inside it.
env('USE_SSL') will be true
But if i have .env file pointing to another env:
APP_ENV=dev
and than i'll have .env.dev file containing USE_SSL=true , env('USE_SSL') will be null.
I tried composer dump-autoload and php artisan config:clear, and php artisan config:cache - no luck. cached or not, i can't get the value.
I tried naming the files .dev.env and .env.dev - no luck.
Any ideas would be appreciated.
I'm adding this as an answer, but please note this isn't how .env file should be used according to laravel docs. It's just a way i needed to use due to some restrictions which required me to use different config files for each env, and load it in runtime. For correct usage of .env file check the docs.
This is a way of loading different config files in runtime depends on where the APP_ENV is pointing. I'm marking this as answered since it's answering this specific question.
.env
APP_ENV=specific_domain
.env.specific_domain
USE_SSL=true
Http/Kernel.php
public function __construct(Application $app, Router $router)
{
parent::__construct($app, $router);
$app_env = explode("=", file($app->environmentFilePath(), FILE_IGNORE_NEW_LINES)[0])[1];
$app->loadEnvironmentFrom(".env.$app_env");
}
Alright if you really wanted to do this,
Route::get('renderEnvChaining',function(){
$myCustomEnv = parse_ini_file(base_path(env('CUSTOM_ENV')));
return $myCustomEnv['USE_SSL']; // This will return true
});
In my .env file i've mentioned this,
CUSTOM_ENV=.env.example
Now i in default env.example i put this
USE_SSL="true" // This will return true
USE_SSL=true // This will return 1
I just found that .ini and .env follows the same values, so i parsed .env file as .ini file,
Give this a try, i've never done this thing before, please concern with other developers before running this into production server
I am very confused about the environment in Laravel 4.2. I have setup my environment folders in the /config folder. I then added the following:
$env = $app->detectEnvironment(array(
'production' => array('my-server-name'),
'local' => array('my-local-name')
));
where my-server-name and my-local-name where taken from the terminal by running hostname.
When I do this however, no matter where I run the code, the environment is always production. What am I doing wrong?
I think you're not using detectEnvironment correctly. In this function, YOU are supposed to return the environment used, based on a config file, or an external environment variable - not get the environment. If you look at the documentation, you'll see some samples on how to use detectEnvironment properly, with both config file, or external variable (e.g. set the environment variable MY_LARVEL_ENV=local at the command line, and access it using $_SERVER['MY_LARAVEL_ENV'] inside the function, to return the proper environment.
in the beginning of a project in laravel could be a really mess with the roots and all that stuff, so I recommend you to follow this tutorial!
https://github.com/JeffreyWay/Laravel-4-Generators
Go to the root of your project on cmd and follow the steps,once your ready, just type:
php artisan generate:scaffold theNameOfYourTable
And say yes!
It will create you all te MVC, Seeders,Standar of your project, and some other awesome staff. ;)
I am currently deploying a Laravel project on my shared hosting account. It is an open project and hosted on GitHub as a public repository. As a result I'm using dynamic variables set by an .htaccess file in my database.php configuration file for my production environment. This allows me to also update my deployment using a git pull command on my host which helps speed up work.
The database.php file has something similar to
$database = $_SERVER['DBNAME'];
$database_user = $_SERVER['DBUSER'];
This is much like what is done when deploying to PagodaBox & works perfectly fine for the application with all things functioning as expected in the browser, no complaints.
The problem I have is that artisan is unable to use these variables and will attempt instead to connect to the database using what I believe to empty variables when processing a migrate instruction. I get an error that artisan tried to connect to the databases with no password. I have been calling artisan using --env=production and have tested this but found that it will only work if the database.php file has the variables specified explicitly instead of as environment variables.
Is there a way of causing artisan to "see" these environment variables?
answers that have proved useful to me so far:
http://forums.laravel.io/viewtopic.php?pid=8455
and
Environment driven database settings in Laravel?
Because Artisan is a CLI PHP request - the request never hits the .htaccess file - and therefore your variables are never set.
As a workaround - you could define the variables inside the artisan file itself on line 3 (just after the <?php)
$_SERVER['DBNAME'] = 'test';
$_SERVER['DBUSER'] = 'something';
edit: I just noticed you said this is public hosted on github - so you wont want to include your username/password in the file? Maybe put the artisan file as part of the .gitignore group - so you dont push/pull that single file?
The capability to set up environment variables is built in to Laravel, so there's no reason to do it in .htaccess. Laravel's built-in way works with artisan without any trouble.
See this part of the docs about environment variables you would like to protect.
http://laravel.com/docs/configuration#protecting-sensitive-configuration
Quoting:
... create a .env.local.php file within the root of your project [...] The .env.local.php should return an array of key-value pairs, much like a typical Laravel configuration file:
<?php
return array(
'TEST_STRIPE_KEY' => 'super-secret-sauce',
);
All of the key-value pairs returned by this file will automatically be available via the $_ENV and $_SERVER PHP "superglobals". You may now reference these globals from within your configuration files:
'key' => $_ENV['TEST_STRIPE_KEY']
Be sure to add the .env.local.php file to your .gitignore file. This will allow other developers on your team to create their own local environment configuration, as well as hide your sensitive configuration items from source control.
Add your private environment variables
<?php
return array(
'MY_SECRET_KEY' => 'super-secret-sauce',
);