Custom post type API custom endpoint for single post by ID - wordpress

I've created a WordPress custom post type, then I've created REST API custom endpoint to GET all the posts works ok. Then I've created another custom endpoint to GET single post by ID. For example http://localhost:8888/wordpress/wp-json/lc/v1/cars/120
I have created a few posts, each time I change the ID at the end of the route to 118 or 116 it shows the same data for the latest post-ID 120. I need the relevant data to show based on the post ID, I would appreciate any kind of help. Thanks
public function rest_posts_endpoints(){
register_rest_route(
'lc/v1',
'/cars/(?P<id>\d+)',
[
'method' => 'GET',
'callback' => [$this, 'rest_endpoint_handler_single'],
]
);
}
public function rest_endpoint_handler_single( WP_REST_Request $request ) {
$params = $request->get_query_params();
$args = [
'post_type' => 'cars',
'id' => $params['id'],
];
$post = get_posts($args);
$data['id'] = $post[0]->ID;
$data['slug'] = $post[0]->post_name;
$data['title'] = $post[0]->post_title;
$data['content'] = $post[0]->post_content;
$data['excerpt'] = $post[0]->post_excerpt;
return $data;
}

public function rest_endpoint_handler_single( WP_REST_Request $request ) {
$params = $request->get_params();
$args = [
'post_type' => 'cars',
'id' => $params['id'],
'include' => array($params['id']),
];
$post = get_posts($args);
$data['id'] = $post[0]->ID;
$data['slug'] = $post[0]->post_name;
$data['title'] = $post[0]->post_title;
$data['content'] = $post[0]->post_content;
$data['excerpt'] = $post[0]->post_excerpt;
return $data;
}

Related

Custom post type REST API custom endpoint for single post by ID

I've created a WordPress custom post type, then I've created REST API custom endpoint to GET all the posts works well. Then I've created another custom endpoint to GET single post by ID. For example http://localhost:8888/wordpress/wp-json/lc/v1/cars/120
I have created a few posts, each time I change the ID at the end of the route to 118 or 116 it shows the same data for the latest post-ID 120. I need the relevant data to show based on the post ID, I would appreciate any kind of help. Thanks
public function rest_posts_endpoints(){
register_rest_route(
'lc/v1',
'/cars/(?P<id>\d+)',
[
'method' => 'GET',
'callback' => [$this, 'rest_endpoint_handler_single'],
]
);
}
public function rest_endpoint_handler_single($id) {
$args = [
'post_type' => 'cars',
'id' => $id['id'],
];
$post = get_posts($args);
$data['id'] = $post[0]->ID;
$data['slug'] = $post[0]->post_name;
$data['title'] = $post[0]->post_title;
$data['content'] = $post[0]->post_content;
$data['excerpt'] = $post[0]->post_excerpt;
return $data;
}
Please use the WP_REST_Request $request to get the params passed.
public function rest_endpoint_handler_single(WP_REST_Request $request) {
$params = $request->get_query_params();
$args = [
'post_type' => 'cars',
'numberposts' => 1,
'include' => array($params['id']),
];
$post = get_posts($args);
$data['id'] = $post[0]->ID;
$data['slug'] = $post[0]->post_name;
$data['title'] = $post[0]->post_title;
$data['content'] = $post[0]->post_content;
$data['excerpt'] = $post[0]->post_excerpt;
return $data;
}

Add links on Wordpress custom endpoint

I created a custom endpoint for specific data from a custom table in my Wordpress plugin. It get's all the data from the table with the getHelpers() function. After that it will be merged by some user data. I would like to add the profile_image as a link to the response so we can get it with the embed parameter.
What is the best way to add the link to the response? I know the $response->add_link() function but this would add it to the response and not to each contributor.
I tried to add the link as an array but this won't react on the _embed parameter.
This is my code for the custom endpoint:
class VEMS_Rest_Contributors extends WP_REST_Controller {
protected $namespace = 'vems/v2';
protected $rest_base = 'contributors';
/**
* Register the routes for coupons.
*/
public function register_routes() {
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'args' => $this->get_collection_params(),
) );
}
public function get_items( WP_REST_Request $request ) {
$project_id = $request->get_param( 'project_id' );
$contributors = array();
if( !empty($project_id) ) {
$project = new VEMS_Project( $request['project_id'] );
$helpers = $project->getHelpers();
foreach($helpers as $helper) {
$contributor = array();
if( !empty($helper->contributor_id) ) {
$user = get_user_by( 'ID', $helper->contributor_id );
$user_meta = get_user_meta( $helper->contributor_id );
$contributor['ID'] = $helper->contributor_id;
$contributor['user_nicename'] = $user->data->display_name;
$contributor['user_profile_image'] = $user_meta['contributor_profile_image'][0];
} else {
$contributor['user_nicename'] = $helper->name;
$contributor['user_profile_image'] = $helper->image_id;
}
$contributor['item_total'] = $helper->item_total;
$contributor['checked'] = $helper->checked;
$contributor['helper_date'] = $helper->helper_date;
/*
$contributor['_links']['profile_image'] = array(
'href' => rest_url( '/wp/v2/media/' . $contributor['user_profile_image'] ),
'embeddable' => true
);
*/
$contributors[] = $contributor;
}
}
$response = rest_ensure_response( $contributors );
return $response;
}
public function get_collection_params() {
$params['project_id'] = array(
'description' => __( 'Limit result set to contributors assigned a specific project.', 'vems' ),
'type' => 'integer',
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
);
return $params;
}
}
to handle links on route vems/v2/contributors?_embed, the element profile_image must be an array of links and then you can do that
$contributor['_links']['profile_image'] = [
[
'href' => rest_url( '/wp/v2/media/' . $contributor['ID'] ),
'embeddable' => true,
],
];

get_posts() does not return featured_image field on Wordpress custom endpoint

Trying to get only the needed data on a custom endpoint in Wordpress. To do so, I am using get_posts() function.
add_action('rest_api_init', function() {
register_rest_route('wl/v1', 'pages', [
'methods' => 'GET',
'callback' => 'wl_page',
]);
});
function wl_page() {
$args = [
'numberposts' => 99999,
'post_type' => 'page',
'post_parent' => 0,
];
$posts = get_posts($args);
$data = [];
$data['ID'] = $posts[0]->ID;
$data['title'] = $posts[0]->post_title;
$data['content'] = $posts[0]->post_content;
$data['featured_image'] = $posts[0]->featured_media;
return $data;
}
It should return the ID of the featured image, but get_posts() doesn't even return that field.
get_posts returns array of Post Objects which don't have featured_media property available. Use get_post_thumbnail_id() instead.
See updated code below:
add_action('rest_api_init', function() {
register_rest_route('wl/v1', 'pages', [
'methods' => 'GET',
'callback' => 'wl_page',
]);
});
function wl_page() {
$args = [
'numberposts' => 99999,
'post_type' => 'page',
'post_parent' => 0,
];
$posts = get_posts($args);
$data = [];
$data['ID'] = $posts[0]->ID;
$data['title'] = $posts[0]->post_title;
$data['content'] = $posts[0]->post_content;
$data['featured_image'] = get_post_thumbnail_id( $posts[0]->ID );
return $data;
}

REST filter based on ACF properties does not work

I have this REST data:
[{"id":215,"acf":{"stad":{"value":"barcelona","label":"barcelona"},"description":"","images":[{"ID":191,"id":191,"title":"logo-black.png","filename":"logo-black.png","filesize":3080,"url":"https:\/\/wordpress-132670-574369.cloudwaysapps.com\/wp-content\/uploads\/logo-black.png","link":"https:\/\/wordpress-132670-574369.cloudwaysapps.com\/logo-black-png\/","alt":"","author":"1","description":"","caption":"","name":"logo-black-png","status":"inherit","uploaded_to":0,"date":"2018-04-16 15:39:37","modified":"2018-08-05 15:19:12","menu_order":0,"mime_type":"image\/png","type":"image","subtype":"png","icon":"https:\/\/wordpress-132670-574369.cloudwaysapps.com\/wp-includes\/images\/media\/default.png","width":443,"height":98,"sizes":{"thumbnail":"https:\/\/wordpress-132670-574369.cloudwaysapps.com\/wp-content\/uploads\/logo-black-150x98.png","thumbnail-width":150,"thumbnail-height":98,"medium":"https:\/\/wordpress-132670-574369.cloudwaysapps.com\/wp-content\/uploads\/logo-black-300x66.png","medium-width":300,"medium-height":66,"medium_large":"https:\/\/wordpress-132670-574369.cloudwaysapps.com\/wp-content\/uploads\/logo-black.png","medium_large-width":443,"medium_large-height":98,"large":"https:\/\/wordpress-132670-574369.cloudwaysapps.com\/wp-content\/uploads\/logo-black.png","large-width":443,"large-height":98}}]}},{"id":205,"acf":{"stad":{"value":"oslo","label":"oslo"},"description":"","images":false,"myid":"333"}}]
I created a filter to query with the "myid" parameter like this:
/wp-json/wp/v2/hotels/?myid=333
This is the filter code I added to the functions.php:
add_filter('rest_hotels_vars', function ($valid_vars)
{
return array_merge($valid_vars, array('myid', 'meta_query'));
});
add_filter('rest_hotels_query', function($args, $request)
{
$myid = $request->get_param('myid');
if (!empty( $myid))
{
$args['meta_query'] = array(
array(
'key' => 'myid',
'value' => $myid,
'compare' => '=',
)
);
}
return $args;
}, 10, 2 );
Hotels is a custom post type.
The query always returns all the rows, the filter has no effect.
What's wrong here?
If you look into the filter closely you will understand the error.
apply_filters( "rest_{$this->post_type}_query", array $args, WP_REST_Request $request );
This is your code:
add_filter('rest_hotels_query', function($args, $request){
$myid = $request->get_param('myid');
if (!empty( $myid))
{
$args['meta_query'] = array(
array(
'key' => 'myid',
'value' => $myid,
'compare' => '=',
)
);
}
return $args;
}, 10, 2 );
Here rest_hotels_query : we need to put post type name please be careful, if your post type name is hotel then filter should be like : "rest_hotel_query"
This is the working code:
add_filter('rest_hotel_query', function($args, $request){
$myid = $request->get_param('myid');
if (!empty( $myid))
{
$args['meta_query'] = array(
array(
'key' => 'myid',
'value' => $myid,
'compare' => '=',
)
);
}
return $args;
}, 10, 2 );
Same case with the collection parameters for the posts controller:
apply_filters( "rest_{$this->post_type}_query", array $args, WP_REST_Request $request );
It should be :
add_filter('rest_hotel_collection_params', function ($valid_vars){
return array_merge($valid_vars, array('myid', 'meta_query'));
});
The rest_query_vars filter no longer exists. Take a look at https://developer.wordpress.org/reference/hooks/rest_this-post_type_collection_params/ and https://developer.wordpress.org/reference/hooks/rest_this-post_type_query/
So replace this
add_filter('rest_hotels_vars', function ($valid_vars)
{
return array_merge($valid_vars, array('myid', 'meta_query'));
});
with this
add_filter('rest_hotels_collection_params', function ($valid_vars)
{
return array_merge($valid_vars, array('myid', 'meta_query'));
});
and it should work.

Wp Rest Api Custom End point POST request

Im trying to post some data to custom api endpoint that i created,
This is what my wordpress custom endpoint code.
register_rest_route( 'api/v1', '/cities', array(
'methods' => 'POST',
'callback' => 'create_city_from_data'
));
And for testing I am trying to return the request like this
function create_city_from_data($req) {
return ['req' => $req];
}
but always i receive empty object as response, whatever i send in payload i didn't receive anything.
My payload is something like this
{ name: 'Hello', population: 565656 }
This is what is received from the request
{"req":{}}
By using below code you can view your payload.
add_action('rest_api_init', function () {
register_rest_route( 'api/v1', '/cities', array(
'methods' => 'POST',
'callback' => 'create_city_from_data'
));
});
function create_city_from_data($req) {
$response['name'] = $req['name'];
$response['population'] = $req['population'];
$res = new WP_REST_Response($response);
$res->set_status(200);
return ['req' => $res];
}
I have used postman to view the POST parameter
By using this function you can see all post of your custom post type in API...
Get All Post in your API Viewer.
Writer URL on your API viewer (e.g. I used Postman json api view, google chrome adon)
Domain-name/wp-json/showFavorites/v2?post_type=hotel
Here 'hotel' is the custom posttype.
Add this function in your functions.php
add_action( 'rest_api_init', 'wp_api_show_favorites_endpoints' );
function wp_api_show_favorites_endpoints() {
register_rest_route( 'showFavorites', '/v2', array(
'methods' => 'GET',
'callback' => 'showFavorites_callback',
));
}
function showFavorites_callback( $request_data ) {
global $wpdb;
$data = array();
$table = 'wp_posts';
$parameters = $request_data->get_params();
$post_type = $parameters['post_type'];
if($post_type!=''){
$re_query = "SELECT * FROM $table where post_type='$post_type'";
$pre_results = $wpdb->get_results($re_query,ARRAY_A);
return $pre_results;
}else{
$data['status']=' false ';
return $data;
}
}
And using this you can post your content from API
// POST All Posts using API
add_action( 'rest_api_init', 'wp_api_add_posts_endpoints' );
function wp_api_add_posts_endpoints() {
register_rest_route( 'addPost', '/v2', array(
'methods' => 'POST',
'callback' => 'addPosts_callback',
));
}
function addPosts_callback( $request_data ) {
global $wpdb;
$data = array();
$table = 'wp_posts';
// Fetching values from API
$parameters = $request_data->get_params();
$user_id = $parameters['user_id'];
$post_type = $parameters['post_type'];
$post_title = $parameters['post_title'];
$the_content = $parameters['the_content'];
$cats = $parameters['cats'];
$the_excerpt = $parameters['the_excerpt'];
$feature_img = $parameters['featured_image'];
// custom meta values
$contact_no = $parameters['contact_no'];
$email = $parameters['email'];
$hotel_url = $parameters['hotel_url'];
if($post_type!='' && $post_title!=''){
// Create post object
$my_post = array(
'post_title' => wp_strip_all_tags( $post_title),
'post_content' => $the_content,
'post_author' => '',
'post_excerpt' => $the_excerpt,
'post_status' => 'publish',
'post_type' => $post_type,
);
$new_post_id = wp_insert_post( $my_post );
function wp_api_encode_acf($data,$post,$context){
$customMeta = (array) get_fields($post['ID']);
$data['meta'] = array_merge($data['meta'], $customMeta );
return $data;
}
if( function_exists('get_fields') ){
add_filter('json_prepare_post', 'wp_api_encode_acf', 10, 3);
}
// Set post categories
$catss = explode(',', $cats);
if (!empty($catss)) {
if ($post_type == 'post') {
wp_set_object_terms( $new_post_id, $catss, 'category', false );
}
else{
wp_set_object_terms( $new_post_id, $catss, 'Categories', false ); // Executes if posttype is other
}
}
// Set Custom Metabox
if ($post_type != 'post') {
update_post_meta($new_post_id, 'contact-no', $contact_no);
update_post_meta($new_post_id, 'email', $email);
update_post_meta($new_post_id, 'hotel-url', $hotel_url);
}
// Set featured Image
$url = $feature_img;
$path = parse_url($url, PHP_URL_PATH);
$filename = basename($path);
$uploaddir = wp_upload_dir();
$uploadfile = $uploaddir['path'] . '/' . $filename;
$contents= file_get_contents($feature_img);
$savefile = fopen($uploadfile, 'w');
chmod($uploadfile, 0777);
fwrite($savefile, $contents);
fclose($savefile);
$wp_filetype = wp_check_filetype(basename($filename), null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => $filename,
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $uploadfile );
if ($attach_id) {
set_post_thumbnail( $new_post_id, $attach_id );
}
if ($new_post_id) {
$data['status']='Post added Successfully.';
}
else{
$data['status']='post failed..';
}
}else{
$data['status']=' Please provide correct post details.';
}
return ($data);
}
The object parameter passed into the callback function is a WP_REST_REQUST object and has a get_body() method on it which returns the payload/post body of the HTTP Post Request.
function create_city_from_data(WP_REST_Request $req) {
$body = $req->get_body()
return ['req' => $body];
}
I learnt about this today whilst reading this article
You can also declare the type of object in the method signature in case you need to search the documentation for it (like i have above).
CURL request :
$url = $your_url; // your url should like: http://host.com/wp-json/v1/'.$key
$post_string = json_encode($post_data);// make json string of post data
$ch = curl_init(); //curl initialisation
curl_setopt($ch, CURLOPT_URL, $url); // add url
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // get return value
curl_setopt($ch, CURLOPT_POST, true); // false for GET request
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string); // add post data
curl_setopt($crl, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($post_string))
);// add header
$output = curl_exec($ch);
curl_close($ch); // close curl
$error = curl_error($ch); // get error
if(!$error){
return json_decode($output);
}else{
return $error;
}
For Handle Request in PLUGIN context :
public static function handle_requests(WP_REST_Request $request){
$return_data = [];
//get GET params
$key = $request['key'];
//get POST values
$post_data = json_decode($request->get_body());
//$return_data = $post_data;
if ( empty( $return_data ) ) {
return new WP_Error( 'error', 'Invalid Request', array( 'status' => 404 ) );
}else{
return $return_data;
}
}
Your WP REST API ACTION :
add_action( 'rest_api_init', function () {
register_rest_route( '/v1', '/(?P<key>[\w]+)', array(
'methods' => ['GET', 'POST'],
'callback' => 'YOUR_CLASS::handle_requests',
'permission_callback' => '__return_true'
) );
} );
//permission_callback need to add for wordpress newer versions.

Resources