Php Symfony2/3:是否可以刷新单个实体/对象?如果不是,我如何访问foreach循环后保留但未刷新的对象?

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

我知道在原则中(作为一般规则),最好在将所有实体/对象持久化到数据库后使用flush(),但在下面的情况下,我认为使用相反的方法可能会很有用。 例如:

想象一下,您正在循环浏览一系列运动成绩,如下所示:

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
对象。 但如果我还没有刷新playerA
User
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)]的可能性;