WP pagination in rest api - wordpress

we have made a custom api to get all the post in descending order and we want to add pagination in that api, I have read other questions and answers also but didnt get any idea so can some one explain me with a simple code with pagination so that I can understand how it works.
This is my code so how can I add pagination can anyone explain to me because I searched other questaion also but I didnt get any idea.
define('API_ENDPOINT_VERSION',1);
//flush the rewrite rules on plugin activation
function apiendpoint_activate()
{
flush_rewrite_rules();
}
register_activation_hook(__FILE__,'apiendpoint_activate');
function apiendpoint_register_endpoints(){
register_rest_route(
'api/v1',
'/post',
[
'methods' => 'GET',
'callback' =>'api_get_post',
]
);
}
add_action('rest_api_init','apiendpoint_register_endpoints');
function api_get_post($request){
$ar = array( 'post_type'=>'post',
'posts_per_page'=>15,
'orderby' => 'date',
'order' => 'DESC',
);
$posts = get_posts($ar);
//var_dump($posts);
//exit;
$a = array();
if($posts){
foreach ($posts as $post) {
$a[]= array(
'title'=>$post->post_title,
'link'=>get_the_permalink($post->ID),
'category'=>get_the_category($post->ID),
'published_date'=>get_the_date('l, F j, Y',$post->ID),
'guid'=>$post->guid,
'image'=>get_the_post_thumbnail_url($post->ID,'large'),
'description'=>$post->post_excerpt,
'source'=>"Nepaljapan"
//'img'=>$img
);
}
return $a;
}
}

Try the below code:
define('API_ENDPOINT_VERSION', 1);
//flush the rewrite rules on plugin activation
function apiendpoint_activate() {
flush_rewrite_rules(); } register_activation_hook(__FILE__, 'apiendpoint_activate');
function apiendpoint_register_endpoints() {
register_rest_route(
'api/v1',
'/post',
[
'methods' => 'GET',
'callback' => 'api_get_post',
]
);
} add_action('rest_api_init', 'apiendpoint_register_endpoints');
function api_get_post($request) {
$ar = array('post_type' => 'posts',
'posts_per_page' => 15,
'orderby' => 'date',
'order' => 'DESC',
'paged' => ($_REQUEST['paged'] ? $_REQUEST['paged'] : 1)
);
$posts = get_posts($ar); //var_dump($posts); //exit; $a = array();
if ($posts) {
foreach($posts as $post) {
$a[] = array(
'title' => $post -> post_title,
'link' => get_the_permalink($post -> ID),
'category' => get_the_category($post -> ID),
'published_date' => get_the_date('l, F j, Y', $post -> ID),
'guid' => $post -> guid,
'image' => get_the_post_thumbnail_url($post -> ID, 'large'),
'description' => $post -> post_excerpt,
'source' => "Nepaljapan"
//'img'=>$img
);
}
return $a; }
}
Call API call as below:
/wp-json/api/v1/post?paged=1
Increase the paged value by 1 to get next paging posts.
Hope this helps!

Related

Customize returned object by WP_Query or similiar

I'm trying to query posts, but I'm only interested in certain fields and want to limit the fields that are being returned. In the end I want to return an array of posts with limited fields to pass it to a rest-api endpoint, so I can fetch it in another project.
I managed to query exactly the posts that I want (meta key geo_latitude exists) and pass it to the api endpoint, but the query does return an array of WP_Post objects which don't include the geodata I'm looking for. My big headache is how to customize the return value.
For the return value, I'm trying to achieve this:
Array of queried posts
Each post only contains:
Post Title
Post Link
geo_latitude
geo_longitude
Geodata: https://codex.wordpress.org/Geodata (the values are being copied from the plugin geo mashup)
Working code for querying the posts:
// Query the posts
function get_posts_with_geo( $data ) {
$posts = get_posts( array(
'numberposts' => -1,
'post_type' => 'post',
'meta_query' => [
[
'key' => 'geo_latitude',
'compare' => 'EXISTS',
]
],
) );
if ( empty( $posts ) ) {
return null;
}
return $posts;
}
// Register api endpoint and pass the query post function to it.
add_action( 'rest_api_init', function () {
register_rest_route( 'endpoint', '/posts', array(
'methods' => 'GET',
'callback' => 'get_posts_with_geo',
) );
} );
It returns an array of following wp posts object:
WP_Post Object
(
[ID] =>
[post_author] =>
[post_date] =>
[post_date_gmt] =>
[post_content] =>
[post_title] =>
[post_excerpt] =>
[post_status] =>
[comment_status] =>
[ping_status] =>
[post_password] =>
[post_name] =>
[to_ping] =>
[pinged] =>
[post_modified] =>
[post_modified_gmt] =>
[post_content_filtered] =>
[post_parent] =>
[guid] =>
[menu_order] =>
[post_type] =>
[post_mime_type] =>
[comment_count] =>
[filter] =>
)
Before I tried to use the already available rest-api endpoints, especially /wp-json/wp/v2/posts. We're talking about around 250 posts which have geodata, but over 500 posts overall. Limit per page is 100. I can't query for posts with geodata only in this endpoint, so I would have to receive all posts, loop through pagination and then filter all posts without geodata out. That's pretty wasteful and the reason I'm trying to build my own endpoint which gives me exactly the data that I want.
/edit:
Likely a lot of room of improvement, but working solution so far:
Right before returning the $posts in function get_posts_with_geo, following foreach loop was added:
foreach ( $posts as $key => $post ) {
$posts[ $key ]->title = get_the_title( $post->ID );
$posts[ $key ]->link = get_permalink( $post->ID );
$posts[ $key ]->latitude = get_post_meta( $post->ID, 'geo_latitude', true );
$posts[ $key ]->longitude = get_post_meta( $post->ID, 'geo_longitude', true );
}
It adds the keys to the end of each returned $post, but still returns every other field as well from the WP_Object.
/edit: better solution
I changed the wp query to return only the post ids. From this array of ids, I create a new array with post objects that contains only the fields I want (queried with the post ids). In the end, I return the new array.
function get_posts_with_geo( $data ) {
$posts = get_posts( array(
'numberposts' => -1,
'post_type' => 'post',
'fields' => 'ids',
'meta_query' => [
[
'key' => 'geo_latitude',
'compare' => 'EXISTS',
]
],
) );
// https://codex.wordpress.org/Geodata
if ( empty( $posts ) ) {
return null;
}
$newPosts = [];
$i = 0;
foreach ( $posts as $post ) {
$newPosts[$i] = [
"title" => get_the_title( $post ),
"thumbnail" => get_the_post_thumbnail_url( $post, 'thumbnail' ),
"link" => get_permalink( $post ),
"latitude" => get_post_meta( $post, 'geo_latitude', true ),
"longitude" => get_post_meta( $post, 'geo_longitude', true ),
];
$i++;
}
return $newPosts;
}
// Register the new endpoint and pass the related callback to it.
add_action( 'rest_api_init', function () {
register_rest_route( '(redacted)', '/posts', array(
'methods' => 'GET',
'callback' => 'get_posts_with_geo',
) );
} );
You can use the posts_fields filter to alter what fields get returned.
you need to pass 'suppress_filters => false in the get_posts() arguments in order to get that filter to run.
example :-
function alter_fields_zillion($fields) {
return 'ID,post_title'; // etc
}
add_filter('posts_fields','alter_fields_zillion');
Or you can loop through the posts then add meta_data with the post.
foreach ( $posts as $key => $post ) {
$posts[ $key ]->key1 = get_post_meta( $post->ID, 'key1', true );
$posts[ $key ]->key2 = get_post_meta( $post->ID, 'key2', true );
}
I hope it helps.

Is there any way to get related posts API in WordPress?

I need to create an API that will render a related post by category filter. I have written the code in my functions.php file but I did not get how can I pass a post id to the arguments?
function related_posts_endpoint( $request_data ) {
$uposts = get_posts(
array(
'post_type' => 'post',
'category__in' => wp_get_post_categories(183),
'posts_per_page' => 5,
'post__not_in' => array(183),
) );
return $uposts;
}
add_action( 'rest_api_init', function () {
register_rest_route( 'sections/v1', '/post/related/', array(
'methods' => 'GET',
'callback' => 'related_posts_endpoint'
) );
} );
I need to pass the id from my current API call. So, I need to pass that id to the related API arguments that I have currently passed as static (180)
Image of Current post API from which I need to render a related API
You can add to your rest route a parameter called post_id, and then access the id from the request_data array.
function related_posts_endpoint( $request_data ) {
$post_id = $request_data['post_id'];
$uposts = get_posts(
array(
'post_type' => 'post',
'category__in' => wp_get_post_categories($post_id),
'posts_per_page' => 5,
'post__not_in' => array($post_id),
)
);
return $uposts;
}
add_action( 'rest_api_init', function () {
register_rest_route( 'sections/v1', '/post/related/(?P<post_id>[\d]+)', array(
'methods' => 'GET',
'callback' => 'related_posts_endpoint'
));
});
You can add the id to the end of your URL call /post/related/183.
Your can get the post id like normal get request. ?key=value and use its ad $request['key'] so Your code should be like this.
function related_posts_endpoint( $request_data ) {
$uposts = get_posts(
array(
'post_type' => 'post',
'category__in' => wp_get_post_categories(183),
'posts_per_page' => 5,
'post__not_in' => array($request_data['post_id']),//your requested post id
)
);
return $uposts;
}
add_action( 'rest_api_init', function () {
register_rest_route( 'sections/v1', '/post/related/', array(
'methods' => 'GET',
'callback' => 'related_posts_endpoint'
));
});
Now your api url should be like this /post/related?post_id=183
try this then let me know the result.

Access to all content with specific post type (Wordpress)

I had a question about Wordpress + rest api,
I use register_rest_route for adding new end-point for my collection, and I also created a plugin named as 'article', and the type of this post type also is 'article'.
Now I wanna access all these post types in my new end-point with GET like this :
function my_awesome_func( $post_id ) {
$x = get_post_type_object( 'article' );
return $x[$post_id];
}
add_action( 'rest_api_init', function () {
register_rest_route( 'Articles/v2', '/author/(?P<id>\d+)', array(
'methods' => 'GET',
'callback' => 'my_awesome_func',
) );
} );
I know you can't write $x[$post_id]. I wrote it to say that I wanna access to specific article id. what should I do?
thanks.
I solve this problem finally, I post it, it may be useful for others.
add_action( 'rest_api_init', function () {
register_rest_route( 'wp/v2/Articles', '/author/(?P<id>\d+)', array(
'methods' => 'GET',
'callback' => 'my_awesome_func',
) );
} );
function my_awesome_func( $data ) {
$args = array(
'post_type' => 'article',
'p' => $data['id'],
);
$query = new WP_Query( $args );
return $query->post;
}

acf/validate_value not working on acf 4.4.12

I want my acf field "unique_field" in my custom post type "places" to be unique.
I used acf/validate_value documented here -> https://www.advancedcustomfields.com/resources/acf-validate_value/
https://support.advancedcustomfields.com/forums/topic/solved-check-if-value-already-exist-2/
I tried to put this on my functions.php but it doesn't work.
add_filter('acf/validate_value/name=unique_field', 'validate_unique_field_filter', 10, 4);
function validate_unique_field_filter($valid, $value, $field, $input) {
if (!$valid || $value == '') {
return $valid;
}
// query posts for the same value
global $post;
$args = array(
'post_type' => 'places',
'post__not_in' => array($post->ID),
'meta_query' => array(
array(
'key' => 'unique_field',
'value' => $value
)
)
);
$query = new WP_Query($args);
if (count($query->posts)) {
$valid = 'Place already exist';
}
return $valid;
}
Are there any mistakes? Please Advise. Thank you!
it is missing 'meta_key' => 'unique_field' in the meta_query array
the filter 'acf/validate_value/name=unique_field' should be 'acf/validate_value/key=field_unique_field'

wordpress get posts random from specific categories

Need some help.
I have code in functions.php. when going to myweb.com/random=1 it goes to random post but I want it picks random only from chosen categories. I tried that but it still picks it from all categories.
add_action('init','random_add_rewrite');
function random_add_rewrite() {
global $wp;
$wp->add_query_var('random');
add_rewrite_rule('random/?$', 'index.php?random=1', 'top');
}
add_action('template_redirect','random_template');
function random_template() {
if (get_query_var('random') == 1) {
$posts = get_posts('category=14,17,23,28,32&orderby=rand&numberposts=1');
foreach($posts as $post) {
$link = get_permalink($post);
}
wp_redirect($link,307);
exit;
}
}
Try seeing if this revised one works
add_action('init','random_add_rewrite');
function random_add_rewrite() {
global $wp;
$wp->add_query_var('random');
add_rewrite_rule('random/?$', 'index.php?random=1', 'top');
}
add_action('template_redirect','random_template');
function random_template() {
if (get_query_var('random') == 1) {
$arguments = array('orderby' => 'rand', 'numberposts' => 1, 'category' => '14,17,23,28,32');
$posts = get_posts( $arguments );
foreach($posts as $post) {
$link = get_permalink($post);
}
wp_redirect($link,307);
exit;
}
}
If you query some custom posts, you'll need to do a taxonomy query instead of using category parameter - which refer to the default post type categories.
$args = array(
'numberposts' => 1,
'orderby'=> 'rand',
'tax_query' => array(
array(
'taxonomy' => 'category',
'field' => 'term_id',
'terms' => array(14,17,23,28,32)
)
)
);
$posts = get_post($args);

Resources