'How can I make a symfony 4 command to be registered only in dev environment and disabled in prod?
In my App I have a helper class App\Command\GenerateFixturesCommand that provides a command named my-nice-project:generate-fixtures.
This command consumes a service of my own project named App\Services\CatalogFixtureGenerator that generates 1000 random PDF documents for testing while developing the app.
To do so, this service uses the joshtronic\LoremIpsum class which is required in composer only in dev. LoremIpsum is a third-party library. I require it under composer's require-dev.
So the injection is:
- I run my
GenerateFixturesCommand. - Before that, the system transparently locates my
CatalogFixtureGeneratorand to inject it into the command. - Before that, the system transparently locates the
LoremIpsumthird party service to inject it into my fixture generator service.
All is autowired.
When I deploy to prod and do composer install --no-dev --optimize-autoloader of course the LoremIpsum class is not installed.
But when I clear the cache with APP_ENV=prod php bin/console cache:clear the framework finds the command and cannot inject the autowired dependencies.
[WARNING] Some commands could not be registered:
In CatalogsFixtureGenerator.php line 26:
Class 'joshtronic\LoremIpsum' not found
This my-nice-project:generate-fixtures command is never going to be used in the production server.
Question
How can I "disable" the command in prod?
I mean: How can I tell the framework that the class GenerateFixturesCommand should not be loaded nor its autowired dependencies, and neither of them should be autowired in prod?
Solution 1:[1]
Use the isEnabled() method in Command.
For example
public function isEnabled(): bool
{
// disable on prod
if ($this->appKernel->getEnvironment() === 'prod') {
return false;
}
return true;
}
Solution 2:[2]
In my last project, I need some commands to work only in dev environment. You use getenv function to achieve this:
# src/Command/SomeCommand.php
...
public function __construct()
{
parent::__construct();
if (getenv("APP_ENV") !== "dev") {
exit('This command should work only "dev" environment.');
}
}
This will do the trick.
Code fun :)
Solution 3:[3]
The solution @gusDeCooL suggests doesn't work with lazy-loaded commands (at least not for me).
I ended up implementing the isEnabled() method anyway, but then I added a guard in execute():
<?php
namespace App\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(
name: 'command:name',
description: 'Some description',
)]
class CommandName extends Command
{
public function isEnabled(): bool
{
return 'dev' === getenv('APP_ENV');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
if (!$this->isEnabled()) {
$io->error('This command is only available in `dev` environment.');
exit(1);
}
// the rest
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | GusDeCooL |
| Solution 2 | YahyaE |
| Solution 3 | Jan Klan |
