自定义发布类型:将术语链接到显示计数

时间:2016-08-02 作者:Stephen

因此,我有一个带有一些自定义分类法的自定义帖子类型。

archive 我列出所有自定义帖子类型的页面我在侧栏中进行了优化搜索,允许您勾选分类术语,然后使用该术语搜索帖子类型。(下图)

Redefine Search

当你点击说“Cellar”时,它会重新加载页面并显示结果(在本例中,它只是一种帖子类型)

我的问题是:我如何更新名字旁边的数字,这样如果勾选了“Cellar”,那么“地毯”旁边的数字应该更新为(1) 因为只有一处房产同时具有“地窖”和“地毯”两个术语

这是控制数字输出的代码,但目前这只是静态的,只是用该术语计算每个帖子类型。

<?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 ) {
            ?>
            <div class="option-bar">
                <input type="checkbox"
                       id="feature-<?php echo $feature->slug; ?>"
                       name="features[]"
                       value="<?php echo $feature->slug; ?>" onclick="document.getElementById(\'refine-properties\').submit();"
                    <?php if ( in_array( $feature->slug, $required_features_slugs ) ) { echo \'checked\'; } ?> />
                <label for="feature-<?php echo $feature->slug; ?>"><?php echo $feature->name; ?> <small>(<?php echo $feature->count; ?>)</small></label>
            </div>
            <?php
        }
        ?>
    </div>
<?php
}
?>
我在下面举了一个例子:

enter image description hereenter image description here

上面的图片代表了我正在尝试做的事情

2 个回复
最合适的回答,由SO网友:Howdy_McGee 整理而成

一种似乎效率低下的方法(但目前我想不出一种不重新查询数据库的方法)是在循环时查询每个术语。您将进行更多的查询,因此我们将限制返回的内容,尝试并加快查询速度。

if ( $features_count > 0 ) {
  ?>

    <div class="more-options-wrapper clearfix">

      <?php foreach ($all_features as $feature ) {
            $count = $feature->count;

            if( ! empty( $required_features_slugs ) ) {
                $tmp_required = $required_features_slugs;

                if( ! in_array( $feature->slug, $required_features_slugs ) ) {
                    array_push( $tmp_required, $feature->slug );
                }

                $tmp_query = new WP_Query( array(
                    \'posts_per_page\'    => -1,
                    \'fields\'            => \'ids\',           // Only return post IDs
                    \'tax_query\'         => array( array(
                        \'taxonomy\'  => \'features\',
                        \'field\'     => \'slug\',
                        \'terms\'     => $tmp_required,
                    ) ),
                ) );

                $count = ( $tmp_query->have_posts() ) ? count( $tmp_query->posts ) : 0;
            }
      ?>

            <div class="option-bar">
                <input type="checkbox"
                       id="feature-<?php echo $feature->slug; ?>"
                       name="features[]"
                       value="<?php echo $feature->slug; ?>" onclick="document.getElementById(\'refine-properties\').submit();"
                    <?php if ( in_array( $feature->slug, $required_features_slugs ) ) { echo \'checked\'; } ?> />
                <label for="feature-<?php echo $feature->slug; ?>"><?php echo $feature->name; ?> <small>(<?php echo $count; ?>)</small></label>
            </div>

      <?php } ?>

    </div>

  <?php
}
我们所做的是,如果选择了一个或多个类别,我们将遍历这些类别并附加当前的slug。然后,我们在数据库中查询包含所需类别和当前类别的帖子。最后,为了提高速度,我们只返回帖子ID——如果我们有帖子,我们会将其计数,否则为0。

SO网友:bosco

理论上,术语关联计数与各自的术语一起静态存储在数据库中。这意味着,仅仅通过检查术语本身,无法确定有多少帖子共享两个或多个术语。

目前我还没有测试或调试这个解决方案,也不确定它是否比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;
?>

相关推荐