Laravel 5 configuration - environments and overriding - php

I installed fresh Laravel 5 copy.
My detectEnvironment function is defined this way:
$app->detectEnvironment(function()
{
return 'local';
return getenv('APP_ENV') ?: 'production';
});
In config\local I've created database.php file:
<?php
return [
'nothing' => 'new',
];
I run php artisan clear-compiled.
My index method of WelcomeController is defined this way:
public function index(Application $app)
{
echo $app->environment();
var_dump($app['config']['database']);
//echo $app['config']['database'];
return view('welcome');
}
Application was imported this way: use Illuminate\Foundation\Application;
The result I get is:
local array(1) { ["nothing"]=> string(3) "new" }
whereas I would expect Laravel to cascade config file with production one (with the default config\database.php file.
The strange thing is that even if I comment the line return 'local'; run again php artisan clear-compiled it shows:
production array(1) { ["nothing"]=> string(3) "new" }
so it seems it always loads database.php file content (this one from local folder) and overrides main database.php file. It works fine again when I change this file name to for example aaa.php.
Is it a bug or maybe environment configuration shouldn't be stored inside config directory? But if not, where should they be store? I don't know if it's a bug or a feature so if anyone knows more about it, please give me a clue.

Although in documentation for Laravel dev (5.0) there is info that configuration will cascade it's not true. I have tested it about 2 weeks ago and it seems at the moment the only way to have different values for environments is using ENV file where you put custom values for current environment. Putting settings in directories won't work as it used to work however it's possible it will change or maybe has been already changed for last 2 weeks.

There's a package that brings the cascading config system back to Laravel 5.
Disclaimer: I am the author.

For me it looks like defect in Laravel 5 dev branch. I was able to work around by adding manual environment detection and configuration. This code does it.
'default' => $app->environment()=='testing'?'sqlite':'mysql',

It is easy to configure Laravel 5 environment.
Open your root application folder and find ".env.example",
Copy and rename into ".env",
Please fit ".env" file into your environment,
If you use GIT, make sure you don't push this file to your GIT repository.
For 'complete explanation', I write this configuration here.
Edited;
I quote from the developer in His github repository readme.md file;
phpdotenv is made for development environments, and generally should
not be used in production. In production, the actual environment
variables should be set so that there is no overhead of loading the
.env file on each request. This can be achieved via an automated
deployment process with tools like Vagrant, chef, or Puppet, or can be
set manually with cloud hosts like Pagodabox and Heroku.
So, you need to create ".env" file per machine and don't use ".env" file in your production server.

Related

Getting nginx environment variable in laravel with cached config

I use laravel framework on 2 websites,
The application backend is one, but view paths is different for each site.
There is nginx variable "WEBSITE", which is available in PHP (phpinfo prints it).
When I run application locally, all is right. But in production, I get exception what variable is not exists.
I discovered what during deploy running command php artisan config:cache, which cached all config in "bootstrap" directory. I don't may delete this command, because it ups performance of site. This command caches all config including app/config/view.php file that descript changes in view paths, like this
'paths' => [
resource_path('views/' . env('WEBSITE')),
],
but config already cached without variable and in this form is delivered to the production.
I don't understand how fix this problem, other that edit all views, base layouts for both sites. Does anyone know how to solve this problem in a simple way?
Just add a fallback by explicitly adding WEBSITE=somewebsiteurl in your production sites .env, then re-cache the config and try if it works.

.env files in Github Actions CI/CD workflows: how to provide these into the workflow

I use Github Actions workflows for my CI/CD processes for Node and PHP projects.
Within a workflow I clone my repository into Github Actions runner virtual machine. Then in order to run tests within a workflow I have to have the .env file in the cloned repository.
The problem is my .env file is not a part of repository (which is the ubuquitous practice).
To solve the problem I use what I consider a workaround: set up MY_PROJECT_ENV Github Action sercret variable, manually put there the content of my .env file and then dynamically create the .env file within my workflow with Linux console echo "${{ secrets.MY_PROJECT_ENV}}" > .env. This works.
But I would like to know are there other approaches for providing .env files to Github Actions workflows?
There are 3 ways to do this I know by now. I put the answer to my own question a year after in the different question. See there.
For the sake of SO rules and findablity I put here a summary.
You keep your .env file in the repository. Use dotenv actions to read your file into the workflow.
You keep the file out of the repository. Then you have 2 ways of getting .env variables:
2.1. as I wrote in my question above manually copy the file content to the GitHub actions secret variable and then in your workflow create the .env file from that variable.
2.2. Use the GitHub Actions API to create/update the secrets: write the NodeJS script on your machine (chances are you anyway use Webpack, Gulp or the like Node thing so you have Node installed).
The script should read the local .env files and write their content to the GH secrets. Of course you can write a custom console utilty to do this with any language you use in your project.
As easy as this :)
As you know .env doesn't mean to push to the remote repository.
You need to somehow add the environment variables to the machine that you're running the program.
In your case, you can add environment variables by using the .yaml file as below
steps:
- name: Hello Program
run: Hello $FIRST_NAME $LAST_NAME!
env:
FIRST_NAME: Akhil
LAST_NAME: Pentamsetti
for more information please visit github official doc about using the environment variables.
I do the following, which is simple and effective:
Add environment variables (either define them in the yaml file or as secrets) as needed
Keep .env.example in the repository, and run the following at the start of the CI job:
# Create the .env file
cp .env.example .env
# Install dependencies so we can run artisan commands
composer install ...
# generate an APP_KEY
php artisan key:generate
An alternative to this is to commit a .env.ci file to the repository with env vars specific to the CI environment, and run cp .env.ci .env when running tests. Sensitive keys should still be set as secrets.
You can technically provide all of your env vars between secrets / env's in the YAML file and have no .env file, but I like having a random APP_KEY set per test run to ensure there's nothing relying on a specific APP_KEY.
Environment Precedence
As an aside, here's how environment precedence works with Laravel in phpunit tests. This is laravel specific and may come at a surprise as it's not exactly how phpunit alone works outside of Laravel:
Env vars set in phpunit.xml always "win" (this is true in Laravel despite what phpunit's docs say about system env vars taking precedence over phpunit.xml file items)
System environment variations (in GitHub actions, these are ones set as an env var when running commands in the yaml file)
.env file items
Source: I created/run Chipper CI, a CI platform for Laravel.

Trying to Migrate in Development Mode

I'm trying to figure out how I can get my environment set to development mode inside my Laravel application.
bootstrap/start.php
$env = $app->detectEnvironment(array(
'development' => array('blog.app'),
'production' => array('')
));
Inside my routes file I have the following:
Route::get('/', function()
{
dd(App::environment());
});
When I go to blog.app it says its set to production and I'm not sure why. The purpose of figuring out why its giving me production instead of development is because I am attempt to run the command "php artisan migrate" and its giving me the following.
My-iMac:blog my$ php artisan migrate
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command?
So I need help understanding why its still saying application is in production mode when I'm attempting to be in development mode.
Go inside your project directory. Then navigate to bootstrap/start.php.
Edit the local array specified in $app->detectEnvironment with your machine name.
Laravel will automatically check you machine name every time and know that it is a local environment and use the local configuration files instead. To use the local config files you can navigate to app/config/local and edit the files there. The files in app/config belong to the production environment. You can copy these files in the local folder and then edit them accordingly, for example you database configuration probably will differ on your local machine and the server.
You can simply edit the files in the config folders and Laravel will detect automatically the environment according to the array in the start.php and use the config files related to the machine on which you are working. You can also specify more environments and create their entries in the start.php file and then go and create a folder by the same name in the app/config folder and create config files for that environment in that folder.
Example: If you want to have two local environments you can edit you start.php file like so
$env = $app->detectEnvironment(array(
'local' => array('Machine1', 'Machine2'),.
'local2' => array('Machine3', 'Machine4'),
));
And then navigate to the app/config folder and create two folders like local and local2 and have separate files for each of them. Now the machines with names Machine1 and Machine2 will automatically use config files present in local folder and Machine3 and Machine4 will use config files in local2 folder. This way Laravel provides great flexibility in setting environments.
For more information check out the Environments and Configuration Episode on Laracasts.
You need to figure out your machine name. In order to do that, run this code anywhere:
echo gethostname();
exit;
More info about the function: http://php.net/manual/en/function.gethostname.php
It will output your machine name, then you need to paste it in the 'development' array.

Laravel Environment

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. ;)

Artisan unable to use $_SERVER variables from database config file

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',
);

Categories