I am working on Laravel 4.2.
I've three environments - Local i.e. my localhost on WAMP, dev i.e. development environment on Ubuntu digital ocean and production - i.e. Production environment on Ubuntu Amazon.
Now, each time I deploy the code on each environment, I am forced to manually setup host name, database name, user and password.
I go through the Laravel documentation as well as some searching and finally I've created 3 directories inside app/config/ directory namely - local, dev and production. I've placed database.php inside each directory with the said database connection settings.
Now I've created a evn.local.php file in the root directory for local environment as below :
<?php
return [
'STRIPE_SECRET' => 'my-secrete-test-stripe-key',
'APP_ENV'=>'local'
];
And also have changed $app->detectEnvironment function of \bootstrap\start.php as :
$env = $app->detectEnvironment(function(){
return getenv('APP_ENV') ? : 'local';
});
It is working fine for local but I am not sure will it work for dev and production or not.
Also, in App/Config/Services.php I've placed code :
'stripe' => array(
'model' => 'User',
'secret' => $_ENV['STRIPE_SECRET'],
)
and If I use like
Config::get('services.stripe.secret')
it is giving me the secrete key I've placed in evn.local.php but if I use the same to get the environment in \bootstrap\start.php as :
$env = $app->detectEnvironment(function(){
return $_ENV['APP_ENV'];
});
it is not working. Gives error Undefined index: APP_ENV.
Can anyone guide me what am I missing? Or am I handling it wrong way?
Related
My Problem
I am having trouble loading my environment variables on Heroku production.
When pushing to Heroku I get following error message during the build script:
Failed to load ./.env.
Current Setup
I am using a .env file in the root of my app locally. I can succesfully load my environment variables using the dotenv-webpack plugin as follows:
//webpack.config
const Dotenv = require('dotenv-webpack')
module.exports = {
// other settings...
plugins: [
new Dotenv(),
]
};
Loading the environment variables:
//server.js
require('dotenv').config();
console.log(process.env.MY_VARIABLE);
This works like a charm locally, but fails on Heroku.
Note: My config vars have been set on Heroku, so that's not the problem.
What I tried
I have already tried to force load the .env file from the root of my app like this:
new Dotenv({ path: path.resolve(__dirname, './.env') });
Someone also pointed out that the Heroku environment might be system wide environment variables so I tried to load them using:
new Dotenv({ systemVars: true });
Neither of these attempts worked for me.
My guess
I have noticed that Heroku saves their .env file under ./tmp/build_someRandomBuildId/.env. My guess is that the .env file is not on the root of the directory, hence why dotenv can't find it. There is also no way to hardcode the location of this file in my Webpack configuration as the build ID is randomized with every build. Is there a way to tell Webpack to look for the file in a dynamic location?
Today i stumbled upon this problem, i tried several solutions but none worked. My App was working locally but in production mode (heroku) it was not loading process.env correctly.
then i found this https://www.npmjs.com/package/dotenv-webpack
//webpack.config.js
plugins: [
new Dotenv({ systemvars: true }),
],
Just setting systemvars to true does the trick..
For now I have tested this using different keys for the .env file and the heroku dashboard; They are not connected, and they replace themself correctly in production or dev mode.
Use the package "dotenv-webpack" instead of "dotenv".
I hope this saves some time to anyone facing the same problem
I finally found the solution, leaving this here for others who have the same problem as I did.
I used dotenv-webpack to set my environment variables locally, which worked like a charm. Heroku on the other hand sets their environment variables automatically, so there is no need to set them yourself. There is no need to look for a .env file. All I had to do was split up my webpack.config in 2 separate files.
//webpack.dev
require('dotenv').config();
plugins: [
new Dotenv()
],
Load .env file locally.
//webpack.prod
require('dotenv').config();
plugins: [
new webpack.DefinePlugin({
'process.env': {
'YOUR_VARIABLE': JSON.stringify(process.env.YOUR_VARIABLE),
}
});
]
Get your environment variables from Heroku and write them to your own process.env
If you are not using Webpacks, the idea's solution is similar to the accepted answer.
Heroku works on "production" mode by default, so if the problem in Heroku is with Dotenv (which should not be used anyways in Heroku), disable the use of Dotenv in production time like this:
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config() }
}
...and then, access env variables just by doing:
var someVar = process.env.SOME_VARIABLE;
Don't forget to set the environment variables on Heroku first by using Console Commandline in your app's dashboard, or with an app.json file.
I am new with laravel and I am confused on how to setup my server environment configuration. So here is a sample code I've seen in some tutorials, but still I am not satisfied that this would be flexible enough specially when my other co-developers use it.
$env = $app->detectEnvironment(array(
'local' => ['127.0.0.1', gethostname()],
'production' => ['ipforproductionhere'] ));
You can put in local names of your and other developer PC for example:
'local' => ['yourpcname', 'yourcoworkerpcname', 'yourothercoworkerpcname'],
And of all you when developing on those machines will work in local environment.
EDIT
You can also use other type of environment detecting for example:
$env = $app->detectEnvironment(function(){
if (!isset($_SERVER['HTTP_HOST']) ||
strpos($_SERVER['HTTP_HOST'],'.') === false) {
return 'local';
}
return 'production';
});
Now assuming each developer create virtualhost without a dot and uses for example http://myproject as domain it will use local environment and if dot will be found in HTTP_HOST it will use production environment.
$env = $app->detectEnvironment(array(
'local' => array('*localhost*'),
'test' => array('chan.app'),
));
This is how I set in boostrap/start.php, and I set ip in hosts file
127.0.0.1 localhost
127.0.0.1 chan.app
No matter I type http://localhost/ or http://chan.app, App::environment() always reveal production, therefore I can't change database config for it.
Open your CMD (Mac, Linux, and Windows) and type the command:
hostname
this will return the name of your computer. Then use that name:
$env = $app->detectEnvironment(array(
'local' => array('ComputerName'),
));
Because of security issues, the use of url domains in environment is forbidden. Laravel says to use hostnames instead.
This is why I doubt, that Laravel would recognise (detect) your configuration correctly, as both are on the same machine.
From the 4.2 Upgrade Guide:
Environment Detection Updates
For security reasons, URL domains may no longer be used to detect your
application environment. These values are easily spoofable and allow
attackers to modify the environment for a request. You should convert
your environment detection to use machine host names (hostname command
on Mac, Linux, and Windows).
EDIT
Let's say, you want a local and a live environment.
1. Create folders for each configuration:
Create a folder local & live inside /app/config/
Inside each of those folders you create the config file(s) you wish to override from /app/config/,
For example, in your live (production) environment, you don't want to have the debug option activated.
Create a file app.php in the /app/config/live folder.
Inside, you'll just return the desired options to override, as defined in the original /app/config/app.php.
return array('debug' => false);
In the local environment, 'debug' would be set to true, for development.
2. Add the environment to the framework:
In your /bootstrap/start.php file:
$env = $app->detectEnvironment(array(
'local' => array('local-machine-name'),
'live' => array('yourdoamin.com')
));
That's the important part:
- Development (local): --> machine name
- Production: --> root-url (yourdomain.com) which represents the "machine" name
See the docs about environment config for further information.
In Laravel 4, I'm setting up my local development machine (my laptop) and then I have my production server.
In my /bootstrap/start.php
$env = $app->detectEnvironment(array(
'local' => array('MacBook-Pro-2.local'),
'production' => array('ripken'),
));
I then created a .env.local.php in my root directory with the following:
<?php
return [
// Database Connection Settings
'db_host' => '127.0.0.1',
'db_name' => 'censored',
'db_user' => 'censored',
'db_password' => 'censored'
];
That part works. However, I went to my production server and created the same exact file, called it .env.production.php and it doesn't load the variables from that file. I don't know what made me think to do it but I renamed that file .env.php without "production" in the name and it works.
My question therefore is, why wouldn't .env.production.php work? I thought that is what the good folks over at Laravel wanted me to name my various environment files.
Production is the 'default' ruleset, so it is a bit special. Laravel will look for the "base" or "default" rules when loading production, rather than the actual name production.
So you can change
$env = $app->detectEnvironment(array(
'local' => array('MacBook-Pro-2.local'),
'production' => array('ripken'),
));
to
$env = $app->detectEnvironment(array(
'local' => array('MacBook-Pro-2.local'),
));
That way anything that is not "MacBook-Pro-2.local" is going to be production automatically. Then just use the default .env.php for the production settings.
Every other env needs to be explicitly defined - such as .env.local.php and .env.testing.php etc
I am writing my code on Nitrous.IO using Laravel I configured my start.php to the following
$env = $app->detectEnvironment(array(
'local' => array('harrenhal-php-95199'),
'staging' => array('*.herokuapp.com'),
));
I tried this format I also tried the hostname itself both seems not to working. is there a specific practice to do so?
Once I run hostname on the shell in heroku I get this result "9e7831e0-284c-48b8-88a4-3afbbbac0b35" which changes over time.
the problem php don't detect herokuapp.com so the staging environment doesn't work
From the Laravel docs
If you need more flexible environment detection, you may pass a
Closure to the detectEnvironment method, allowing you to implement
environment detection however you wish
$env = $app->detectEnvironment(function()
{
return $_SERVER['MY_LARAVEL_ENV'];
});