WordPress:使用meta_query排除帖子 - 并非每个帖子都有meta_field

Cra*_*ray 6 php wordpress custom-fields

我想排除每个具有自定义元字段特定值的帖子。问题是,并不是每个帖子都有这个元字段。

我的代码如下所示(工作循环摘录):

// WP_Query arguments
        $args = array (
            'post_parent'   => $parentid,
            'orderby'       => 'menu_order',
            'order'         => 'ASC',
            'post_type'     => array( 'page' ),
            'meta_query' => array(
                array(
                    'key' => 'hide',
                    'value' => 1,
                    'compare' => '!='
                )
            )
        );
Run Code Online (Sandbox Code Playgroud)

并非每个帖子都使用“隐藏”字段。有些帖子返回 NULL。所以我认为,循环因此不起作用?!

它是否正确?每个帖子都必须有该键的值吗?

bpy*_*bpy 6

另一种方法:

// WP_Query arguments
    $args = array (
    'post_parent'   => $parentid,
    'orderby'       => 'menu_order',
    'order'         => 'ASC',
    'post_type'     => array( 'page' ),
    'meta_query' => array('0' => array('key' => 'hide', 'value' => '1', 'compare' => 'NOT EXISTS')
    )
);
Run Code Online (Sandbox Code Playgroud)


Mat*_*eys 5

这是一篇老帖子了,不过还是来回答一下吧。此问题中的元查询将仅返回具有该元键的帖子的结果。要返回根本没有该元键的帖子,您需要一个额外的元查询。例子:

// WP_Query arguments
$args = array (
    'post_parent'   => $parentid,
    'orderby'       => 'menu_order',
    'order'         => 'ASC',
    'post_type'     => array( 'page' ),
    'meta_query'    => array(
        'relation'  => 'OR',
        array(
            'key'       => 'hide',
            'value'     => 1,
            'compare'   => '!='
        ),
        array(
            'key'       => 'hide',
            'compare'   => 'NOT EXISTS'
        )
    )
);
Run Code Online (Sandbox Code Playgroud)

请注意“关系”的使用以及比较值为“不存在”的第二个元查询。

更新我目前如何处理这种情况:

我似乎越来越多地遇到这样的情况,并且我开发了一种处理它的方法,该方法可以使 SQL 查询更快。每当保存相关帖子类型中的帖子时,我都会更新满足我的查询条件的帖子 ID 列表,并将其存储在 WP 选项中。然后,当我的查询运行时,我会获取此列表,并将其放入“包含”或“排除”查询参数中,具体取决于这是白名单还是黑名单。

这确实添加了一些代码,但这样做的好处不仅在于性能,而且如果您还有其他需要运行的元查询,还可以消除一些复杂性。下面是黑名单的一些示例代码,这也可以适用于白名单。

class Example_Meta_Blacklist
{

    public function init()
    {
        /*
         * Trigger whenever post is saved, you could also trigger on save_post_{$post->post_type}
         * If you are using Advanced Custom Fields, you may need to use acf/save_post
         */
        add_action( 'save_post', [ $this, 'update_my_custom_post_type_blacklist' ] );

        /*
         *  One time use function to create an initial list if needed. Remove if not.
         */
        add_action( 'wp', [ $this, 'create_initial_my_custom_post_type_blacklist' ] );
    }

    /*
     *  Add or remove post ids from our list whenever the post is saved
     */
    public function update_my_custom_post_type_blacklist( $post_id )
    {
        if ( 'my_custom_post_type' != get_post_type( $post_id ) ) {
            return;
        }

        $my_custom_post_type_blacklist  = get_option( 'my_custom_post_type_blacklist', [] );
        $key                            = array_search( $post_id, $my_custom_post_type_blacklist );
        $meta_key_in_question           = get_post_meta( $post_id, 'meta_key_in_question', true );

        if ( ! $meta_key_in_question && $key !== false ) {
            unset( $my_custom_post_type_blacklist[ $key ] );
        } else if ( $meta_key_in_question && $key === false ) {
            $my_custom_post_type_blacklist[] = $post_id;
        }

        update_option( 'my_custom_post_type_blacklist', $my_custom_post_type_blacklist, true );
    }

    /*
     *  When I run into this issue, there are usually already some existing
     *  posts, so I need to run this code one-time to create my initial list
     *  This code would be run by visiting your site with ?gocode=myuniquegocode
     *  at the end of the URL. The function and action hook can then be removed.
     */
    public function create_initial_my_custom_post_type_blacklist()
    {
        if ( ! isset( $_GET['gocode'] ) || 'myuniquegocode' != $_GET['gocode'] ) {
            return;
        }

        $clients = get_posts([
            'posts_per_page'    => -1,
            'post_type'         => 'my_custom_post_type',
            'post_status'       => 'publish',
            'fields'            => 'ids',
            'meta_key'          => 'the_meta_key_in_question',
            'meta_value'        => 'the_meta_value_in_question',
            'meta_compare'      => '='
        ]);

        update_option( 'my_custom_post_type_blacklist', $clients, true );
    }

}

add_action( 'plugins_loaded', [ new Example_Meta_Blacklist, 'init' ] );
Run Code Online (Sandbox Code Playgroud)

然后在帖子查询中:

$my_query = new WP_Query( [
    'post_type'     => 'my_custom_post_type',
    'post_status'   => 'publish',
    'exclude'       => get_option( 'my_custom_post_type_blacklist', [] )
] );
Run Code Online (Sandbox Code Playgroud)


Ven*_*t.R 1

尝试通过执行以下代码片段来检查您的 SQL 语句。

$customPosts = new WP_Query($yourArgs);
echo "Last SQL-Query: {$customPosts->request}";
Run Code Online (Sandbox Code Playgroud)