在PersistentCollection中搜索Symfony4

时间:2019-06-14 14:00:28

标签: symfony

我在Symfony PersistentCollection中苦苦挣扎-在存储库上执行的查询findByOne()的结果集中。我需要根据PersistentCollection中的特定值来查找一个或多个元素,即与另一个与另一个有关系的实体。

我有一个与RuleSet实体有关的SrcFile实体。 在RuleSetRepository上,我调用方法findOneBy(['id' => 1)以找到RuleSet ID = 1。 这将返回具有RuleSet的对象srcFiles: PersistentCollection

现在我需要从该集合中获取特定对象。我知道有一种方法getIterator(),我可以遍历集合中的所有结果,并建立条件来查找文件。kind=='master',但是...

是否有更好的方法使用buildin方法在PersistentCollection中访问/查找/搜索?

//...
// dump of acctual result of 
dump($grsr->findOneBy(['id' => 1)]);

// dumped data (shortened version):
ProfileUController.php on line 118:
RuleSet {#1509 ▼
  -id: 1
  -srcFiles: PersistentCollection {#1507 ▼
    -snapshot: array:5 [ …5]
    -owner: RuleSet {#1509}
    -association: array:15 [ …15]
    -em: EntityManager {#975 …11}
    -backRefFieldName: "ruleset"
    -typeClass: ClassMetadata {#1230 …}
    -isDirty: false
    #collection: ArrayCollection {#1481 ▼
      -elements: array:5 [▼
        0 => SrcFile {#1573 ▶}
        1 => SrcFile {#1734 ▶}
        //...
      ]
    }
    #initialized: true
  }
}

1 个答案:

答案 0 :(得分:0)

您要寻找的是Doctrine Criteria,它使您可以过滤Collection。如果收集对象还没有在内存中,它可以在数据库级别进行筛选足够聪明。

这是一个简单的例子:

$ruleSet = $grsr->findOneBy(['id' => 1]);
$criteria = Criteria::create();
// Criteria to find SrcFiles where kind = 'master'
$criteria->where(Criteria::expr()->eq('kind', 'master');
// return only the srcFiles matching criteria
$ruleSet->srcFiles->matching($criteria);

我更喜欢在我的实体上创建辅助方法,因为我认为它更清洁一些。这取决于您,但是我会在RuleSet实体上做类似的事情:

public function getMasterFiles()
{
    $criteria = Criteria::create();
    $criteria->where(Criteria::expr()->eq('kind', 'master');
    // assuming you have a getter named getSrcFiles for the srcFiles association
    return $this->getSrcFiles()->matching($criteria);
}

然后您可以执行类似的操作(并且不必在每次我们需要主文件时都重复代码):

$ruleSet = $grsr->findOneBy(['id' => 1]);
$ruleSet->getMasterFiles();

更新

如果需要过滤嵌套集合,则必须使用filter方法:

public function getMasterFiles()
{
    return $this->getSrcFiles()->filter(function(SrcFile $srcFile) {
        // if callback returns true, then object is included in result
        return ($srcFile->getKind() === 'master' && $srcFile->getSrcSheet()->getName() === 'MainData');
    });
}

filter方法更灵活,但是始终在从数据库中获取对象之后对对象进行处理。通常这没什么大不了的,但是会影响性能。另一个选项是自定义存储库方法,但我更喜欢在实体上使用辅助方法。对我来说,感觉更像是ORMish。