Search code examples
phpsymfonysymfony4symfony-console

Symfony - Best practice to reset the database


I'm working on a Symfony 4.2 project and I'm looking for the best practice to achieve a reset of the database when the admin needs to do it via a button in backoffice.

Explanation :

The project is a temporary event website. This means that, people will visit the website only for a day / a week and then the website is off. Per example, a website for spectators into a stadium during a basketball tournament.

When the tournament is over, the administrator would like to reset all datas sent during it via a button.

Right now I did it like this but I don't know if it's the better way in production environment.

I created a service which get the KernelInterface in constructor :

public function resetDB() {

    $application = new Application($this->kernel);
    $application->setAutoExit(false);

    $input = new ArrayInput([
        'command'   => 'doctrine:schema:drop',
        '--force' => true
    ]);

    $output = new BufferedOutput();
    $application->run($input, $output);

    $responseDrop = $output->fetch();

    if (strpos($responseDrop, 'successfully') !== false) {
        $input = new ArrayInput([
            'command'   => 'doctrine:schema:create',
        ]);

        $application->run($input, $output);

        $responseCreate = $output->fetch();

        if (strpos($responseCreate, 'successfully') !== false)
            return new Response();
    }

    return new \ErrorException();
}

Firstly, is it good to do it like this in a production environment ? (Nobody else the administrator will use the website when doing this operation)

Secondly, I'm not really satisfied with the method I used to check if the operation has been successfully done (strpos($responseCreate, 'successfully') !== false). Does someone know a better way ?

Thanks a lot for your help


Solution

  • If it works for you, its ok. About the "successful" check part. Simply surround your call in a try-catch block and check for exceptions. If no exception was thrown, assume it did execute successfully.

    $application = new Application($this->kernel);
    $application->setAutoExit(false);
    
    try {
        $application->run(
            new StringInput('doctrine:schema:drop --force'),
            new DummyOutput()
        );
    
        $application->run(
            new StringInput('doctrine:schema:create'),
            new DummyOutput()
        );
    
        return new Response();
    } catch (\Exception $exception) {
        // don't throw exceptions, use proper responses
        // or do whatever you want
    
        return new Response('', Response::HTTP_INTERNAL_SERVER_ERROR);
    }
    

    Is PostgreSQL good enough at DDL transactions? Force a transaction then:

    $application = new Application($this->kernel);
    $application->setAutoExit(false);
    
    // in case of any SQL error
    // an exception will be thrown
    $this->entityManager->transactional(function () use ($application) {
        $application->run(
            new StringInput('doctrine:schema:drop --force'),
            new DummyOutput()
        );
    
        $application->run(
            new StringInput('doctrine:schema:create'),
            new DummyOutput()
        );
    });
    
    return new Response();