WordPress REST API with meta fields

Before starting lets have a complex WordPress query with custom meta fields

Some times ago I created a WordPress plugin for testing purpose and personal use.

What this plugin does is very simple, it adds some custom fields (metaboxes) on each WordPress post where user can choose to make a post a sticky post, with the option to choose and expiration method with two options manual and automatic.

If user will check manual method then he needs to come back to that post and uncheck the option Make this post sticky.

If user will check automatic another option will be visible, where he can check expiration date and time, after the selected time will pass the post will be removed from sticky post.

Plugin functions outputs only one post, because it removes every custom fields added by the plugin from all other posts if a new post is set as sticky. The sticky option used here doesn’t have to do with the build in sticky option used on WordPress.

The WordPress query used to loop through posts was a bit complex because it need to get one post from all posts where the custom field was set for that post to be sticky and the Expiration method was set manual or automatic and if it was set automatic the current time must be greater or equal to the expiration time.

Here is the WordPress query

// Let's build the arguments used on query
$query_arg = array(
  'post_type' => 'post',
  'showposts' => 1,
  'meta_query' => array(
    'relation' => 'AND',
    array(
      'key' => 'my_sticky_post',
      'value' => 'on',
      'compare' => '='
    ),
    array(
      'relation' => 'OR',
      array(
        'key' => 'my_sticky_exp_time',
        'value' => 'manual',
        'compare' => '='
      ),
      array(
        'relation' => 'AND',
        array(
           'key' => 'my_sticky_exp_time',
           'value' => 'automatic',
           'compare' => '='
        ),
        array(
          'key' => 'my_sticky_exp_date_time',
          'value' => current_time( 'mysql' ),
          'compare' => '>='
        ),
      ),
    ),
  ),
);

$query = new WP_Query($query_arg);

Now the query is created, so we have to get what we want by using some WordPress build in functions as below

if ($query->have_posts()) :
  while ($query->have_posts()) : $query->the_post();
  echo '<div>';
  echo '<a href="' .get_permalink(). '" title="'. get_the_title() .'" >'. get_the_title() .'</a> ';
  echo '<div>' . get_the_content() . '</div>';
  echo '</div>';
  endwhile;
endif;
wp_reset_query();

Everything works well.
But for no reason i was searching on StackExchange and found a question where a user was trying to filter multiple custom fields with WordPress REST API 2 and the query was somehow complex as my query. So i though let’s give a try…

WordPress REST API with complex custom fileds

Lets go for a solution of filtering the same query using WordPress REST API v2

With WordPress REST API you may get posts from your website by using many filters including custom taxonomies.

But when it comes to filter posts by using meta fields is not that easy because by default filtering using meta fields is not allowed (for security reasons, if you will use this post to create a similar function on your website used on your own risk).It is not allowed by default but is not that this can’t be achieved by using built in hooks.

The rescue here is rest_query_vars. This hook will allow us to set custom query attributes to the allowed query variables. Here is how to use it:

add_filter( 'rest_query_vars', 'api_allow_meta_query' );
function api_allow_meta_query( $valid_vars ) {

  $valid_vars = array_merge( $valid_vars, array( 'meta_query' ) );

  return $valid_vars;

}

Adding this function on WordPress theme functions.php will allow us to filter the request using the new fields

For this test I created a new php file a putted it on another domain and created the function to get the post from my WordPress website and output it in the new domain.

The function used for retrieving the data from the WordPress site is as below:

/**
* Created by PhpStorm.
* User: emilushi
* Date: 5/25/16
* Time: 1:17 PM
*/

$curl = curl_init();
$dt = new DateTime();
$fields = [
'filter[meta_query]' => [
  'relation' => 'AND',
  [
    'key' => 'my_sticky_post',
    'value' => 'on',
    'compare' => '='
  ],
  [
    'relation' => 'OR',
    [
      'key' => 'my_sticky_exp_time',
      'value' => 'manual',
      'compare' => '='
    ],
    [
      'relation' => 'AND',
      [
        'key' => 'my_sticky_exp_time',
        'value' => 'automatic',
        'compare' => '='
       ],
       [
         'key' => 'my_sticky_exp_date_time',
         'value' => $dt->format('Y-m-d H:i:s'),
         'compare' => '>='
       ],
     ],
   ],
 ],
];

$field_string = http_build_query($fields);

curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_URL => 'http://yourwordpresswebsite.com/wp-json/wp/v2/posts?' . $field_string
  ]
);

$result = curl_exec($curl);

$jsonresult = [];
$jsonresult = var_dump(json_decode($result));

print_r ($jsonresult);

Remember: for everything to work as needed you need to have cURL installed on your server, as well you need to have WP REST API v2 plugin installed on your WordPress website.

Let’s explain what this function does:

First we need to start a cURL session by using curl_init(), then we need to set a variable for the current date and time by using new DateTime() which will be used to compare current time and the expiration time stored on meta filed.

Next step will be creating a variable which holds all the fields that will be used on the REST API filter. After creating the fields we will use, we need to convert them to an encoded query string by using http_build_query

After encoding it the URL will look like this:

http://yourwordpresswebsite.com/wp-json/wp/v2/posts?filter%5Bmeta_query%5D%5Brelation%5D=AND&filter%5Bmeta_query%5D%5B0%5D%5Bkey%5D=my_sticky_post&filter%5Bmeta_query%5D%5B0%5D%5Bvalue%5D=on&filter%5Bmeta_query%5D%5B0%5D%5Bcompare%5D=%3D&filter%5Bmeta_query%5D%5B1%5D%5Brelation%5D=OR&filter%5Bmeta_query%5D%5B1%5D%5B0%5D%5Bkey%5D=my_sticky_exp_time&filter%5Bmeta_query%5D%5B1%5D%5B0%5D%5Bvalue%5D=manual&filter%5Bmeta_query%5D%5B1%5D%5B0%5D%5Bcompare%5D=%3D&filter%5Bmeta_query%5D%5B1%5D%5B1%5D%5Brelation%5D=AND&filter%5Bmeta_query%5D%5B1%5D%5B1%5D%5B0%5D%5Bkey%5D=my_sticky_exp_time&filter%5Bmeta_query%5D%5B1%5D%5B1%5D%5B0%5D%5Bvalue%5D=automatic&filter%5Bmeta_query%5D%5B1%5D%5B1%5D%5B0%5D%5Bcompare%5D=%3D&filter%5Bmeta_query%5D%5B1%5D%5B1%5D%5B1%5D%5Bkey%5D=my_sticky_exp_date_time&filter%5Bmeta_query%5D%5B1%5D%5B1%5D%5B1%5D%5Bvalue%5D=2016-05-25+21%3A29%3A35&filter%5Bmeta_query%5D%5B1%5D%5B1%5D%5B1%5D%5Bcompare%5D=%3E%3D

After encoding our URL we start the transfer by using curl_setopt_array. After setting all the options used on the transfer we execute the cURL session by using curl_exec().

Final step is to decode and print the result by using json_decode(). This will output all the data transferred from the WordPress website using REST API v2.

Now you will have to loop through all the results you have received and show only those you will need and work a bit with HTML and CSS to have a nice view.

I hope you have enjoyed this post and as well hope that this post will help you a bit on what you want to achieve. If you will have any question when following the steps explained on the post please leave a comment and i will try to replay to you on time. Don’t forget to share it. All the bests!

Exit mobile version