我有一个扩展页面的对象(“Thing”),它与DataObject(“Tag”)有很多关系。
class Thing extends Page
{
static $many_many = array(
'Tags' => 'Tag'
);
}
class Tag extends DataObject
{
static $belongs_many_many = array(
'Things' => 'Thing'
);
}
我有一系列标签ID,我想获得附有所有这些标签的物品清单。
以下应该是可能的......
$tag_ids = array(1,2,3,4);
$things = Thing::get();
$things->filter('Tags.ID', array($tag_ids));
...但这只会返回一个未经过滤的列表。显然,这尚未实现关系。那我怎么能这样做呢?
答案 0 :(得分:3)
我认为如果您使用SilverStripe 3的旧版本,则需要使用ExactMatchMulti SearchFilter。
$tag_ids = array(1,2,3,4);
$things = Thing::get();
$things->filter('Tags.ID:ExactMatchMulti', $tag_ids);
答案 1 :(得分:2)
我没有看到一个简单的解决方案直接用ORM做到这一点。但是你应该能够通过一些循环和过滤来解决这个问题。
$tag_ids = array(1,2,3,4);
$things = Thing::get();
$results = new ArrayList();
$tags_count = count($tag_ids);
$matches = 0;
foreach ($things as $thing)
{
foreach ($thing->Tags() as $tags)
{
$matches = 0;
foreach ($tags as $tag)
{
if ( in_array($tag->ID, $tag_ids) )
{
$matches++;
}
}
if ( $matches === $tags_count )
{
$results->push($thing);
}
}
}
虽然没有经过测试,但这应该会为您留下包含所有标签及其他内容的商品。 (假设一个东西只能用相同的标签标记一次)。
答案 2 :(得分:1)
您可以尝试执行以下操作:
Tag::get()->byIds($tag_ids)->relation('Things')
将返回可以迭代的ManyManyList,即
foreach(Tag::get()->byIds($tag_ids)->relation('Things') as $thing){
Debug::Dump($thing); // A 'Thing' object
}
希望这有帮助
答案 3 :(得分:1)
出于性能原因,您可能最好尽可能多地依赖SQL查询。
$tag_ids = array(1,2,3);
$objects = new ArrayList();
if (count($tag_ids)) {
$sql = "SELECT \"SiteTree\".*, \"Page\".*, \"Thing\".*,count(\"ThingID\") AS ThingIDCount FROM \"SiteTree\" ";
$sql.= "LEFT JOIN \"Page\" ON \"Page\".\"ID\" = \"SiteTree\".\"ID\" ";
$sql.= "LEFT JOIN \"Thing\" ON \"Thing\".\"ID\" = \"SiteTree\".\"ID\" ";
$sql.= "LEFT JOIN \"Thing_Tags\" ON \"Thing_Tags\".\"ThingID\" = \"SiteTree\".\"ID\" ";
$sql.= "LEFT JOIN \"Tag\" ON \"Thing_Tags\".\"TagID\" = \"Tag\".\"ID\" ";
$sql.= "WHERE \"TagID\" IN (" . implode(',', $tag_ids) . ") GROUP BY \"ThingID\" HAVING ThingIDCount >= " . count($tag_ids);
// Get records
$records = DB::query($sql);
foreach($records as $record) {
$objects->push(new Thing($record));
}
}
// Display the Things for demo purposes
foreach($objects as $thing){
Debug::Dump($thing);
}
注意我已经在Thing表中添加了一个左连接,因为我想你上面有一些数据库字段,但是如果不是这种情况则删除该行(以及SELECT语句中的“Thing \”。*)