我知道在Doctrine中(作为一般规则)最好在将所有实体/对象持久化到数据库之后刷新(),但在下面的例子中,我认为相反的做法可能是有用的。 例如:
想象一下,你正在循环查看一个像这样的运动结果列表:
playerA_unique_tag (string), playerB_unique_tag (string), result
在数据库中,playerA
和playerB
是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的问题:
这不是一个糟糕而低效的解决方法吗?
答案 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();