This is something that could help local developers configure their setups much quicker. With the added support for DSNs in the core, it is now quite easy to get setup.
Why
This isn't a new way to configure applications. Many of us are already taking advantage of this in production through process managers such as Circus, SupervisorD, and Upstart. As well, all popular webservers support the usage of environment variables (SetEnv
in Apache, and various ways with Nginx). In production at least, environment variables allow the changing of configuration without a deploy, which can be a godsend if, for example, your database goes away and you need to swap to a backup.
The other issue I'd like to tackle is different development environments for teams. It's annoying to have to change hardcoded config when moving from one database config to another (we don't all have my_app:secret
setup), and having a .env
file can obviate the need for people stepping over each other while changing config.
How
We can use josegonzalez/php-dotenv, a library I maintain, or vlucas/phpdotenv, which is used in Laravel. Both solve similar problems in different ways. The advantage with the former is that we have more control over features we want/need, though to be honest both would work adequately.
Using my library, we can add the following to our bootstrap.php
file:
try {
josegonzalez\Dotenv\Loader::load([
'filepath' => __DIR__ . DS . '.env',
'toServer' => true,
'skipExisting' => ['toServer'],
'raiseExceptions' => true
]);
} catch (InvalidArgumentException $e) {
// do nothing in case the file doesn't exist
}
Here is a sample .env
file that I use for vagrant
based installations:
export APP_NAME=app
export DEBUG=2
export SECURITY_SALT="DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi"
export SECURITY_CIPHER_SEED="76859309657453542496749683645"
export DATABASE_URL="mysql://my_app:secret@localhost/my_app?encoding=utf8&timezone=UTC&cacheMetadata=true"eIdentifiers=false&persistent=false"
export DATABASE_TEST_URL="mysql://my_app:secret@localhost/my_app?encoding=utf8&timezone=UTC&cacheMetadata=true"eIdentifiers=false&persistent=false"
export CACHE_URL="file:///CACHE/?prefix=APP_NAME_&duration=DURATION"
export CACHE_CAKE_CORE_URL="file:///CACHE/persistent/?prefix=myapp_cake_core_&duration=DURATION&serialize=true"
export CACHE_CAKE_MODEL_URL="file:///CACHE/models/?prefix=myapp_cake_model_&duration=DURATION&serialize=true"
export LOG_DEBUG_URL=file:///LOGS/?levels[]=notice&levels[]=info&levels=[]=debug
export LOG_ERROR_URL=file:///LOGS/?levels[]=warning&levels[]=error&levels[]=critical&levels[]=alert&levels[]=emergency
export EMAIL_URL="mail://user:secret@localhost:25/?client=null&timeout=30&tls=null"
I do a few replacements in my app.php
file like so:
'_cake_model_' => [
'url' => str_replace(
['/CACHE/', 'DURATION'],
[CACHE, '+2 minutes'],
env('CACHE_CAKE_MODEL_URL')
),
],
I can likely make the library smarter and have it do it's replacements not only from bash
but also from PHP constants or existing environment variables.
Errata
We'd need to add documentation on how .env
files work. I have quite a bit of it in the readme for my project, but we'd want to add this to the main docs as well.
Note that this would maybe increase the complexity of setting up an app. We don't want to promote a .env
file in production, but we do want to show users how to configure apps in production. Something to consider.
Developers might think this is something we've stolen from other frameworks, though this sort of thing has been around for quite a while. Rails has had automatic support for DSNs in environment variables since at least 3.x, and the friendsofcake/app-template
project has used them for at least a year. As well, most/all of the core team has used this sort of functionality in the past, though maybe not with a php library to support their dev cycle.
Does adding this break BC? We've not yet made a release of the app
composer project. Should we wait until a 3.1 CakePHP release before doing this? Or are we allowed to make changes like this without waiting for a major release.
Finally, does everyone desire this change? I know this makes it easy for me to write my book, and probably makes tutorial writing slightly easier, but maybe this isn't right for our users. Thoughts?