Executing config:cache command during deployment - laravel

I have a secret test key for a payment gateway in the .env file.
APP_TIMEZONE = 'Africa/Lagos'
APP_PAYSTACK_KEY = sk_test_b6c0b4925403blablabla
Reason is that other people working on the project can use their own test key if they have. So in a payment controller i get the value of this key like so:
"authorization: Bearer " .env('APP_PAYSTACK_KEY' , 'sk_test_b6c0b4925403blablabla')
During deployment I intend running config:cache so that Laravel won't be going a long trip in getting the required configuration setups. But from Laravel documentation :
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. Once the configuration
has been cached, the .env file will not be loaded and all calls to
the env function will return null.
So my question is how can I set this APP_PAYSTACK_KEY in the config file and how to retrieve it anywhere in my app?

You can add paystack to your config/services.php file:
<?php
return [
/*
|--------------------------------------------------------------------------
| Third Party Services
|--------------------------------------------------------------------------
|
| This file is for storing the credentials for third party services such
| as Stripe, Mailgun, SparkPost and others. This file provides a sane
| default location for this type of information, allowing packages
| to have a conventional place to find your various credentials.
|
*/
// ...
'paystack' => [
'key' => env('APP_PAYSTACK_KEY', 'sk_test_b6c0b4925403blablabla'),
],
];
Then call config() helper method instead of env() on your controller:
"authorization: Bearer " .config('services.paystack.key')
Now you're safe to cache your configs via calling php artisan config:cache.

Related

Laravel Enviroment Variables are not working within Google Cloud Run

I've deployed too many times Laravel projects up to Cloud Run successfully, but right now
It looks like Cloud Run is unable to read Enviroment Variables (which i've specified already in the Variables&Secrets section within Cloud Run instance).
I'm using Laravel 8. For testing purposes (and make sure Cloud Run it's reading env variables), i've added a simple route in the api.php section like belows:
Route::get('/test-env', function () {
echo 'debuggeando<br>';
dd(config('variables.test_env'));
});
Into my config/variables.php i've the follows:
<?php
return [
'test_env' => env('TEST_ENV', 'no se encontro la variable')
];
And this is my final result:
What do am I doing wrong? Why Cloud Run is unable to read the enviroment variables from Laravel?
You can only make Laravel pick up envirnmental variables, but not the other way around.
config(['test_env' => getenv('TEST_ENV')]);
Running php artisan config:clear & php artisan config:cache might be required. Another option might be to generate a fresh .env file during the deployment, which merely translates to: already defining the value, before it can be cached.

Laravel - How to clear config:cache on each request

I am working on a project which will have 50 subdomains and I found a solution to load separate .env file based on a domain name and everything is working fine... now my problem is
I have to run command config:cache to clear the cache so sytem can load relevant .env file, otherwise, it keeps loading the older .env file. How can i ask system to do cache clear on each load in bootstrap/app.php file???
My Code to load .env files in bootstrap/app.php
$domain = '';
if(isset($_SERVER['HTTP_HOST']) && !empty($_SERVER['HTTP_HOST'])){
$domain = $_SERVER['HTTP_HOST'];
}
if ($domain) {
$dotenv = \Dotenv\Dotenv::create(base_path(), '.env.'.$domain.'.env');
try {
$dotenv->overload();
} catch (\Dotenv\Exception\InvalidPathException $e) {
// No custom .env file found for this domain
}
}
I would advise against doing that because things WILL break.
However, to answer your question, you can use Artisan::call('config:clear') inside a middleware that you can call on each request.
But instead of doing that, you could build a middleware that detects the subdomain you're getting the request from and then call the command instead, just to avoid that extra load.
I used another way to solve this on my project. It is setting the config dynamically according to the request. The config is only valid for the current request. If the count of the dynamic config is less you can use
Config::set('myConfig.hostName', $hostName);
Before doing that you must use the package
use Illuminate\Support\Facades\Config;

Calling passport:client from route, "there are no commands defined in the "passport" namespace"

I have an issue where the passport namespace is not available when I call passport:client. I set up a brand new Laravel project with version 5.6.34 where I installed Laravel passport according to the documentation. I also checked a similar question and followed all steps there with no sucess.
Calling php artisan passport:client --password --name="Test" from the command line works without any issues and I can see the client in the database.
However if I create a route in routes/web.php like so:
<?php
use Illuminate\Support\Facades\Route;
use \Illuminate\Support\Facades\Artisan;
Route::get('/', function () {
Artisan::call('passport:client', [
'--password' => true,
'--name' => "Test client",
'--quiet' => true,
]);
});
and use the Artisan facade to call the command I get the error below when I navigate to http://homestead.test/.
Symfony \ Component \ Console \ Exception \ CommandNotFoundException
The command "passport:client" does not exist.
I have added Laravel\Passport\PassportServiceProvider::class in the providers array in config/app.php.
How can I call the passport:client command from a web route?
We have a Laravel application that has several hundred database connections which are handled dynamically. In the admin interface you can create a new project and thus a new database where we need to generate a client.
My other option is the instantiate a ClientRepository and call the createPasswordGrantClient() method but I would like to avoid this if possible. I am curious to know why the namespace is available when called on the CLI but not via a request. I can call other commands such as migrate:fresh via a request but passport:client will fail even if it is part of the migration or inside another command.
According to this link, I ran the below commands.
composer update
php artisan config:cache
php artisan migrate
php artisan passport:install
This helped me.

Invalid API key: You must be granted a valid key tmdb laravel 5.5

i am trying to install php-tmdb/laravel on my laravel 5.5 but getting error on basic test
Invalid API key: You must be granted a valid key
i try with google and found this link https://github.com/php-tmdb/laravel/issues/38
but its not working or can't understand
help me
auto discovery in this package is not working correctly
just add this on providers
config/app.php
Tmdb\Laravel\TmdbServiceProvider::class,
everything is working fine now
According to the github README.md https://github.com/php-tmdb/laravel
After you install the package, run this command to publish the configuration file:
php artisan vendor:publish --provider="Tmdb\Laravel\TmdbServiceProviderLaravel5"
then edit this file: config/tmdb.php in your application with your api key.
The configuration file should look like this:
https://github.com/php-tmdb/laravel/blob/master/src/config/tmdb.php
Notice 'api_key' => '', fill this in and then re-run your code/test.
Here's where you get your API key from: https://developers.themoviedb.org/3/getting-started
After changing the config, for good measure; clear your config cache with this command:
php artisan config:clear
edit /vendor/php-tmdb/laravel/src/config/tmdb.php
find 'api_key' => '', and add your key here.

What is difference between use env('APP_ENV'), config('app.env') or App::environment() to get app environment?

What is difference between use env('APP_ENV'), config('app.env') or App::environment() to get app environment?
I know that the env('APP_ENV') will to $_ENV, config('app.env') reads the configuration and App::environment() is an abstraction of all. And in my opinion the advantage is even this. Abstraction.
I do not know if there are other differences, such as the level of performance or security
In Short & up-to-date 2022:
use env() only in config files
use App::environment() for checking the environment (APP_ENV in .env).
use config('app.var') for all other env variables, ex: config('app.debug')
create own config files for your own ENV variables. Example:
In your .env:
MY_VALUE=foo
example config/myconfig.php
return [
'myvalue' => env('MY_VALUE', 'bar'), // 'bar' is default if MY_VALUE is missing in .env
];
Access in your code:
config('myconfig.myvalue') // will result in 'foo'
Explanation & History:
I just felt over it. When you cache your config file, env() will (sometimes?) not work right. So what I found out:
Laravel recommends only to use env() within the config files. Use the config() helper in your code instead of env(). For example you can call config('app.env') in your code.
When you use php artisan config:cache all the configuration strings are cached by the framework and any changes you make to your .env file will not be active until you run the php artisan config:cache command again.
From this article on Laracast:
UPDATE:
env() calls work as long as you don't use php artisan config:cache. So it's very dangerous because it will often work while development but will fail on production. See upgrade guide
Caching And Env
If you are using the config:cache command during deployment, you must
make sure that you are only calling the env function from within your
configuration files, and not from anywhere else in your application.
If you are calling env from within your application, it is strongly
recommended you add proper configuration values to your configuration
files and call env from that location instead, allowing you to convert
your env calls to config calls.
UPDATE Laravel 5.6:
Laravel now recommends in its documentation to use
$environment = App::environment();
// or check on an array of environments:
if (App::environment(['local', 'staging'])) {
// The environment is either local OR staging...
}
and describes that env() is just to retrieve values from .env in config files, like config('app.env') or config('app.debug').
You have two equally good options
if (\App::environment('production')) {...}
or
if (app()->environment('production')) {...}
app()->environment() is actually used by Bugsnag, look in documentation here it says
By default, we’ll automatically detect the app environment by calling the environment() function on Laravel’s application instance.
Now, differences:
1) env(...) function returns null after caching config. It happens on production a lot.
2) you can change config parameters inside unit tests, it gives you flexibility while testing.
One thing to consider is perhaps the convenience factor of passing string to app()->environment() in order validate your current environment.
// or App:: whichever you prefer.
if (app()->environment('local', 'staging')) {
logger("We are not live yet!");
Seeder::seedThemAll();
} else {
logger("We are LIVE!");
}
2023 Updated Answer
env() helper works when there is no config.php inside bootstrap/cache directory
config() helper works both in case if the file config.php is present or not. If the file is not present then if will parse the variables at runtime, but if it does find one; it uses the cached version instead.
In production environment the artisan commands we run to add/remove the config file.php becomes of paramount importance in context of how env() and config() behave.
Consider the following example to understand the concept:
Route::get('/', function () {
// to experiment: set APP_ENV=production in your .env file
echo 'Via env(): ' . env('APP_ENV') . '<br/>'; // production
echo 'Via config(): ' . config('app.env'); // production
/*
|--------------------------------------------------------------------------
| run: php artisan config:cache
|--------------------------------------------------------------------------
|
| The config:cache command will generate a configuration cache file (config.php) in the bootstrap/cache directory.
| At this point, the env() helper will no longer work as all ENV variables will be flushed in favor of the cached config.php file.
|
*/
echo '<hr/>';
echo 'Via env(): ' . env('APP_ENV') . '<br/>'; // null
echo 'Via config(): ' . config('app.env'); // production
/*
|--------------------------------------------------------------------------
| run: php artisan config:clear
|--------------------------------------------------------------------------
|
| The config:clear command will remove (config.php) configuration cache file from the bootstrap/cache directory.
| At this point, the env() helper will work again as framework doesn't find a cached configuration file.
|
*/
echo '<hr/>';
echo 'Via env(): ' . env('APP_ENV') . '<br/>'; // production
echo 'Via config(): ' . config('app.env'); // production
});
So general rule of thumb is to always use config() helper inside your code files; in this way your code does not explode if cached configuration file is available or not.
Now getting the environment is so important and common; Laravel gives us a handful ways we can accomplish the same:
// APP_ENV=production inside .env file
App::environment(); // production
app()->environment(); // production
App::environment('production'); // returns boolean: true
app()->environment('production'); // return boolean: true
Keep in mind you are using App facade or app() helper they all will be using config helper under the hood.
If you are using the config:cache command during deployment, you must make sure that you are only calling the env function from within your configuration files, and not from anywhere else in your application.
If you are calling env from within your application, it is strongly recommended you add proper configuration values to your configuration files and call env from that location instead, allowing you to convert your env calls to config calls.
Add an env configuration option to your app.php configuration file that looks like the following:
'env' => env('APP_ENV', 'production'),
More: https://laravel.com/docs/5.2/upgrade#upgrade-5.2.0
In 12factor methodology application contains two types of configuration values:
internal which not vary between deploys and are stored in laravel ./config/ folder. In this type we usually store some technical optimal/good values used in application which should not be changed by users over time e.g. optimal image compression level, connection timeout, session expiration time etc.
external which vary between deploys and are stored in .env file (but should not be stored in git repo, however .env.example with example values with detail info can be stored in repo). In this type we store usually some important/protected values which depends on local environment e.g. passwords, debug mode, db address etc.
Laravel proposes handy approach for this
in regular code we use only config(...) helper (so on this level programmer do not need to know which configuration value is internal and which is external)
in configuration code external config values should be set using env(...) helper e.g. in config/app.php 'debug' => env('APP_DEBUG', false)

Resources