Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm trying to query for a custom post type for a gallery system. I have a checkbox to set a gallery as a "featured" gallery (set up through More Fields plugin) - if this is checked then the meta value becomes 1 and then if unchecked it becomes 0. All good. However if the box has never been checked then the meta key is never created, meaning I can't query for NOT LIKE 1 because it doesn't exist.

The query I want is to pull out 4 galleries that aren't marked as '1' in this meta value, but also those that don't have this value at all. Is there a way to always give newly added posts a default value for this meta key (ie always make them 0 by default if the box is left unchecked) or is there a way to query for the key not yet being set?

My current query is:

$args = array(
                        'post_type' => 'gallery',
                        'showposts' => 4,
                        'meta_key' => 'gal-ID',
                        'order_by' => 'meta_value',
                        'order' => 'ASC',
                        'meta_query' => array( array(
                                            'key' => 'main-gal',
                                            'value' => false,
                                        ) ),
                        ) );

And I've tried various attempts with 'compare' => 'NOT LIKE', '!=' etc etc.

Any ideas? This ticket seems to imply it's something that ought to be sorted out:

http://core.trac.wordpress.org/ticket/18158

Thanks!

share|improve this question

4 Answers 4

As the ticket pointed out, it's not supported.. until then you'll have to rely on a custom solution.

A few users have asked for this before, or at least asked how to do it over on the WordPress.org forums, so i wrote a function to do the job which i never kept hold of(pastebinned), fortunately i found the original topic where i provided the pastebin link(which shouldn't expire).

http://pastebin.com/kgLt1RrG

I wrote that 8 months ago and i've not tested it(since then), so let me know of any issues.

Hope that helps..

share|improve this answer
    
Cool, thanks for this - will test it out later this evening and let you know what happens. –  artparks Jul 27 '11 at 11:55

The simplest method, albeit not the cleanest:

$args = array(
    'post_type' => 'gallery',
    'posts_per_page' => -1,
    'meta_key' => 'gal-ID',
    'order_by' => 'meta_value',
    'order' => 'ASC',
    'meta_key' => 'main-gal',
    ) );

This will give you all your galleries sorted by the meta key. The next step is to figure out if the galleries with the value 1 come after or before the other posts. This way you can either:

  • Process items until you've processed either 4 gallery items, or reached a post with a meta value of 1
  • Skip over the posts with a meta value 1 then start processing when you reach the first non-1 value

Other methods not requiring a custom SQL statement:

  • Doing a query to find the galleries you dont want, using it to fill an array of post IDs, then doing a second query, passing that array in as posts to exclude
  • Using a taxonomy instead of custom fields ( solves this quite nicely and puts a lot of other nice improvements in free of charge so its saving you time too )
share|improve this answer

As per Custom Field Parameters in Codex, special NOT EXISTS compare is available since WP version 3.5

Technically it produces something like following SQL query in posts requests:

$posts = get_posts( array(
    'meta_query' => array(
        array(
            'key'     => 'wrong',
            'compare' => 'NOT EXISTS',
        ),
    ),
) );
SELECT *,wp_posts.ID
FROM wp_posts
LEFT JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = 'wrong')
WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish') AND (wp_postmeta.post_id IS NULL)
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 5

It works by joining meta table on provided key and only selecting records where that hadn't resulted in meaningful data (IS NULL). So it works only for case when key doesn't exist at all and won't work for keys that exist with falsy values.

share|improve this answer
    
I'm intrigued by this NOT EXISTS compare. As a work around for unset meta keys, I just save a 0 on the save_post hook if the meta key isn't set. How does NOT EXISTS work? Will it sort the OP's query by main-gal and then fill in the 4 with the posts that don't have that meta? –  helgatheviking Jan 10 '13 at 13:35
    
@helgatheviking I've elaborated on mechanics in answer –  Rarst Jan 10 '13 at 21:46
    
thank you for the elaboration! –  helgatheviking Jan 11 '13 at 16:36

That massive function was a bit scary, I got this working like so - with two arguments (that exclude the features)

$args = array(

    'meta_query' => array(
        'relation' => 'OR',
            array( // new and edited posts
                'key' => 'Set as Featured Post',
                'compare' => '!=',
                'value' => 1
            ),

            array( // get old posts w/out custom field
                'key' => 'Set as Featured Post',
                'value' => '1',
                'compare' => 'NOT EXISTS'
            ) 
        ),
    'posts_per_page' => 30

);
share|improve this answer
    
My first array is overriding my second with this solution. It seems maybe you can't double query the same field? –  Allen Gingrich Apr 2 '13 at 19:51

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.