理论上,术语关联计数与各自的术语一起静态存储在数据库中。这意味着,仅仅通过检查术语本身,无法确定有多少帖子共享两个或多个术语。
目前我还没有测试或调试这个解决方案,也不确定它是否比Howdy\\u McGee的答案更有效,但我发现这个问题很有趣,想看看它把我带到了哪里。
其想法是通过在创建/更新属性时跟踪对每个属性的功能的更改,然后将与该功能相关联的每个属性的ID存储在该功能的术语元数据中,从而减少每次页面加载时进行多次post查询的开销。计算相关特征属性列表相交处的项目,然后得出共享这些特征的属性数。
原则上,我认为这种方法比在每次页面加载时为每个术语运行post查询更有效。但在实践中,我认为在处理大量特性和/或属性集合时,这将更加困难。
可以通过比较post元数据中以前存储的术语与属性的当前术语来跟踪属性相关功能的更改(初步)。检测到更改后,可以更新相关特性的相关要素术语元数据列表:
add_action( \'save_post\', \'wpse233841_update_property_feature_lists\', 10, 2 );
function wpse233841_update_property_feature_lists( $post_id, $post ) {
if ( wp_is_post_revision( $post_id ) )
return;
if( \'property\' !== $post->post_type )
return;
$previous_feature_ids = get_post_meta( $post_id, \'_previous_features\', true );
if( $previous_feature_ids )
$previous_feature_ids = maybe_unserialize( $previous_feature_ids );
else
$previous_feature_ids = [];
$feature_ids = wp_get_object_terms(
$post_id,
\'features\',
[
\'fields\' => \'ids\'
]
);
sort( $feature_ids );
if( $previous_feature_ids == $feature_ids )
return;
$added = array_diff( $feature_ids, $previous_feature_ids );
$removed = array_diff( $previous_feature_ids, $feature_ids );
foreach( $added as $added_feature_id )
wpse233841_feature_add_property( $added_feature_id, $post_id );
foreach( $removed as $removed_feature_id )
wpse233841_feature_remove_property( $removed_feature_id, $post_id );
update_post_meta( $post_id, \'_previous_features\', $feature_ids );
}
function wpse233841_feature_add_property( $feature_id, $property_id ) {
$property_ids = get_term_meta( $feature_id, \'_properties\', true );
if( $property_ids )
$property_ids = maybe_unserialize( $property_ids );
else
$property_ids = [];
$property_ids[] = $property_id;
update_term_meta( $feature_id, \'_properties\', $property_ids );
}
function wpse233841_feature_remove_property( $feature_id, $property_id ) {
$property_ids = get_term_meta( $feature_id, \'_properties\', true );
if( ! $property_ids )
return;
$property_ids = maybe_unserialize( $property_ids );
$property_ids = array_diff( $property_ids, [$property_id] );
update_term_meta( $feature_id, \'_properties\', $property_ids );
}
(我不记得我是否正确处理了元数据-已经有一段时间了)。
现在,每个特性的关联属性列表都可以通过术语元查询而不是查询帖子快速获得。这些列表甚至可以很容易地打包成JSON并发送到浏览器,从而实现即时过滤(减去实际查询相关属性)。属性列表在手,获取具有任何给定特征集的属性列表就变成了与相关阵列相交的问题:
function wpse233841_get_properties_by_features( $feature_slugs ) {
static $feature_properties = [];
if( empty( $feature_properties ) ) {
$all_feature_ids = get_terms([
\'taxonomy\' => \'features\',
\'fields\' => \'id=>slug\',
\'hide_empty\' => false
]);
foreach ($ all_feature_ids as $feature_id => $feature_slug ) {
$property_ids = get_term_meta( $feature_id, \'_properties\', true );
$feature_properties[ $feature_slug ] = maybe_unserialize( $property_ids );
}
}
return call_user_func_array(
\'array_intersect\',
array_intersect_key( $feature_properties, array_flip( $feature_slugs ) )
);
}
function wpse233841_get_feature_property_count( $feature_slug, $filter_features = [] ) {
if( !in_array( $feature_slug, $filter_features ) )
$filter_features[] = $feature_slug;
return count( wpse233841_get_properties_by_features( $feature_slugs ) );
}
然后,在模板中,可以通过调用
wpse233841_get_feature_property_count()
带“a”;“主题”;第一个参数为feature slug,第二个参数为过滤计数的一组特征:
<?php
$all_features = get_terms(\'features\');
/* Features in search query */
$required_features_slugs = array();
if( isset ( $_GET[\'features\'] ) ) {
$required_features_slugs = $_GET[\'features\'];
}
$features_count = count ($all_features);
if($features_count > 0):
?>
<div class="more-options-wrapper clearfix">
<?php
foreach ( $all_features as $feature ) {
$cb_atts = [
\'id\' => \'feature-\' . $feature->slug,
\'name\' => \'features[]\',
\'value\' => $feature->slug,
\'onclick\' => \'document.getElementById(\\\'refine-properties\\\').submit();\'
];
$cb_atts_string = \'\';
foreach( $cb_atts as $key => $value )
$cb_atts_string .= \' \' . $key . \'="\' . $value . \'"\';
if( in_array( $feature->slug, $required_features_slugs ) )
$cb_atts_string .= \' checked \';
?>
<div class="option-bar">
<input type="checkbox" <?= $cb_atts_string ?> />
<label for="<?= $cb_atts[\'id\'] ?>"><?= $feature->name ?> <small>(<?= wpse233841_get_feature_property_count( $feature->slug, $required_features_slugs ) ?>)</small>
</label>
</div>
<?php
}
?>
</div>
<?php
endif;
?>