Reputation: 98
I am trying to pass EntityManagerInterface to Command and it looks like the parent constructor only accepts string or null
#[AsCommand(
name: 'app:cleanDB'
)]
class CleanDBCommand extends Command
{
private $em;
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
parent::__construct($entityManager);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$date = new \DateTime('now');
$repo = $this->em->getRepository(User::class);
$shortUrl = $repo->findBy(['createdAt'=>'<'.$date->format('Y-m-d')]);
$io = new SymfonyStyle($input, $output);
$io->success('You have a new command! Now make it your own! Pass --help to see your options.');
return Command::SUCCESS;
}
}
I get the following error
Symfony\Component\Console\Command\Command::__construct(): Argument #1 ($name) must be of type ?string, Container6Yp8i34\EntityManagerGhostE8260f8 given, called in /.../app/src/Command/CleanDBCommand.php on line 28
I have checked the documentation and I cannot find how to use EntityManagerInterface in command. Any ideas would be helpful.
Figured out the solution: I need to pass the command in the constructor instead of entitymanager to parent constructor like below
parent::__construct($entityManager);
I need to pass the command as follows
parent::__construct('app:cleanDB');
Upvotes: 0
Views: 821
Reputation: 131
Look at the parent class here https://github.com/symfony/console/blob/6.3/Command/Command.php#L114. The constructor takes only one argument and that is $name
which must be strictly string or null. You are trying to pass an EntityManagerInterface object. This will always blow up, no matter what.
Do you need to call the parent constructor with the name anyway? Since you are using the attribute #[AsCommand]
, I suppose you are defining the name of your command here and the Symfony should get it from the Reflection of the attribute. If you remove your parent constructor argument, it should work just fine. Here you can see that in constructor, if you do not pass anything, it will do the static reflection check:
https://github.com/symfony/console/blob/6.3/Command/Command.php#L71
Also, since you are using attributes, you are on new PHP 8, and I suggest to write types of your variables, also using shorter and modern notation and the whole command should look like this.
#[AsCommand(name: 'app:cleanDB')]
class CleanDBCommand extends Command
{
public function __construct(
private EntityManagerInterface $em,
) {
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$date = new \DateTime('now');
$repo = $this->em->getRepository(User::class);
$shortUrl = $repo->findBy(['createdAt'=>'<'.$date->format('Y-m-d')]);
$io = new SymfonyStyle($input, $output);
$io->success('You have a new command! Now make it your own! Pass --help to see your options.');
return Command::SUCCESS;
}
}
If you are not familiar with the way how I wrote the constructor, here you have something to read: https://www.php.net/releases/8.0/en.php#constructor-property-promotion
If you are using PHP 8.1, you can edit the line in the constructor https://www.php.net/releases/8.1/en.php#readonly_properties
private readonly EntityManagerInterface $em,
Upvotes: 2