Php Symfony2/3:是否可以刷新单个实体/对象?如果不是,我如何访问foreach循环后保留但未刷新的对象?
我知道在原则中(作为一般规则),最好在将所有实体/对象持久化到数据库后使用flush(),但在下面的情况下,我认为使用相反的方法可能会很有用。 例如: 想象一下,您正在循环浏览一系列运动成绩,如下所示:Php Symfony2/3:是否可以刷新单个实体/对象?如果不是,我如何访问foreach循环后保留但未刷新的对象?,php,doctrine-orm,symfony,Php,Doctrine Orm,Symfony,我知道在原则中(作为一般规则),最好在将所有实体/对象持久化到数据库后使用flush(),但在下面的情况下,我认为使用相反的方法可能会很有用。 例如: 想象一下,您正在循环浏览一系列运动成绩,如下所示: playerA_unique_tag (string), playerB_unique_tag (string), result Match record id, playerA_fk, playerB_fk, result User records id, playerA_unique_t
playerA_unique_tag (string), playerB_unique_tag (string), result
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)
在数据库中,playerA
和playerB
是外键(指向用户
实体)。因此,数据库结构与此类似:
playerA_unique_tag (string), playerB_unique_tag (string), result
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将播放多个匹配,每次我都必须以某种方式检索相应的
User
对象,并将其传递给新的Match
对象。
但如果我还没有刷新playerAUser
object,我该怎么做呢
我能想到的唯一两种选择是:1-创建
用户
实体后刷新该实体(并且仅刷新用户
实体)2-创建一个临时对象数组,如下所示:
array('playerA\u unique\u tag'=>playerA\u对象等)
选项_1有问题:我试过
$em->flush($db_playerA)
但持久化到实体管理器的每个实体也会被刷新(与此处编写的相反:)。基本上,结果与$em->flush()相同代码>
选项_2有问题:
这不是一个糟糕且低效的解决方法吗?考虑使用内存中的播放器注册表,如下所示:
// 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();
考虑使用内存中的播放器注册表,如下所示:
// 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();
但如果我还没有刷新playerA用户对象,我怎么能做到这一点呢。为什么不呢?你确定需要刷新玩家才能进入比赛$match->setplayerA($db_playerA)代码>?请小心。。。当然,如果刚刚创建了$db_playerA(=如果我正在解析他的第一个匹配项),那么这是可行的,但是如果这是playerA的第二、第三(n)个匹配项,我如何检索我之前创建的$db_playerA对象?我不能每次都创建一个完全新的用户实体,如果玩家是同一个实体,那么就将其移动。无论如何,在每次迭代中命中数据库并不是最有效的方法。事实上,我会在($tags)
调用中在一次调用中获取所有玩家。但是“$tags”应该是一个对象数组,对吗?对不起,如果我没弄好的话。只是我需要检索一个对象,而不仅仅是一个字符串。这很公平。这看起来真的像XY问题。看到我的答案了。但如果我还没有刷新playerA用户对象,我该怎么做呢。为什么不呢?你确定需要刷新玩家才能进入比赛$match->setplayerA($db_playerA)代码>?请小心。。。当然,如果刚刚创建了$db_playerA(=如果我正在解析他的第一个匹配项),那么这是可行的,但是如果这是playerA的第二、第三(n)个匹配项,我如何检索我之前创建的$db_playerA对象?我不能每次都创建一个完全新的用户实体,如果玩家是同一个实体,那么就将其移动。无论如何,在每次迭代中命中数据库并不是最有效的方法。事实上,我会在($tags)
调用中在一次调用中获取所有玩家。但是“$tags”应该是一个对象数组,对吗?对不起,如果我没弄好的话。只是我需要检索一个对象,而不仅仅是一个字符串。这很公平。这看起来真的像XY问题。看看我的答案。太好了!!这是选项2的一个更干净的实现。关键是通过player_标记创建一个用户实体索引数组。干得好,不容易,但你能解决问题。我不知道使用->findBy(['tag'=>array_key($players)]的可能性;伟大的这是选项2的一个更干净的实现。关键是通过player_标记创建一个用户实体索引数组。干得好,不容易,但你能解决问题。我不知道使用->findBy(['tag'=>array_key($players)]的可能性;