How to set the environment in a Symfony2 console command - symfony

Hopefully a simple question - how does one specify which environment to use when running a console command in Symfony2. I've created a few commands, however I would like to run them in the context of my 'staging' environment when on my staging server and my 'prod' environment when on my production server (the different environments define different database connections). How do I configure and pass this information to my console command?

You have two options that will help you out. You can specify the environment that the console will run in with the --env flag, and use --no-debug to disable debug mode.
php app/console --env=staging your:console:command or php app/console --env=prod your:console:command should do what you're looking for (the console runs in the dev environment with debug on by default).
You can look at the code of the app/console file for more info.

You can also use the SYMFONY_ENV environment variable to set a default environment distinct to 'dev' (e.g. export SYMFONY_ENV=prod in ~/.bash_profile)

To answer the question #croca had, to expand on what #Francesc Rosàs posted, and as #Problematic suggested.
If you look in app/console you should see $env = $input->getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev');
All this does is checks the input arguments passed to the console for --env or -e, checks the default value from getenv('SYMFONY_ENV'), or sets it to dev if neither are supplied.
It is then passed to $kernel = new AppKernel($env, $debug);
You could essentially either make changes directly to app/console to achieve your application's specific functionality or copy app/console to a separate file such as app/exec, then process the $env variable how you prefer to determine the desired environment.
Simple Example: app/exec
#!/usr/bin/env php
<?php
/**
* disabled debug mode,
* set environment based on requesting address being local
* otherwise the server's IP address
* be sure to perform at least chmod(750) on the file to ensure it is executable
* otherwise it must be prefixed with your php executable
*/
set_time_limit(0);
require_once __DIR__.'/bootstrap.php.cache';
require_once __DIR__.'/AppKernel.php';
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
$input = new ArgvInput();
$env = ($_SERVER['REMOTE_ADDR'] === '127.0.0.1' || $_SERVER['REMOTE_ADDR'] === '::1' ? 'dev' :
($_SERVER['SERVER_ADDR'] === '192.168.2.1' ? 'test' : 'prod')
);
$kernel = new AppKernel($env, false);
$application = new Application($kernel);
$application->run($input);
Then call php app/exec namespace:command arguments --flags
Additionally you could process your own application instead of using the app/console AppKernel - instructions from Symfony can be found here: http://symfony.com/doc/current/components/console/introduction.html

The official documentation says:
By default, console commands run in the dev environment and you may want to change this for some commands.
So, as #Problematic suggest, you can specify the environment for your command using the flag "--env=your_env" or its shortcut "-e your_env".
I wonder whether it is possible to force the default environment for a command. I mean, without having to use the flags. Any idea?

There is another variant, not so convenient though, but works also with composer
SYMFONY_ENV=prod app/console cache:clear

Maybe you could look at the implementation of the cache:clear command. This may give you some clues on how to choose the environment from a command.
app/console help cache:clear

Related

remove test database when tests ends (Symfony / PHP Unit)

I am using PHPUnit (9.5) with Symfony (5.3).
For my tests, I use the default test database config from config/packages/test/doctrine.yaml :
doctrine:
dbal:
# "TEST_TOKEN" is typically set by ParaTest
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
So my tests use the same database as prod with the suffix '_test'.
I added some code to tests/bootstrap.php to automate database creation / reset before each test runs :
// delete database if exists, then create
passthru('php bin/console doctrine:database:drop --env=test --force --if-exists');
passthru('php bin/console doctrine:database:create --env=test');
// run migrations
passthru('php bin/console doctrine:migrations:migrate --env=test -n');
and I use dama/doctrine-test-bundle for automatic transactions for each tests.
That is working very well, but I have a question :
Is there a way to delete the database at the end of test run ? (like I did in bootstrap.php)
I understand that your bootstrap.php file is running before the test, you need a solution to launch something after your test.
First, create a command that drop the test database.
In anyway, be very careful that the code in your command stop all execution, if you aren't in an explicit test environment (because it means you are in a production environment).
Then, you can alter your composer.json file to launch the created command after your test in a chain of scripts.
Here is an exemple
"scripts": {
"test-and-remove": [
"#putenv APP_ENV=test",
"phpunit --configuration phpunit.xml",
"php bin/console app:drop-test-database"
],
Then you only have to launch your test via this new command:
composer test-and-remove

In Symfony 5, the command doctrine:database:create outputs an error instead of creating a database for test environment

I'm learning Symfony 5 at Symfony 5: The Fast Track and I'm at the step 17.4 Working with a Test Database.
I can read from the beginning of this section:
... the Symfony CLI automatically exposes the DATABASE_URL
environment variable. When APP_ENV is test, like set when running
PHPUnit, it changes the database name from main to main_test so
that tests have their very own database.
Before being able to run the test, we need to “initialize” the test
database (create the database and migrate it):
$ APP_ENV=test symfony console doctrine:database:create
$ APP_ENV=test symfony console doctrine:migrations:migrate -n
My database name is guestbook, running under MySql & Apache, as specified in the .env file:
DATABASE_URL="mysql://root:#127.0.0.1:3306/guestbook?serverVersion=mariadb-10.4.19"
So, while I was expecting a database named guestbook_test to be created when I execute the command symfony console doctrine:database:create, it outputs the following error:
Could not create database `guestbook` for connection named default
An exception occurred while executing 'CREATE DATABASE `guestbook`':
SQLSTATE[HY000]: General error: 1007 Can't create database 'guestbook'; database exists
exit status 1
To make sure the environment is "test", I, first, tried these two ways:
In the .env file: APP_ENV=test
In the .env.local file: APP_ENV=test
But, I got the same error.
When I displayed the content of environment variable APP_ENV from a controller, using return new Response("APP_ENV = '" . getenv('APP_ENV') . "'");, it displays a null value: APP_ENV=''.
So, I assigned the value 'test' to APP_ENV in Real environment variables (for me, that was Windows/Paramaters/environment variables...etc). This once, the controller displays APP_ENV='test', but I get always the same error, when I execute the Doctrine command: symfony console doctrine:database:create
I don't know what I'm missing !! Please, any help?
UPDATE ON: 07 June 2021 22:05
I, even tried assigning the value test to APP_ENV in php.ini; but, when I displayed this env var using: symfony console debug:container --env-var=APP_ENV, I got:
Symfony Container Environment Variables
=======================================
// Displaying detailed environment variable usage matching APP_ENV
None of the environment variables match this name.
It's, little bit, strange since I have this env var assigned every where (in .env file, .env.local, php.ini and in a real env vars) and this command says there is no env var called APP_ENV !
What helped in my case:
create .env.local file
copy the DATABASE_URL variable with db name suffixed with _test
I also had to change db user to root, as my app db user didn't have permissions to create databases,

Symfony debug still enabled after cache:warmup --no-debug

I have Symfony 3.2.7 installed on a production server.
I issue the following commands:
bin/console cache:clear --no-warmup --no-debug --env=preview
bin/console cache:warmup --no-debug --env=preview
bin/console --version
I get the following output, showing that debug is enabled.
Symfony 3.2.7 (kernel: app, env: preview, debug: true)
What am I missing?
Nevermind.
Bad programmer on device.
The monolog.handlers.main.level value was set to debug.
Duh.
Sorry for the noise.
I've never used bin/console in a production server, but I don't think that information is reliable for your use case.
If you open the bin/console script in an editor you will see:
$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(['--no-debug', '']) && $env !== 'prod';
As you can see the $debug parameter is determined by a combination of environment variables and parameters.
Every time you call this script this value is recalculated.

Symfony2 Composer and environment variables

I would like to set the configuration of my symfony2 project using environment variables.
In the server I have defined:
SYMFONY__DATABASE__USER
SYMFONY__DATABASE__PASSWORD
SYMFONY__DATABASE__NAME
SYMFONY__DATABASE__HOST
SYMFONY__DATABASE__DRIVER
My parameters.yml.dist looks like this:
#app/config/parameters.yml.dist
parameters:
database_host: "%database.host%"
database_port: ~
database_name: "%database.name%"
database_user: "%database.user%"
database_password: "%database.password%"
database_driver: "%database.driver%"
when I run composer I get an exception
composer install --dev --no-interaction --prefer-source
[Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException]
You have requested a non-existent parameter "database.driver". Did you mean one of these: "database_user", "database_driver"?
These variables are defined in the server so I can modify the parameters.yml.dist to define these values. But this does not seams the right way, because wat I really want to use are the environment variables.
Note: I want to read this environment variables in travis, heroku and my vagrant machine. I only want to have in the repository the vagrant machine variables.
Which is the proper way to do this?
How should look my parameters.yml.dist?
Looks you are doing everything okay.
Here is the complete documentation for Setting Environment Variables which I believe you already read.
What is important to note is this:
Also, in order for your console to work (which does not use Apache),
you must export these as shell variables. On a Unix system, you can
run the following:
$ export SYMFONY__DATABASE__USER=user
$ export SYMFONY__DATABASE__PASSWORD=secret
I remember once I have a similar issue, I was setting everything on APACHE, but when running commands it wasn't working because I forgot to EXPORT the variables on the system.
Be aware that using export is a temp solution, if you reset your server those values will be lost, you will need to setup in a permanent way according to your OS.
I think you solved this long time ago, but the problem is actually that you have 2 _ between DATABASE and USER and the parser for this have a string replace function that replaces every __ with a . .
For your example to work you should have written like this:
SYMFONY__DATABASE_USER -> database_user
SYMFONY__DATABASE__USER -> database.user
You can try this bundle if your system version is >= 2.6.2:
This bundle provides a way to read parameters from environment
variables at runtime. The value defined in the container parameter is
used as fallback when the environment variable is not available.

Why does Symfony2 set the error_reporting?

I've been trying to remove the E_NOTICE and E_STRICT error levels to avoid this error:
Runtime Notice: Only variables should be passed by reference
I tried modifying php.ini but didn't work, error_reporting always is -1. Then I tried setting it dynamically in the current action, and worked fine. Then I also tried the same in the first line in app_dev.php and didn't work. Which means Symfony2 is setting it dynamically somewhere.
What should I do?
EDIT
For those who are not familiar with the error:
$user = $this->('security.context')->getToken()->getUser();
$first = reset($user->getRoles()); // error
$roles = $user->getRoles();
$first = reset($roles); // works fine
Whilst the notice is not 'retarded', this is a reasonable question in other contexts so: this is set in the Kernel instance, instantiated in app_dev.php (or app.php).
The second parameter to the construct is a boolean debug flag, and if true then error_reporting is set to -1 and display_errors to 1, otherwise default and 0 respectively.
$kernel = new AppKernel('dev', false);
symfony documentation
Hope this helps.
I got the same error in the following scenario i.e.
Scenario:
I lost the development environment for my existing LIVE project. But I got the whole code from GIT repo and then installed the symfony 2.4.2 (same version as on LIVE site) in my new development environment. Then I found that the web-application pages working on the LIVE site are broken in my new DEV environment.
Solution:
I spent quit a lot time to understand why the problem is then I found that i.e.
When I installed symfony 2.4.2 in my development environment using composer.phar then it created a new web/app_dev.php file in my development environment and it has the following entry to turn it off i.e.
Debug::enable();
Just comment the above line then the php notices will be off and then all the pages that were giving me notices are fixed.
I hope this will be helpful for someone having the same problem like me. Good Luck!
Cheers.
PS: But I will recommend to enable the above line in your new development projects so that you can see the PHP notices and then remove them during development.

Resources