1

I have created a class with a PHP function I would like to run from the command windows.

Therefore I have created a class extending command but I'm having trouble because I have to call the EntityManagerInterface and the UserPasswordHasherInterface.

If I put them in the constructor and create a new instance, I'm asked to provide the two parameters, which I cannot I guess. So what would be a solution to use those 2 interfaces when I call my method ?

Here my 2 files : TestHashPassword

<?php

namespace App;

use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;

class TestHashPassword
{
    private $entityManager;
    private $passwordHasher;

    public function __construct(EntityManagerInterface $em,UserPasswordHasherInterface $passwordHasherInterface){
        $this->entityManager = $em;
        $this->passwordHasher = $passwordHasherInterface;

        parent::__construct();
    }

    public function hashPassword(){
        $em = $this->entityManager; // will throw an error  "Using $this when not in object context"
        $userAll = $em
            ->getRepository(User::class)
            ->findAll();
        echo("coucou");


        foreach($userAll as $user){
            $comb = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
            $pass = array();
            $combLen = strlen($comb) - 1;
            for ($i = 0; $i < 8; $i++) {
                $n = rand(0, $combLen);
                $pass[] = $comb[$n];
            };
            echo("coucou");
            $user->setDescription($pass);
            $hashedPassword = $this->passwordHasher->hashPassword(
                $user,
                $pass
            );
            $user->setPassword($hashedPassword);
            $this->entityManager->persist($user);
            $this->entityManager->flush();
        }
    }
}

TestHashPasswordCommand.php

<?php

namespace App\Command;

use App\Entity\User;
use App\TestHashPassword;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;

class TestHashPasswordCommand extends Command
{
    protected static $defaultName = 'test-hash-password';
    protected static $defaultDescription = 'Add a short description for your command';

    protected function configure(): void
    {
        $this
            ->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description')
            ->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $arg1 = $input->getArgument('arg1');

        if ($arg1) {
            $io->note(sprintf('You passed an argument: %s', $arg1));
        }

        if ($input->getOption('option1')) {
            // ...
        }

        $io->success('You have a new command! Now make it your own! Pass --help to see your options.');
        $foobar = new TestHashPassword();  // 2 parameters necessary
        $foobar->hashPassword();
//        TestHashPassword::hashPassword(); // will give an error saying I cannot use $this there
        return Command::SUCCESS;
    }
}

And I run in the command CLI : php .\bin\console test-hash-password

2 Answers 2

3

You should be able to use autowiring for your command as well (with default services.yaml configuration).

Instead of creating a new TestHashPassword();, use auto wiring to inject it as a service.

Add in your command a __construct:

use App\TestHashPassword;
class TestHashPasswordCommand extends Command
{
    protected $testHashPassword;
    protected static $defaultName = 'test-hash-password';
    protected static $defaultDescription = 'Add a short description for your command';

    public function __construct(TestHashPassword $testHashPassword)
    {
        $this->testHashPassword = $testHashPassword;
    }
    

And then use it with your initialized variable :

$this->testHashPassword->hashPassword();

PS: Why do you have parent::__construct(); in your service constructor if it does not extend a class ?

Sign up to request clarification or add additional context in comments.

1 Comment

It worked, thank you. I just had an error and I had parent::__constructor() in the new contrucst function you gave. For the other parent::__construct, it was a mistake indeed :)
0

i use a similar structure for my message generator service used in flash messages

<?php

namespace App\Service;
use Psr\Log\LoggerInterface;

class MessageGenerator
{
    public function __construct(private LoggerInterface $logger)

    {
        $this->messages = [
            'well done',
            'keep it up',
        ];
    }


    public function getMessage(): string
    {
        $this->logger->info(' message has been generated!');
        $index = array_rand($this->messages);
        return $this->messages[$index];
    }

}

i also use the following loop to display the flash messages in my base.html.twig:

   {% for message in app.flashes('success') %}
            <div class="alert alert-success">{{ message }}</div>
        {% endfor %}

finally to call the service i use following code in my controller classes:

$message = $messageGenerator->getMessage();
            $this->addFlash('success', $message);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.