There was a Laravel .env variable loading Issue. We were having issues loading GOOGLE_MAPS_API API keys from .env for our Laravel app. So we tried debugging the loading of the Laravel .env file in which the variable was stored. From there the variable should output the Google Map API key on the frontend. This by loading it in a blade view Here is what we tried, learned and what worked in the end.
Frontend Output .Env Variable
To output the .env variable on the frontend we were using:
<script src="https://maps.googleapis.com/maps/api/js?key={{ env('GOOGLE_MAPS_API') }}" async defer></script> <script>
As you can see we use the env() function created by Laravel. But all we saw was:
<script src="https://maps.googleapis.com/maps/api/js?key=" async defer></script>
Emptying Configuration Cache
Doing a simple:
php artisan config:cache
This so you empty all configuration data stored. It empties and rebuilds the cache. No need for
php artisan cache:clear
On reloading the admin the errors:
Google Maps API warning: NoApiKeys https://developers.google.com/maps/documentation/javascript/error-messages#no-api-keys
kept on popping up though. So still there was a Laravel .env variable loading Issue.
PHP OpCache
Then we decided to empty PHP OpCache. This is setup using our Stedding Laravel Stack . The emptying should be working during deployment using:
after('db:migrate', 'cachetool:clear:opcache');
in our deploy.php using Deployer‘s awesome deployment app. But it was not helping so we though why not do it manually and see. So we did a:
/etc/init.d/php7.1-fpm restart
from the server using ssh. And then the errors went away. Well, we thought. As soon as we changed data for the map module we got the same error and geolocation error:
Geocoding Service: This service requires an API key. For more information on authentication and Google Maps Javascript API services please see: https://developers.google.com/maps/documentation/javascript/get-api-key
So it was not the OpCache either.
Memcached
We have Stedding setup with Memcached for database calls caching. Inside config/cache of our Laravel app we just had the basic:
memcached' => [ 'driver' => 'memcached', 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 'sasl' => [ env('MEMCACHED_USERNAME'), env('MEMCACHED_PASSWORD'), ], 'options' => [ // Memcached::OPT_CONNECT_TIMEOUT => 2000, ], 'servers' => [ [ 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 'port' => env('MEMCACHED_PORT', 11211), 'weight' => 100, ],
And to empty it you can use:
echo 'flush_all' | netcat localhost 11211
and we got OK as a response. No changes with the Google Map API nor Geolocation errors though. And we soon realized why. Memcached was not properly setup really. Environmental variables to run Memcached properly were not setup. And on thinking further we realized these keys would not be database stored anyways.. No idea why we tried this, but we learned more about Memcached in the process so good.
Laravel Views
Well, we hadn’t emptied the Laravel views yet. So we thought we would give this a try using:
php artisan view:clear
Did also not work though. Was worth a shot as we did have an output issue, but no go. So we were pretty desperate by now really.
Env() function is disabled on Production
Then I did some more digging on Laravel caching and came onto this beautiful SO thread on issues with using .env in connection with configuration caching for production. It stated:
This is because how caching works in Laravel, you have an storage/cache folder where is stored a “compiled” version of your configuration files when you use the command php artisan config:cache, so it is lighter and faster. In that caching process, Laravel reads the .env file and replaces all values using the env() helper function.
Now, to access the compiled version of the config, which is normally already in memory, you need to use the config() helper, otherwise you would be accessing a file, a much slower approach.
The reason behind disabling the env() function once you cached your configurations is to ensure the performance in the production enviroment, because it is assumed it is the situation where the compiling would take place.
In conclusion, it’s the decision, you may like it or not, IMO it makes things a bit cleaner and forces you to have a more optimized and organized application.
So env() is disabled once:
php artisan config:cache
is used and this tends to be used to compile all configuration data inside storage/cache. And to access that you will be needing the config() helper. So to load the Google Map API key from the compiled config config() needs to be used. Otherwise you wind up emptying cache all the time to make the env() work and avoid a Laravel .env variable loading issue