doctrine - 如何使用 ServiceEntityRepository 刷新实体加载
问题描述
我已经使用 Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository 加载了一个实体(SF4 中的新建议),我想刷新这个实体。
但$entityManager->clear()
不要做这项工作
$entityManager->refresh($myentity)
告诉我
Doctrine\ORM\ORMInvalidArgumentException: Entity App\Entity\MyEntity@0000000068ed8bf0000000007dca9dd1 不受管理。如果实体从数据库中获取或通过 EntityManager#persist 注册为新实体,则该实体被管理
这是我的回购:
<?php
namespace App\Core\Repository;
use App\Core\Entity\Question;
use App\Core\Entity\QuestionnaireResponse;
use App\Core\Entity\Reponse;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
/**
* @method Reponse|null find($id, $lockMode = null, $lockVersion = null)
* @method Reponse|null findOneBy(array $criteria, array $orderBy = null)
* @method Reponse[] findAll()
* @method Reponse[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ReponseRepository extends ServiceEntityRepository
{
/**
* ReponseRepository constructor.
* @param RegistryInterface $registry
*/
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, Reponse::class);
}
}
这是我的 testSetup :
<?php
/*
* Created by Aurelien Jolivard on 24/01/2019.
*/
namespace App\Core\Service;
use Doctrine\Bundle\DoctrineBundle\Command\DropDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\CreateDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\Proxy\CreateSchemaDoctrineCommand;
use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\EntityManager;
use Symfony\Bridge\Doctrine\ContainerAwareEventManager;
use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
class TestSetUp extends WebTestCase
{
/** @var EntityManager $em */
protected $em;
protected $application;
public function beginningTest(String $fixtures){
static::$kernel = static::createKernel(array(
'environment' => 'test',
'debug' => 'true'
));
static::$kernel->boot();
$application = new Application(static::$kernel);
// get the Entity Manager
/** @var EntityManager $em */
$em = static::$kernel->getContainer()
->get('doctrine')
->getManager();
/** @var ContainerAwareEventManager $evm */
$evm = $em->getEventManager();
// drop the database
$command = new DropDatabaseDoctrineCommand(static::$kernel->getContainer()->get('doctrine'));
$application->add($command);
$input = new ArrayInput(array(
'command' => 'doctrine:database:drop',
'--force' => true,
'--env' => 'test'
));
$command->run($input, new NullOutput());
// we have to close the connection after dropping the database so we don't get "No database selected" error
$connection = $application->getKernel()->getContainer()->get('doctrine')->getConnection();
if ($connection->isConnected()) {
$connection->close();
}
// create the database
$command = new CreateDatabaseDoctrineCommand(static::$kernel->getContainer()->get('doctrine'));
$application->add($command);
$input = new ArrayInput(array(
'command' => 'doctrine:database:create',
'--env' => 'test'
));
$command->run($input, new NullOutput());
// create schema
$command = new CreateSchemaDoctrineCommand();
$application->add($command);
$input = new ArrayInput(array(
'command' => 'doctrine:schema:create',
'--env' => 'test'
));
$command->run($input, new NullOutput());
// load fixtures
$client = static::createClient();
$loader = new ContainerAwareLoader($client->getContainer());
$loader->loadFromFile(static::$kernel->getProjectDir().$fixtures);
$purger = new ORMPurger($em);
$executor = new ORMExecutor($em, $purger);
$executor->execute($loader->getFixtures());
$this->em = $em;
$this->application = $application;
return ;
}
}
这是我尝试清除数据的测试。
<?php
namespace App\Core\Tests\Form\FunctionalTest;
use App\Core\Entity\Questionnaire;
use App\Core\Entity\QuestionnaireResponse;
use App\Core\Entity\Reponse;
use App\Core\Service\TestSetUp;
use Doctrine\ORM\EntityManager;
class QuestionTypeBooleanTest extends TestSetUp
{
public function setUp()
{
$array = $this->beginningTest('/src/Core/DataFixtures/AppFixturesQuestionTypeBoolean.php');
//$this->em = $array[0];
//$this->application = $array[1];
}
/**
* @group question
* @group test_BrouillonPuisSoumission
*/
public function test_BrouillonPuisSoumission()
{
// vérification de l'état de la base de données avant
$client = static::createClient(
array('environment' => 'test') ,
);
$questionnaire = $this->em->getRepository(Questionnaire::class)->findSystemAndValue('system', '123');
$crawler = $client->request(
'GET',
'/questionnaire/'.$questionnaire->getId().'/display/1'
);
$response = $client->getResponse();
$this->assertEquals(200, $response->getStatusCode());
$form = $crawler->selectButton('appbundle_questionnaire_display[draft]')->form();
$form['appbundle_questionnaire_display[1]'] = 0;
$form['appbundle_questionnaire_display[2]'] = 1;
$crawler = $client->submit($form);
$response = $client->getResponse();
$this->assertEquals(302, $response->getStatusCode());
// vérification de l'état de la base de données
$reponse1 = $this->em->getRepository(Reponse::class)->find(1);
$reponse2 = $this->em->getRepository(Reponse::class)->find(2);
$questionnaireResponse = $this->em->getRepository(QuestionnaireResponse::class)->find(1);
$this->assertEquals('0', $reponse1->getValeur(), 'cas1.1');
$this->assertEquals('1', $reponse2->getValeur(), 'cas1.2');
$this->assertEquals(2, $questionnaireResponse->getVersionId());
$crawler = $client->request(
'GET',
'/soumission/1/edit'
);
$response = $client->getResponse();
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals(0, $crawler->filter('form[name="appbundle_questionnaire_display"]')->form()->getValues()['appbundle_questionnaire_display[1]'], 'cas2.1');
$this->assertEquals(1, $crawler->filter('form[name="appbundle_questionnaire_display"]')->form()->getValues()['appbundle_questionnaire_display[2]'], 'cas2.2');
$form = $crawler->selectButton('appbundle_questionnaire_display[submit]')->form();
$form['appbundle_questionnaire_display[1]'] = 1;
$form['appbundle_questionnaire_display[2]'] = 0;
$crawler = $client->submit($form);
$response = $client->getResponse();
$this->assertEquals(302, $response->getStatusCode());
$this->em->refresh($reponse1);
$this->em->refresh($reponse2);
$this->em->refresh($questionnaireResponse);
//$this->em->clear();
$this->assertEquals('1', $this->em->getRepository(Reponse::class)->find(1)->getValeur(), 'cas3.1');
$this->assertEquals('0', $this->em->getRepository(Reponse::class)->find(2)->getValeur(), 'cas3.2');
$this->assertEquals(3, $this->em->getRepository(QuestionnaireResponse::class)->find(1)->getVersionId());
}
}
我怎样才能做到这一点 ?
解决方案
我找到了解决方案。
我在 TestSetUp 中获得的 entityManager 不是 ServiceEntityRepository 使用的那个。这是由于 ServiceEntityRepository 的构造造成的。
Si 要清除良好的 entityManager,我必须在 Repository 而不是我的 EntityManger 上调用 clear :
public function test_BrouillonPuisSoumission()
{
// ...
// vérification de l'état de la base de données
$reponseRepository = $this->em->getRepository(Reponse::class);
$questionnaireResponseRepository = $this->em->getRepository(QuestionnaireResponse::class);
$this->em->getRepository(QuestionnaireResponse::class)->find(1)->getVersionId());
$this->assertEquals('0', $reponseRepository->find(1)->getValeur(), 'cas1.1');
$this->assertEquals('1', $reponseRepository->find(2)->getValeur(), 'cas1.2');
$this->assertEquals(2, $questionnaireResponseRepository->find(1)->getVersionId());
// ...
$reponseRepository->clear();
$questionnaireResponseRepository->clear();
$this->assertEquals('1', $reponseRepository->find(1)->getValeur(), 'cas3.1');
$this->assertEquals('0', $reponseRepository->find(2)->getValeur(), 'cas3.2');
$this->assertEquals(3, $questionnaireResponseRepository->find(1)->getVersionId());
}
推荐阅读
- arrays - 在 C 中的另一个函数中迭代数组
- python - 我们如何根据名称连接两列?
- html - 我在我的 squareqpace 站点中添加了一个 CSS 手风琴菜单,但它似乎超出了站点的边缘
- ruby - **args 作为 Ruby 中的函数参数
- java - adb setprop 是否需要重新启动才能进行更改?
- javascript - 将 AMD/requirejs Javascript 文件导入 Typescript
- java - 对流中元素的属性求和
- ffmpeg - FFMPEG 在使用 rtsp-simple-server 降低 FPS 和通过 RTSP 流式传输时保持质量
- regex - 正则表达式 - 在匹配字符串后定位第一个 ')'
- amazon-web-services - AWS Amplify 与 Google 域 DNS