[英]Best practice for database connection via Doctrine in a Symfony Bundle
[英]Symfony - Best practice to reset the database
我正在开发一个Symfony 4.2项目,当管理员需要通过后台的按钮来实现数据库的重置时,我正在寻找最佳实践。
说明:
该项目是一个临时活动网站。 这意味着,人们将只访问该网站一天/一周,然后该网站关闭。 例如,在篮球比赛期间观众进入体育场的网站。
锦标赛结束后,管理员希望通过按钮重置其中发送的所有数据。
现在我这样做了,但我不知道它是否是生产环境中更好的方式。
我创建了一个服务,它在构造函数中获取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();
我不确定你执行命令的方式,但是使用DoctrineFixturesBundle可以考虑使用单个命令替代。 您需要安装它以便在生产环境中使用(技术上不推荐,我认为是因为删除prod数据的风险,但这就是你想要做的)。
安装:
$ composer require doctrine/doctrine-fixtures-bundle
配置:
// config/bundles.php
return [
...
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['all' => true],
...
];
你需要创建一个fixture ,它必须有一个与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){}
}
命令:
$ php bin/console doctrine:fixtures:load -n --purge-with-truncate --env=prod
救命:
$ php bin/console doctrine:fixtures:load --help
首先,在生产环境中这样做是否很好?
我不这么认为! 例如,下面的命令会警告您: [CAUTION] This operation should not be executed in a production environment!
。 但是,在野外编程世界中一切皆有可能,如下所示。
试试Symfony的The Process Component 。
这是一个基本的例子,因此您可以使它更清晰,无需重复。 我测试过它的确有效。 您也可以流式传输输出。
# 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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.