Get Posts based on serialized meta value - wordpress

I have a series of posts and all have a meta_key with the value of "owner" and meta_value with serialized data such as "a:3:{i:0;s:3:"325";i:1;s:2:"41";i:2;s:2:"29";}"
meta_key owner
meta_value a:3:{i:0;s:3:"325";i:1;s:2:"41";i:2;s:2:"29";}
I am trying to figure out how to properly use get_posts() to return all the posts that have a meta_key with the value of owner and the meta_value containing a specific value such as 41
$args = array(
'post_type' => 'rp_applications',
'nopaging' => true,
'meta_query' => array(
'relation' => 'AND',
array(
'compare' => '=',
'key' => 'archived',
'value' => '0000-00-00'
),
array(
'compare' => '=',
'key' => 'owner',
'value' => ???? WHAT DO I PUT HERE ????
)
)
);
$applications = get_posts($args);

This sounds like you should be storing the "Owner" as a taxonomy term instead of meta data. It would give you easier and faster querying abilities as well.
That said, it's definitely possible to do what you want. I'd be cautious though, because the postmeta table by default is not indexed, so a large table with meta queries run against it will slow down your site quite a lot. You may want to consider adding a partial index to the table if it's going to be even remotely large (or again, switch to Taxonomy Terms instead of post meta for this).
If you still care to use a meta query, take a look at the compare options available in the WP_Meta_Query() docs.
One of the available options is REGEXP, so you could do something like:
$args = array(
'post_type' => 'rp_applications',
'nopaging' => true,
'meta_query' => array(
'relation' => 'AND',
array(
'compare' => 'REGEXP',
'key' => 'owner',
'value' => sprintf( 'a:\d:{i:0;s:\d:"\d.*?";i:1;s:%d:"%d".*', strlen($owner_id), $owner_id )
),
array(
'compare' => '=',
'key' => 'archived',
'value' => '0000-00-00'
)
)
);
Of course this method only works if the serialized data is in the same format on each one, and you'd need to adjust the regular expression if not - but that should be enough to get you started!

Related

WordPress meta query where key/value does not exist

My custom post type order has a meta key 'status'. A post can have multiple statusses e.g. ordered, paid, completed.
I would like to query all unpaid orders. These don't have a meta key/value pair of status/paid.
I can query all paid orders with ...
array(
'key' => 'status',
'value' => 'paid',
'compare' => '=='
)
... it works
But when I try to query all unpaid orders with ...
array(
'key' => 'status',
'value' => 'paid',
'compare' => '!='
)
... WordPress also returns post which do have the status/paid pair, because they also have the status/ordered pair, which returns true.
Is there a way to fetch posts which don't have a certain meta_key / meta_value pair? Or should I write my own query using wpdb()?
Kind regards,
Tom
meta_query can take in multiple arrays, can you just do:
'meta_query' => array(
array(
'key' => 'status',
'value' => 'paid',
'compare' => '!=',
//'compare' => 'NOT EXISTS', //Perhaps this instead?
),
array(
'key' => 'status',
'value' => 'ordered',
'compare' => '!=',
)
)
Though reading your question it almost sounds like you want results that are status:ordered=true right?

ACF Query Posts by Repeater Field Not Empty

This question seems to be unanswered on the internet, perhaps because it is not possible. I simply want to query all posts where the repeater field 'has rows'. i.e.
$args = array(
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'repeater_field',
'value' => '',
'compare' => '=!'
)
);
I know an alternative is to run if statements inside the loop to filter them out, but that messes with some other logic which is based off of the number of posts in the query.
Does anyone have any thoughts on this?
Let's consider you have a Repeater Field labeled My Repeater Field and this repeater contains at least one field labeled A Field on the Repeater.
Assuming you have the default wp_ table prefix, you need to look at the DB's wp_postmeta table to notice that values for this field on the repeater are stored with the meta_key:
NAME_OF_THE_REPEATER_index_NAME_OF_FIELD_ON_THE_REPEATER
So, in our case, if a post has 3 rows on the repeater field, its values will be stored as:
my_repeater_field_0_a_field_on_the_repeater
my_repeater_field_1_a_field_on_the_repeater
my_repeater_field_2_a_field_on_the_repeater
Knowing this, if you want to query all posts having at least ONE row on the repeater, you could do:
$meta_query = [
[
'key' => 'my_repeater_field_0_a_field_on_the_repeater',
'compare' => 'EXISTS',
]
];
$args = [
'posts_per_page' => -1,
'orderby' => 'date',
'order' => 'DESC',
'meta_query' => $meta_query,
'post_type' => 'post',
'post_status' => 'publish',
];
$posts_array = get_posts( $args );
Note: As stated on WP Docs, you can only use the EXISTS comparison on WP >= 3.5 and you don't need to specify a value when using the 'EXISTS' or 'NOT EXISTS' comparisons in WordPress 3.9 and up. I'm also assuming you are using PHP >= 5.4 so you can use short array syntax. If not, just replace [] for array().
You can query the wordpress database using the $wpdb object. ACF fields are saved in prod_postmeta on the database so that is where you will run your query. Your meta_value will be the key of your repeater field, so make sure you replace that in the query below. All keys for any ACF field with start out with field_ and then random characters/digits will follow like seen below. Then once you have the post id, you can run get_post() on those post ids. Let me know if you need anything else or have questions.
global $wpdb;
$results = $wpdb->get_results("SELECT post_id from prod_postmeta WHERE meta_value = 'field_534eeaaa74199'");
$echo $results;
This works. I have test it. Only by the "Welcome World" post it doesn't work.
$args = array(
'post_type'=> 'post',
'posts_per_page' => -1,
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'repeater_field',
'value' => '0',
'compare' => '!='
)
));
$the_query = new WP_Query( $args );
The "repeater_field" is the name of the field, not the field_key. Here is the count of the rows.

Meta Query compare if meta key is in specified range

Posts have a price custom meta field associated with them. On frontend, there is an option to search a post by specifying a price range, such as all posts that's 'price' value is bigger than 1 AND smaller than 10.
Management decided that we have no option to use WooCommerce for whatever out-of-earth reason, so we have to use native Wordpress for this.
This is what I've managed to do as of now as the arguements of get_posts($args)
$args=array(
'meta_query' => array(
array(
'key' => 'price',
'value' => 1,
'compare' => '>'
)
)
);
But this only returns posts where 'price' is bigger than 1. I need to have posts which's 'price' field is bigger than 1 AND at the same time smaller than 10.
Is this possible?
Try like this:
$args=array(
'meta_query' => array(
array(
'key' => 'price',
'value' => array(1,10),
'compare' => 'BETWEEN'
)
)
);

Wordpress Query on custom fields

My site has woocommerce plugin, so post_type is product. Each product has several custom fields used by another plugin (Compare Products Pro).
Now we would like to query products by URL so eg: www.domain.com/?post_type=product&custom_field=value
Is this possible? And how?
Any help would be highly appriciated!
You could add something like this to your query arguments:
'post_type' => $_GET['post_type'],
'meta_query' => array(
array(
'key' => '_woo_compare_field-',
'value' => $_GET['_woo_compare_field-'],
'compare' => '=',
)
),
But its very static, will not work for different meta key value pairs.
You could assign them to an array and append that array like this
$meta_queries = array(
'relation' => 'AND',
);
foreach($_GET as $key => $value) {
$result = array(
'key' => $key,
'value' => $value,
'compare' => '=',
);
$meta_queries[] = $result;
}
And append the $meta_queries array to the wordpress query arguments.
But this means all your get variables are used as meta key value pairs. You can ofcourse write some logic for this but it will never be pretty

WordPress: one condition for multiple values but one key when querying with custom fields

I am working on some kind of booking extension for a custom post type in Wordpress. The admin can choose the dates when the object is booked. The booked date is saved as a new custom field with the key "booking" and the date in the format "yymmdd". So one object can have multiple custom fields with the same key, but multiple values.
Now I need to query the objects that are available for a specific date. The following is one of my last attempts.
$args = array(
'post_type' => 'object',
'meta_query' => array(
array(
'key' => 'booking',
'value' => array('131020', '131021', '131022'),
'compare' => 'NOT IN'
)
)
);
$query = new WP_Query( $args );
From my logic, I am searching for an object that is available from 131020 to 131022. What WordPress sees to do though is comparing each of the available multiple values individually. So if the element is booked on 131019 and on 131020, WordPress still returns it as available, because 131019 is not in the values above.
What I need is a logic that say "if none of the multiple values is among the mentioned numbers, return the post"
I also tried using just a serialized array for all of the dates, but this didn’t work either. I am sure there might be a simple trick, but after doing a lot of research I am stuck here.
Any ideas?
Thanks
After many other approaches, I finally ended up with the following "solution".
I saved all the dates as an array and was using NOT LIKE for each of the dates that needed to be available. The code from above would look like this:
$args = array(
'post_type' => 'object',
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'booking',
'value' => '131020',
'compare' => 'NOT LIKE'
),
array(
'key' => 'booking',
'value' => '131021',
'compare' => 'NOT IN'
),
array(
'key' => 'booking',
'value' => '131022',
'compare' => 'NOT IN'
)
)
);
$query = new WP_Query( $args );
Note relation => 'AND' at the beginning. As I understand, this is the default, but in case you use 'OR' here this wouldn’t work either.
Still happy about any comment on both of the approaches.

Resources