Symfony2 / 3:是否可以刷新单个实体/对象?如果没有,如何在foreach循环后访问持久但未刷新的对象?

时间:2017-02-28 11:28:25

标签: php doctrine-orm symfony

我知道在Doctrine中(作为一般规则)最好在将所有实体/对象持久化到数据库之后刷新(),但在下面的例子中,我认为相反的做法可能是有用的。 例如:

想象一下,你正在循环查看一个像这样的运动结果列表:

playerA_unique_tag (string), playerB_unique_tag (string), result

在数据库中,playerAplayerB是FOREIGN KEYS(指向User实体)。因此,数据库结构与此类似:

Match record
id, playerA_fk, playerB_fk, result

User records
id, playerA_unique_tag, (etc... many other fields)
id, playerB_unique_tag, (etc... many other fields)

脚本示例

$sportResultsArray = array();
foreach($sportResultsArray as $sportResult){
    $playerA_tag = $sportResult["$playerA_unique_tag"];
    $db_playerA = db->getRepository("App:User")->findOneByTag($playerA);
    if(!$db_playerA){
        $db_playerA = new User();
        $db_playerA ->setPlayer_unique_tag($playerA_tag);
        $em->persist($db_playerA );
    }

    $match = new Match();
    $match ->setplayerA($db_playerA );
    /*Same thing would be done for playerB*/
    $em->persist($match );
}

问题:
当然,playerA将播放MULTIPLE匹配,每次我必须以某种方式检索相应的User对象并将其传递给新的Match对象。 但是,如果我还没有刷新playerA User对象,我怎么能这样做呢。

我能想到的唯一两个选择是:
1-创建User实体(仅限User实体)后刷新 2-创建一个临时的对象数组,如下所示:
array('playerA_unique_tag' => playerA_Object, etc.)

option_1的问题:
我已经尝试了$em->flush($db_playerA);,但是持久保存到实体管理器的每个实体也都会被刷新(与此处写的相反:http://www.doctrine-project.org/api/orm/2.5/source-class-Doctrine.ORM.EntityManager.html#338-359)。基本上,结果与$em->flush();

相同

option_2的问题:
这不是一个糟糕而低效的解决方法吗?

1 个答案:

答案 0 :(得分:0)

考虑使用以下内容的玩家内存注册表:

// init registry
$players = [];
foreach ($sportResultsArray as $sportResult) {
    $players[$sportResult["$playerA_unique_tag"]] = null;
    $players[$sportResult["$playerB_unique_tag"]] = null;
}

// fetch all at once
$existing = $db->getRepository("App:User")->findBy(['tag' => array_keys($players)]);

// fill up the registry
foreach ($existing as $player) {
    $players[$player->getTag()] = $player;
}

// match them up
foreach ($sportResultsArray as $sportResult) {
    $playerA_tag = $sportResult["$playerA_unique_tag"];

    if ($players[$playerA_tag] === null) {
        $players[$playerA_tag] = new User();
        $players[$playerA_tag]->setPlayer_unique_tag($playerA_tag);
        $em->persist($players[$playerA_tag]);
    }

    $match = new Match();
    $match->setplayerA($players[$playerA_tag]);
    /*Same thing would be done for playerB*/
    $em->persist($match);
}

// finally 
$em->flush();