2 pre_get_posts 个函数以按自定义字段过滤

2 pre_get_posts functions to filter by custom fields

编辑:查看最后一个(第 3 个)代码片段,它是有效的。

我有一个 "Actions" 页面(一个名为 Actions 的自定义 post 类型的存档),它等同于 "events".

我使用 this tutorial 使用自定义字段过滤它们:ville(城市)、action(动作类型)和日期,效果非常好。

然后我创建了另一个函数来过滤 "date range":过去、未来的操作。它也有效。但是他们"accumulate"。当我 select "Past" 行动和一个城市时,它会显示所有过去的行动 + 所有在城市中发生或将要发生的行动。

所以这两个函数可以工作,但我不知道如何将它们的关系设置为 AND 或使它们一起工作的东西而不是 "accumulating"。

有人可以帮我解决这个问题吗?

谢谢。

按 Type/City/Date 自定义字段过滤的函数:

// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array( 
    'action'  => 'action', 
    'ville'   => 'ville', 
    'date'    => 'date',

);

// action
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);

function my_pre_get_posts( $query ) {

    // bail early if is in admin
    if( is_admin() ) return;

    // bail early if not main query
    // - allows custom code / plugins to continue working
    if( !$query->is_main_query() ) return;

    // get meta query
    $meta_query = $query->get('meta_query');

    // loop over filters
    foreach( $GLOBALS['my_query_filters'] as $key => $name ) {

        // continue if not found in url
        if( empty($_GET[ $name ]) ) {

            continue;

        }

        // get the value for this filter
        // eg: http://www.website.com/events?city=melbourne,sydney
        $value = explode(',', $_GET[ $name ]);


        // append meta query
        $meta_query[] = array(
            'key'       => $name,
            'value'     => $value,
            'compare'   => 'IN',
        );

    } 

    $query->set( 'orderby', array( 'date' => 'DESC' ) );

    // update meta query
    $query->set('meta_query', $meta_query);

    return;

}

?>

Future/Past 操作的函数:

<?php

add_action('pre_get_posts', 'future_past_actions', 10, 1);

function future_past_actions( $query ) {

// bail early if is in admin
    if( is_admin() ) return;

    // bail early if not main query
    // - allows custom code / plugins to continue working
    if( !$query->is_main_query() ) return;

    // get meta query
    $meta_query = $query->get('meta_query');


    if( isset($_GET['range']) ) {

    $range = explode(',', $_GET['range']);

    $meta_query[] = array(
        'key'     => 'range',
        'value'   => $range,
        'compare' => 'IN',
        );


        if( $query->get( 'range' ) == 'future' ) {
             $meta_query[] = array(
             'key' => 'date',
             'value' => date("Ymd"),
             'compare' => '>',
            );
            $meta_query['relation'] = 'OR';
        }

        elseif( $query->get( 'range' ) == 'past' ) {
             $meta_query[] = array(
             'key' => 'date',
             'value' => date("Ymd"),
             'compare' => '<',
            );
            $meta_query['relation'] = 'OR';
        }

        elseif( $query->get( 'range' ) == 'toutes' ) {
           return;
        }

    }

    $query->set( 'meta_key', 'date' );
    $query->set( 'orderby', array( 'date' => 'DESC' ) );
    $query->set('meta_query', $meta_query);

    return;

    }

    ?>

最终合并后的工作代码:

 <?php
// array of filters (field key => field name)
        $GLOBALS['my_query_filters'] = array( 
            'action'    => 'action', 
            'ville'     => 'ville', 
            'date'      => 'date'
        );

add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);

function my_pre_get_posts( $query ) {

    // bail early if is in admin
    if( is_admin() ) return;

    // bail early if not main query
    // - allows custom code / plugins to continue working
    if( !$query->is_main_query() ) return;

    if( ! is_post_type_archive( 'actions' ) ) return;

     // CITY/TYPE/DATE filters
    // loop over filters
    foreach( $GLOBALS['my_query_filters'] as $key => $name ) {

        // continue if not found in url
        if( empty($_GET[ $name ]) ) { continue; }

        // get the value for this filter
        // eg: http://www.website.com/events?city=melbourne,sydney
        $value = explode(',', $_GET[ $name ]);

        // append meta query
        $meta_query[] = array(
            'key'       => $name,
            'value'     => $value,
            'compare'   => 'IN',  
        );
    }

        // FUTURE/PAST/ALL filters
    if( isset($_GET['range']) ) {

    $range = $_GET['range'];

      if($range != "toutes") {

          // Select what kind of compare you need
          if($range == "past") {
            $comparer = '<';
          } else if($range == "future") {
            $comparer = '>=';
          }

        // If you need to filter by date add this to meta_query array
        $meta_query[] = array(
            'key'     => 'date',
            'value'   => date("Ymd"),
            'compare' => $comparer,
            );
          }
       }

    // update meta query
    $query->set('meta_query', $meta_query);

    $query->set( 'meta_key', 'date' );
    $query->set( 'orderby', array( 'date' => 'DESC' ) );
    $query->set('posts_per_page', '20');

}

?>

在这种情况下,我认为最好的解决方案是执行一个操作并检查其中的查询参数,然后决定要执行哪种逻辑。

$query 变量包含您分配的所有参数,因此您的代码可能如下所示:

考虑到对情况的评论进行编辑,您必须在两个元字段之间使用 AND 关系。动作中的代码应如下所示:

add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);

function my_pre_get_posts( $query ) {
  $meta_query = array(
    'relation' => 'AND',
    array(
        'key'     => 'ville',
        'value'   => '$value',
        'compare' => '=',
    )
  );

  // Select what kind of compare you need
  if($range == "past") {
    $compare = ">";
  } else if($range == "future") {
    $compare = "<";
  }
  if($range != "all") {
    // If you need to filter by date add this to meta_query array
    $date_query = array(
        'key'     => 'date',
        'value'   => 'date(\"Ymd\"),',
        'compare' => $compare,
    );
    $meta_query[] = $date_query;
  }
  $query->set( 'orderby', array( 'date' => 'DESC' ) );

  // update meta query
  $query->set('meta_query', $meta_query);
}

因为您现在所做的是多次设置查询参数。 如果您需要更多参数来过滤掉,您可以根据获得的参数类型有条件地将它们添加到 $meta_query 变量中。

我想如果我理解正确的话,这种元查询应该 return 需要结果。