首页 > 解决方案 > 如何使用 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());
    }
}

我怎样才能做到这一点 ?

标签: doctrinerepositorysymfony4

解决方案


我找到了解决方案。

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

推荐阅读