boxybird / boxybird-wp-query-endpoint
Query anything you want from the WordPress database using a single REST API endpoint.
Installs: 7
Dependents: 0
Suggesters: 0
Security: 0
Stars: 27
Watchers: 2
Forks: 1
Open Issues: 0
pkg:composer/boxybird/boxybird-wp-query-endpoint
README
Query anything you want from the WordPress database using a single REST API endpoint.
Simply put, this plugin allows to pass GET params from a url into the WP_Query class as $args
WP_QueryReference: https://developer.wordpress.org/reference/classes/wp_query/
Installation
Clone or Download plugin and run composer install before activating in WordPress Admin.
Usage Examples
PHP
Normally in a WordPress theme or plugin you would create an array of $args and pass them into the WP_Query($args) constructor. Like this:
<?php $args = [ 'post_type' => 'post', 'orderby' => 'title', 'posts_per_page' => 12, 'category__in' => [31, 12, 4], //... any other WP_Query args you want. ]; $query = new WP_Query($args); // loop through results in PHP file.
Using this plugin, you can pass those same args from your front-end Javascript:
Vanilla JS
const url = 'https://your-site.com/wp-json/boxybird/wp-query/v1/args?post_type=post&orderby=title&posts_per_page=12&category__in[]=31&category__in[]=12&category__in[]=4' fetch(url) .then(res => res.json()) .then(data => { console.log(data) })
jQuery
const params = jQuery.param({ post_type: 'post', orderby: 'title', posts_per_page: 12, category__in: [31, 12, 4], //... any other WP_Query args you want. }); jQuery.get(`https:/your-site.com/wp-json/boxybird/wp-query/v1/args?${params}`).done((data) => { console.log(data); });
Hooks
The examples below will use a hypothetical site with a 'movie' post_type.
Formatting the JSON response
Out of the box, WP_Query will return the raw rows from the wp_posts table. Like this:
{
"success": true,
"data": [
{
"ID": 569,
"post_author": "1",
"post_date": "2020-11-23 00:17:16",
"post_date_gmt": "2020-11-23 00:17:16",
"post_content": "An eclectic foursome of aspiring teenage witches get more than they bargained for as they lean into their newfound powers.",
"post_title": "The Craft: Legacy",
"post_excerpt": "",
"post_status": "publish",
"comment_status": "closed",
"ping_status": "closed",
"post_password": "",
"post_name": "the-craft-legacy",
"to_ping": "",
"pinged": "",
"post_modified": "2020-11-23 00:17:16",
"post_modified_gmt": "2020-11-23 00:17:16",
"post_content_filtered": "",
"post_parent": 0,
"guid": "https://wp-query.andrewrhyand.com/movies/the-craft-legacy",
"menu_order": 0,
"post_type": "movie",
"post_mime_type": "",
"comment_count": "0",
"filter": "raw"
},
{
"ID": 567,
"post_author": "1",
"post_date": "2020-11-23 00:17:16",
"...and so on"
}
]
}
The above may be useful in some situations, but more often than not you'll likely want to format the JSON response. This is the filter to do it:
add_filter('boxybird/query/format-response', function (WP_Query $query) { // do something with $query and return. });
Here's an example of how you could use the filter:
add_filter('boxybird/query/format-response', function (WP_Query $query) { // Assign queried 'post_type' $post_type = strtolower($query->query_vars['post_type']); // If it's a 'movie' post_type, format like this: if ($post_type === 'movie') { return array_map(function ($movie) { return [ 'id' => $movie->ID, 'title' => get_the_title($movie->ID), 'description' => get_the_content(null, false, $movie->ID), 'link' => get_the_permalink($movie->ID), 'genres' => array_map(function ($term) { return $term->name; }, get_the_terms($movie->ID, 'genre')), 'details' => array_map(function ($detail) { return $detail[0]; }, get_post_meta($movie->ID)), 'description' => [ 'short' => wp_trim_words(get_the_content(null, false, $movie->ID), 10), 'long' => wp_trim_words(get_the_content(null, false, $movie->ID), 75), ], 'images' => [ 'full' => get_the_post_thumbnail_url($movie->ID, 'full'), 'medium' => get_the_post_thumbnail_url($movie->ID, 'medium'), 'thumbnail' => get_the_post_thumbnail_url($movie->ID, 'thumbnail'), ], ]; }, $query->posts); } // If it's a 'post' post_type, format like this: if ($post_type === 'post') { return array_map(function ($post) { return [ 'id' => $post->ID, 'title' => get_the_title($post->ID), 'content' => get_the_content(null, false, $post->ID), 'link' => get_the_permalink($post->ID), ]; }, $query->posts); } // If it's any other post_type, format like this: return array_map(function ($post) { return [ 'id' => $post->ID, 'title' => get_the_title($post->ID), ]; }, $query->posts); });
Focusing on the 'movie' post_type above, this would be the custom formatted response:
{
"success": true,
"data": [
{
"id": 553,
"title": "Dark Phoenix",
"description": "The X-Men face their most formidable and powerful foe when one of their own, Jean Grey, starts to spiral out of control. During a rescue mission in outer space, Jean is nearly killed when she's hit by a mysterious cosmic force. Once she returns home, this force not only makes her infinitely more powerful, but far more unstable. The X-Men must now band together to save her soul and battle aliens that want to use Grey's new abilities to rule the galaxy.",
"link": "https://wp-query.andrewrhyand.com/movies/dark-phoenix",
"genres": [
"Drama",
"Horror",
"Thriller"
],
"details": {
"budget": "200000000",
"status": "Released",
"tmdb_id": "320288",
"imdb_id": "tt6565702",
"revenue": "252442974",
"runtime": "114",
"tagline": "X-Men Dark Phoenix",
"homepage": "http://darkphoenix.com",
"popularity": "122.285",
"vote_count": "4063",
"vote_average": "61%",
"release_date": "Jun 05, 2019",
"_thumbnail_id": "554"
},
"short_description": {
"short": "The X-Men face their most formidable and powerful foe when…",
"long": "The X-Men face their most formidable and powerful foe when one of their own, Jean Grey, starts to spiral out of control. During a rescue mission in outer space, Jean is nearly killed when she's hit by a mysterious cosmic force. Once she returns home, this force not only makes her infinitely more powerful, but far more unstable. The X-Men must now band together to save her soul and battle aliens that want to use…"
},
"images": {
"full": "https://wp-query.andrewrhyand.com/wp-content/uploads/2020/11/cCTJPelKGLhALq3r51A9uMonxKj.jpg",
"medium": "https://wp-query.andrewrhyand.com/wp-content/uploads/2020/11/cCTJPelKGLhALq3r51A9uMonxKj-200x300.jpg",
"thumbnail": "https://wp-query.andrewrhyand.com/wp-content/uploads/2020/11/cCTJPelKGLhALq3r51A9uMonxKj-150x150.jpg"
}
},
{
"id": 551,
"title": "Enemy Lines",
"description": "In the frozen, war torn landscape of occupied Poland during World War II, a crack team of allied commandos are sent on a deadly mission behind enemy lines to extract a rocket scientist from the hands of the Nazis.",
"...and so on"
}
]
}
Default/Overriding WP_Query Args
Default Args
If you would like to add default WP_Query $args BEFORE the request params are applied, this is the filter to do it.
// Example add_filter('boxybird/query/default-args', function ($args) { $args['posts_per_page'] = 12; return $args; });
Note: The above are defaults only. Meaning, if the incoming request specifies
posts_per_page, it will override theboxybird/query/default-argsfilter defaults.
Override Args
If you would like to modify/remove incoming request params BEFORE running the WP_Query, this is the filter to do it.
// Example. add_filter('boxybird/query/override-args', function ($args) { // Don't allow more than 20 'posts_per_page'. if (isset($args['posts_per_page']) && $args['posts_per_page'] > 20) { $args['posts_per_page'] = 20; } // Always override 'post_status' $args['post_status'] = 'publish'; return $args; });
Note: The above filter can be thought of as a security layer. If you never want an
$argto be passed toWP_Query, do it here!
Permissions Callback
If you would like to protected who has access to the /wp-json/boxybird/wp-query/v1/args endpoint, this is the filter.
// Basic Example. add_filter('boxybird/query/permission', function () { // Only logged in users have access. return is_user_logged_in(); }); // Example taken from the WordPress docs. add_filter('boxybird/query/permission', function () { // Restrict endpoint to only users who have the edit_posts capability. if (!current_user_can('edit_posts')) { return new WP_Error('rest_forbidden', esc_html__('OMG you can not view private data.', 'my-text-domain'), ['status' => 401]); } // This is a black-listing approach. You could alternatively do this via white-listing, by returning false here and changing the permissions check. return true; });
