I have registed a new rest route to existing database table called wpso_messages. I was able to create a get_callback function that fetches all the data from the database.
I want to add a POST request functionality, that allows me to introduce new data rows to the wpso_messages table through the rest api. Any advise how to accomplish that?
below is my code for registering the rest route and get_callback:
<?php
function get_wp_query() {
global $wpdb;
$rows = $wpdb->get_results("SELECT * FROM wpso_messages");
foreach( $rows as $index => $row ) {
$user_from_id = $rows[$index]->user_from;
$user_to_id = $rows[$index]->user_to;
$rows[$index]->username_from = get_user_by('id', $user_from_id)->display_name;
$rows[$index]->username_to = get_user_by('id', $user_to_id)->display_name;
}
return $rows;
};
add_action( 'rest_api_init', function () {
register_rest_route( 'wp/v2', 'messages', array(
'methods' => 'GET',
'callback' => 'get_wp_query'
) );
} );
For the POST request, below is an example of an input json to create new entry in the wpso_messages table:
{"user_from": "82", "user_to": "1", "message": "Iam interested to bid", "listing_id": "22775"}
Final Solution based on Sally C.J answer: Note that it includes few checks such as that user ids are valid and that the key values in the json body are in the SQL database columns.
#GET request function
function get_wp_query() {
global $wpdb;
$rows = $wpdb->get_results("SELECT * FROM wpso_messages");
foreach( $rows as $index => $row ) {
$user_from_id = $rows[$index]->user_from;
$user_to_id = $rows[$index]->user_to;
$rows[$index]->username_from = get_user_by('id', $user_from_id)->display_name;
$rows[$index]->username_to = get_user_by('id', $user_to_id)->display_name;
$rows[$index]->author= array('Welcome'=>'Home');
}
return $rows;
};
#POST request arguments validation
function my_create_item_args() {
return array(
'user_from' => array(
'required' => true,
'validate_callback' => function ( $param ) {
return is_numeric( $param );
},
),
'user_to' => array(
'required' => true,
'validate_callback' => function ( $param ) {
return is_numeric( $param );
},
),
'message' => array(
'required' => true,
'sanitize_callback' => function ( $param ) {
// this allows basic HTML tags like <strong> and <em>
#return wp_filter_kses( $param );
// this allows line breaks, but strips all HTML tags
return sanitize_textarea_field( $param );
},
),
'listing_id' => array(
'required' => true,
'validate_callback' => function ( $param ) {
return is_numeric( $param );
},
),
''
// ... other args.
);
}
#Post request function
function post_function( WP_REST_Request $request ) {
#getting json body
$body = $request->get_json_params();
#checking if there is an invalid entry otherwise it wont be processed (example unseen)
$valid_entries=["user_from","message","user_to","listing_id","seen"];
foreach( $body as $keysx1=>$valuesx1 ) {
if (in_array($keysx1, $valid_entries, true)) {
} else {
return new WP_Error( 'invalid entry', __($keysx1 . ' is an invalid entry'), array( 'status' => 400 ) );
}
}
#######Checking users
$users = get_users();
foreach( $users as $user ) {
// get user names from the object and add them to the array
$useridlist[] = $user->id;
}
$userfromx1=$body['user_from'];
$usertox1=$body['user_to'];
#Checking sender and reciever are not same
if ($userfromx1!=$usertox1) {
} else {
return new WP_Error( 'invalid message', __('Sender and reciever cant be same'), array( 'status' => 400 ) );
}
#Checking userto and userfrom are in users list
if (in_array($userfromx1, $useridlist, true)) {
} else {
return new WP_Error( 'invalid user id', __('user id specified in user_from is invalid'), array( 'status' => 400 ) );
}
if (in_array($usertox1, $useridlist, true)) {
} else {
return new WP_Error( 'invalid user id', __('user id specified in user_to is invalid'), array( 'status' => 400 ) );
}
global $wpdb;
$body["created_at"] = current_time('mysql');
$wpdb->insert('wpso_messages', $body);
return $body;
}
add_action( 'rest_api_init', function () {
register_rest_route( 'my-plugin/v1', 'messages', array(array(
'methods' => 'GET',
'callback' => 'get_wp_query'
),
array(
'methods' => 'POST',
'callback' => 'post_function',
'args' => my_create_item_args(),
'permission_callback' => function () {
// This is just an example of checking the user's permissions..
return current_user_can( 'edit_posts' );
},)));
});
I have registed a new rest route to existing database table called wpso_messages. I was able to create a get_callback function that fetches all the data from the database.
I want to add a POST request functionality, that allows me to introduce new data rows to the wpso_messages table through the rest api. Any advise how to accomplish that?
below is my code for registering the rest route and get_callback:
<?php
function get_wp_query() {
global $wpdb;
$rows = $wpdb->get_results("SELECT * FROM wpso_messages");
foreach( $rows as $index => $row ) {
$user_from_id = $rows[$index]->user_from;
$user_to_id = $rows[$index]->user_to;
$rows[$index]->username_from = get_user_by('id', $user_from_id)->display_name;
$rows[$index]->username_to = get_user_by('id', $user_to_id)->display_name;
}
return $rows;
};
add_action( 'rest_api_init', function () {
register_rest_route( 'wp/v2', 'messages', array(
'methods' => 'GET',
'callback' => 'get_wp_query'
) );
} );
For the POST request, below is an example of an input json to create new entry in the wpso_messages table:
{"user_from": "82", "user_to": "1", "message": "Iam interested to bid", "listing_id": "22775"}
Final Solution based on Sally C.J answer: Note that it includes few checks such as that user ids are valid and that the key values in the json body are in the SQL database columns.
#GET request function
function get_wp_query() {
global $wpdb;
$rows = $wpdb->get_results("SELECT * FROM wpso_messages");
foreach( $rows as $index => $row ) {
$user_from_id = $rows[$index]->user_from;
$user_to_id = $rows[$index]->user_to;
$rows[$index]->username_from = get_user_by('id', $user_from_id)->display_name;
$rows[$index]->username_to = get_user_by('id', $user_to_id)->display_name;
$rows[$index]->author= array('Welcome'=>'Home');
}
return $rows;
};
#POST request arguments validation
function my_create_item_args() {
return array(
'user_from' => array(
'required' => true,
'validate_callback' => function ( $param ) {
return is_numeric( $param );
},
),
'user_to' => array(
'required' => true,
'validate_callback' => function ( $param ) {
return is_numeric( $param );
},
),
'message' => array(
'required' => true,
'sanitize_callback' => function ( $param ) {
// this allows basic HTML tags like <strong> and <em>
#return wp_filter_kses( $param );
// this allows line breaks, but strips all HTML tags
return sanitize_textarea_field( $param );
},
),
'listing_id' => array(
'required' => true,
'validate_callback' => function ( $param ) {
return is_numeric( $param );
},
),
''
// ... other args.
);
}
#Post request function
function post_function( WP_REST_Request $request ) {
#getting json body
$body = $request->get_json_params();
#checking if there is an invalid entry otherwise it wont be processed (example unseen)
$valid_entries=["user_from","message","user_to","listing_id","seen"];
foreach( $body as $keysx1=>$valuesx1 ) {
if (in_array($keysx1, $valid_entries, true)) {
} else {
return new WP_Error( 'invalid entry', __($keysx1 . ' is an invalid entry'), array( 'status' => 400 ) );
}
}
#######Checking users
$users = get_users();
foreach( $users as $user ) {
// get user names from the object and add them to the array
$useridlist[] = $user->id;
}
$userfromx1=$body['user_from'];
$usertox1=$body['user_to'];
#Checking sender and reciever are not same
if ($userfromx1!=$usertox1) {
} else {
return new WP_Error( 'invalid message', __('Sender and reciever cant be same'), array( 'status' => 400 ) );
}
#Checking userto and userfrom are in users list
if (in_array($userfromx1, $useridlist, true)) {
} else {
return new WP_Error( 'invalid user id', __('user id specified in user_from is invalid'), array( 'status' => 400 ) );
}
if (in_array($usertox1, $useridlist, true)) {
} else {
return new WP_Error( 'invalid user id', __('user id specified in user_to is invalid'), array( 'status' => 400 ) );
}
global $wpdb;
$body["created_at"] = current_time('mysql');
$wpdb->insert('wpso_messages', $body);
return $body;
}
add_action( 'rest_api_init', function () {
register_rest_route( 'my-plugin/v1', 'messages', array(array(
'methods' => 'GET',
'callback' => 'get_wp_query'
),
array(
'methods' => 'POST',
'callback' => 'post_function',
'args' => my_create_item_args(),
'permission_callback' => function () {
// This is just an example of checking the user's permissions..
return current_user_can( 'edit_posts' );
},)));
});
Share
Improve this question
edited Mar 1, 2022 at 18:22
The Oracle
asked Feb 25, 2022 at 21:46
The OracleThe Oracle
971 silver badge12 bronze badges
1 Answer
Reset to default 1I want to add a POST request functionality, that allows me to introduce new data rows to the wpso_messages table through the rest api. Any advise how to accomplish that?
Yes, and note that I wrote this based on the official REST API handbook and the core endpoints.
So from the "Routes and Endpoints → Routes vs Endpoints" section — note the part I highlighted:
A route is the “name” you use to access endpoints, used in the URL. A route can have multiple endpoints associated with it, and which is used depends on the HTTP verb.
Where "HTTP verb" here is essentially a HTTP request method like GET or POST.
So for example, the core /wp/v2/posts
route has 2 endpoints — one with a GET method (for retrieving posts) and the other with a POST method (for creating a post).
Therefore, you could follow the same approach, i.e. add an endpoint to your "messages" route, possibly with the POST method, like so:
// I intentionally used my-plugin as the vendor name, and not "wp". See the
// "Additional Notes" at the bottom in my answer.
register_rest_route( 'my-plugin/v2', 'messages', array(
// Endpoint 1 - list items.
array(
'methods' => 'GET',
'callback' => 'get_wp_query',
// ... other args.
),
// Endpoint 2 - create items.
array(
'methods' => 'POST',
'callback' => 'my_create_item',
// ... other args.
)
) );
function my_create_item( WP_REST_Request $request ) {
// your code here...
}
The actual code that performs the new row/data insertion will depend entirely on you, but you would want to use wpdb::insert()
.
Additional Notes
A route's namespace is composed of
<vendor name>/<version>
, and you should use your own vendor name, e.g.my-plugin
, and notwp
. Somy-plugin/v2
is good, butwp/v2
shouldn't be used.Because the "Routes and Endpoints → Namespaces" section stated:
Do not place anything into the
wp
namespace unless you are making endpoints with the intention of merging them into core.Remember to always set a permission callback for your endpoints.
See "Routes and Endpoints → Permissions Callback" and "Adding Custom Endpoints → Permissions Callback" for more details, but for REST API routes that are intended to be public, one can use
__return_true()
as the permission callback, i.e.'permission_callback'
=>
'__return_true'
.You would also want to register your endpoint arguments using the
args
key, and set a validate and sanitize callback which will validate/sanitize the arguments. E.g.The args for Endpoint 2 above:
// Endpoint 2 - create items. array( 'methods' => 'POST', 'callback' => 'my_create_item', 'permission_callback' => function () { // This is just an example of checking the user's permissions.. return current_user_can( 'edit_posts' ); }, 'args' => my_create_item_args(), )
The
my_create_item_args()
function:function my_create_item_args() { return array( 'user_from' => array( 'required' => true, 'validate_callback' => function ( $param ) { return is_numeric( $param ); }, ), 'message' => array( 'required' => true, 'sanitize_callback' => function ( $param ) { // this allows basic HTML tags like <strong> and <em> return wp_filter_kses( $param ); // this allows line breaks, but strips all HTML tags // return sanitize_textarea_field( $param ); }, ), // ... other args. ); }