【问题标题】:How to refresh an entity load with a ServiceEntityRepository如何使用 ServiceEntityRepository 刷新实体加载
【发布时间】:2019-07-05 14:45:26
【问题描述】:

我已经使用 Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository 加载了一个实体(SF4 中的新建议),我想刷新这个实体。

但是$entityManager->clear() 不做这项工作并且

$entityManager->refresh($myentity) 

告诉我

Doctrine\ORM\ORMInvalidArgumentException:实体 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);
        }

    }

这是我的测试设置:

<?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());
    }
}

我该怎么做?

【问题讨论】:

  • 当通过单元测试执行“$client->request”时,我想实体管理器中的“代理实体”可能被清除或覆盖。尝试注释掉$client-&gt;request 看看是否有效。
  • 请求是测试的核心。没有请求,没有数据库更新。所以没有什么要澄清的。我真的认为使用 ServiceEntityRepository 获取的实体不是由这个 em 管理的,而是由 EntityRepository 管理的。

标签: doctrine repository symfony4


【解决方案1】:

我找到了解决办法。

我在 TestSetUp 中获得的 entityManager 不是 ServiceEntityRepository 使用的那个。这是由于 ServiceEntityRepository 的构造造成的。

Si 要清除良好的 entityManager,我必须在 Repository 上调用 clear,而不是在我的 EntityManger 上:

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

【讨论】:

    【解决方案2】:

    Doctrine/ORM/EntityManager::clear()方法

    清除 EntityManager。当前由该 EntityManager 管理的所有实体都将分离。

    Doctrine/ORM/EntityManager::refresh()方法

    刷新数据库中实体的持久状态,覆盖任何尚未持久的本地更改。

    要刷新实体,只需执行以下操作:

    $entityManager->refresh($myentity)
    

    没有 clear() 在它之前,删除它。

    【讨论】:

    • 我同意你的观点,但就我而言,既不清晰也不刷新。我分别尝试并仅使用刷新,我有引用的错误消息。但是,它在我的存储库扩展 Doctrine\ORM\EntityRepository 时有效,但在它扩展 Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository 时无效。但我无法改变它。
    • @MarieP 你能添加你扩展Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository的代码和你使用它的控制器代码吗?
    猜你喜欢
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多