Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Symfony-重置数据库的最佳实践_Php_Symfony_Symfony4_Symfony Console - Fatal编程技术网

Php Symfony-重置数据库的最佳实践

Php Symfony-重置数据库的最佳实践,php,symfony,symfony4,symfony-console,Php,Symfony,Symfony4,Symfony Console,我正在从事一个Symfony 4.2项目,我正在寻找最佳实践,以便在管理员需要通过backoffice中的按钮重置数据库时实现重置 说明: 该项目是一个临时活动网站。 这意味着,人们只会访问网站一天/一周,然后网站关闭。例如,篮球比赛期间观众进入体育场的网站 比赛结束后,管理员希望通过按钮重置比赛期间发送的所有数据 现在我是这样做的,但我不知道这是否是生产环境中更好的方法 我创建了一个在构造函数中获取KernelInterface的服务: public function resetDB() {

我正在从事一个Symfony 4.2项目,我正在寻找最佳实践,以便在管理员需要通过backoffice中的按钮重置数据库时实现重置

说明:

该项目是一个临时活动网站。 这意味着,人们只会访问网站一天/一周,然后网站关闭。例如,篮球比赛期间观众进入体育场的网站

比赛结束后,管理员希望通过按钮重置比赛期间发送的所有数据

现在我是这样做的,但我不知道这是否是生产环境中更好的方法

我创建了一个在构造函数中获取KernelInterface的服务:

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();
}
首先,在生产环境中这样做好吗?(执行此操作时,管理员不会使用网站)

其次,我对用于检查操作是否成功完成的方法并不满意(
strpos($responseCreate,'successfully')!==false
)。有人知道更好的方法吗


非常感谢您的帮助

如果它对您有效,那没关系。关于“成功”检查部分。只需将您的呼叫包围在try-catch块中并检查异常。如果没有引发异常,则假定它确实成功执行

$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);
}
PostgreSQL在DDL事务方面足够好吗?强制交易,然后:

$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();

我不确定你执行命令的方式,但是有一个可以考虑的命令,使用StutixFixtusSu束。您需要安装它以在生产环境中使用(技术上不推荐,我认为是因为删除产品数据的风险,但这正是您想要做的)

安装:

$ composer require doctrine/doctrine-fixtures-bundle
配置:

// config/bundles.php

return [
  ...
  Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['all' => true],
  ...
];
您确实需要并且它必须有一个与Doctrine\Common\DataFixtures\FixtureInterface::load(Doctrine\Common\Persistence\ObjectManager$manager)兼容的
load()
方法,但它可以完全为空,如下所示:

<?php // src/DataFixtures/AppFixtures.php

namespace App\DataFixtures;

use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;

class AppFixtures extends Fixture
{
  public function load(ObjectManager $manager){}
}
帮助:

首先,在生产环境中这样做好吗

我不这么认为例如,下面的命令将警告您:
[注意]此操作不应在生产环境中执行。然而,在野生编程世界中,一切都是可能的,如下所示

试试Symfony的

这是一个基本的例子,所以它是由你使它更干净,无重复。我测试过了,它能工作。您也可以对输出进行流式处理

# DROP IT
$process = new Process(
    ['/absolute/path/to/project/bin/console', 'doctrine:schema:drop', '--force', '--no-interaction']
);
$process->run();
if (!$process->isSuccessful()) {
    throw new ProcessFailedException($process);
}

# RECREATE IT    
$process = new Process(
    ['/absolute/path/to/project/bin/console', 'doctrine:schema:update', '--force', '--no-interaction']
);
$process->run();
if (!$process->isSuccessful()) {
    throw new ProcessFailedException($process);
}

您好@emix,我不知道在我给出的解决方案和对每个表(目前数据库中有15个表)执行TRUNCATE之间有什么更好的解决方案。我有一个postgre数据库,所以比mysql数据库更难截短。你可以坚持使用模式删除和重新创建。我尝试了第二种方法处理事务,但我总是检索HTTP 200。我对drop进行了注释,因此它尝试创建数据库,但它已经创建了。它应该发送一个HTTP 500,但它没有。也许在修改实体并刷新它们时事务性工作,但不使用控制台命令?如果您得到200,则一切工作正常。它不重新创建表格吗?您可以通过在事务匿名函数中抛出异常来模拟错误。最后,我使用了您的第一个示例,但我检查了$application->run的输出,以了解操作是否成功,因为它没有发送任何错误(它返回字符串)<代码>$application->run(新的StringInput('doctrine:schema:drop--force'),$output=new BufferedOutput());如果(strpos($output->fetch(),'successfully')!=false){$application->run(new-StringInput('doctrine:schema:create'),$output=new-BufferedOutput());
$ php bin/console doctrine:fixtures:load --help
# DROP IT
$process = new Process(
    ['/absolute/path/to/project/bin/console', 'doctrine:schema:drop', '--force', '--no-interaction']
);
$process->run();
if (!$process->isSuccessful()) {
    throw new ProcessFailedException($process);
}

# RECREATE IT    
$process = new Process(
    ['/absolute/path/to/project/bin/console', 'doctrine:schema:update', '--force', '--no-interaction']
);
$process->run();
if (!$process->isSuccessful()) {
    throw new ProcessFailedException($process);
}