I have just started with REST API and using it for creating posts from frontend. I managed to publish post with Title, Excerpt, Content.
I want to add a Custom Meta Field value aswell, any example or help is much appreciated.
This is my Ajax Code, all other fields working fine except meta value is not being added in post
jQuery( document ).ready( function ( $ ) {
$( '#post-submission-form' ).on( 'submit', function(e) {
e.preventDefault();
var title = $( '#post-submission-title' ).val();
var excerpt = $( '#post-submission-excerpt' ).val();
var content = $( '#post-submission-content' ).val();
var status = 'draft';
var data = {
title: title,
excerpt: excerpt,
content: content,
status: status,
meta: {
'video_url_url' : 'abc',
}
};
$.ajax({
method: "POST",
url: POST_SUBMITTER.root + 'wp/v2/posts',
data: data,
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', POST_SUBMITTER.nonce );
},
success : function( response ) {
console.log( response );
alert( POST_SUBMITTER.success );
},
fail : function( response ) {
console.log( response );
alert( POST_SUBMITTER.failure );
}
});
});
} );
Add this to your functions.php :
/**
* Add the meta fields to REST API responses for posts read and write
* Read and write a post meta fields in post responses
*/
function mg_register_meta_api() {
//Meta Fields that should be added to the API
$meta_fields = array(
'video_url_url',
'another_meta_key'
);
//Iterate through all fields and add register each of them to the API
foreach ($meta_fields as $field) {
register_rest_field( 'ring',
$field,
array(
'get_callback' => array( $this, 'mg_fw_get_meta'),
'update_callback' => array( $this, 'mg_fw_update_meta'),
'schema' => null,
)
);
}
}
add_action( 'rest_api_init', 'mg_register_meta_api' );
/**
* Handler for getting custom field data.
*
* #since 0.1.0
*
* #param array $object The object from the response
* #param string $field_name Name of field
*
* #return mixed
*/
function mg_get_meta( $object, $field_name ) {
return get_post_meta( $object[ 'id' ], $field_name );
}
/**
* Handler for updating custom field data.
*
* #since 0.1.0
* #link http://manual.unyson.io/en/latest/helpers/php.html#database
* #param mixed $value The value of the field
* #param object $object The object from the response
* #param string $field_name Name of field
*
* #return bool|int
*/
function mg_update_meta( $value, $object, $field_name ) {
if ( ! $value || ! is_string( $value ) ) {
return;
}
return update_post_meta( $object->ID, $field_name, maybe_serialize( strip_tags( $value ) ) );
}
Now you should be able to read and write for meta 'video_url_url' using the api.
I was playing around with this today and came up with the following solution that works well and adds multiple fields.
Hope this helps anyone who may be stuck on this.
add_action( 'rest_api_init', 'foo_register_meta_api' );
function foo_register_meta_api() {
// Meta Fields to add to the API
$meta_fields = array(
'field_1',
'foo_bar',
'foobar',
'another_field'
);
// Loop all fields and register each of them to the API
foreach ($meta_fields as $field) {
register_rest_field( 'my-post-type',
$field,
array(
'get_callback' => function ($params) use ($field) {
return \get_post_meta($params['id'], $field);
},
'update_callback' => function ($value, $object, $fieldName){
return \update_post_meta($object->ID, $fieldName, $value);
},
'schema' => null
)
);
}
}
I am trying to save phy_marks in post type candidates. What I've got is creating the post but not saving phy_marks.
My JSON data:
{ "title": "Why not working finally","content": "Test", "status": "publish" ,"post_type": "candidates", "meta": {
"phy_marks": 66 } }
My Code:
add_action( 'rest_api_init', 'foo_register_meta_api' );
function foo_register_meta_api() {
// Meta Fields to add to the API
$meta_fields = array(
'phy_marks'
);
// Loop all fields and register each of them to the API
foreach ($meta_fields as $field) {
register_rest_field( 'candidates',
$field,
array(
'get_callback' => function ($params) use ($field) {
return \get_post_meta($params['id'], $field);
},
'update_callback' => function ($value, $object, $fieldName){
return \update_post_meta($object->ID, $fieldName, $value);
},
'schema' => null
)
);
}
}
Related
I have my own function fsww_i_add_funds_request_daily that I wrote to perform the addition of a profit by a user based on the role of the user. This function was created / added for one plugin that I use. I am not sending any parameters to the function. I need to call this function using the submit button which will be on the admin toolbar. The function should be implemented in the plugin as it is necessary to use its "library" (maybe I spoke badly, I'm still a beginner in WP). How and where I need these functions implement?
Function
function fsww_i_add_funds_request_daily() {
require_once(dirname(__FILE__) . '/Wallet.php');
global $wpdb;
$query = $wpdb->get_results("SELECT user_id FROM {$wpdb->prefix}fswcwallet ORDER BY user_id ASC");
if($query) {
foreach($query as $user)
{
$user_id = $user->user_id;
$dailyProvision = 0;
if($user_id != 0)
{
$balance = fsww_price(Wallet::get_balance($user_id));
$last_deposit = fswcw_format_date(Wallet::get_last_deposit($user_id));
$status = Wallet::get_status($user_id);
$username = get_user_by('id', $user_id);
}
}
}
}
function fb_add_admin_bar_profit() {
global $wp_admin_bar;
$current_object = get_queried_object();
$wp_admin_bar->add_menu(
array( 'id' => 'addprofit',
'title' => __('Add profit'),
'href' => ?????)
);
}
add_action( 'admin_bar_menu', 'fb_add_admin_bar_profit');
Could you please help me with this?
Create plugin Custom Plugin and add the below code to that plugin. and in you admin bar custom button add URL like this home_url( '/?funds_request_daily=true' ) and check this query string funds_request_daily params on init hook.
<?php
/**
* Plugin Name: Custom Plugin
* Plugin URI: https://example.com/plugins/the-basics/
* Description: Handle the basics with this plugin.
* Version: 1.0.0
* Author: Cleemas
* Author URI: https://author.example.com/
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: my-custom-plugin
* Domain Path: /languages
*/
function fsww_i_add_funds_request_daily() {
if( isset( $_GET['funds_request_daily'] ) && $_GET['funds_request_daily'] == 'true' ){
require_once(dirname(__FILE__) . '/Wallet.php');
global $wpdb;
$query = $wpdb->get_results("SELECT user_id FROM {$wpdb->prefix}fswcwallet ORDER BY user_id ASC");
if( $query ) {
foreach( $query as $user ) {
$user_id = $user->user_id;
$dailyProvision = 0;
if($user_id != 0) {
$balance = fsww_price(Wallet::get_balance($user_id));
$last_deposit = fswcw_format_date(Wallet::get_last_deposit($user_id));
$status = Wallet::get_status($user_id);
$username = get_user_by('id', $user_id);
}
}
}
}
}
add_action( 'init', 'fsww_i_add_funds_request_daily', 10, 1 );
function fb_add_admin_bar_profit() {
global $wp_admin_bar;
$current_object = get_queried_object();
$wp_admin_bar->add_menu(
array(
'id' => 'addprofit',
'title' => __('Add profit'),
'href' => home_url( '/?funds_request_daily=true' )
)
);
}
add_action( 'admin_bar_menu', 'fb_add_admin_bar_profit');
?>
My category url contains both id and slug like https://myapp.com/category/56-category-name (id field = 56 and slug field = category-name in the DB), when updating category name the slug field in DB is updated but the id still the same.
I would like to display my category whatever the slug provided that the id is correct and of course display the correct url. In this case SEO still correct i think.
Here my show method :
/**
* #Route("/category/{id}-{slug}", name="category_show", requirements={"id"="\d+"})
*/
public function show(CategoryRepository $categoryRepository, $slug, $id): Response
{
$category = $categoryRepository->find($id);
if($category->getSlug() !== $slug) {
return $this->redirectToRoute('category_show', [
'id' => $id,
'slug' => $category->getSlug()
]);
}
return $this->render('category/show.html.twig', [
'category' => $category
]);
}
It works if the given id exists in DB, othewise i got an error Call to a member function getSlug() on null. I can throw a NotFoundException, but i think this method use many times queries.
So please help me doing these properly with more flexibility and performance.
In case I would like to display the category in the post url as well like https://myapp.com/56-category-name/23-post-title how to go about it ??
Thanks in advance
Use findOneBy() and check if the result is null
/**
* #Route("/category/{id}-{slug}", name="category_show", requirements={"id"="\d+"})
* #Route("/{id}-{slug}/{idArticle}-{postSlug}", name="article_show", requirements={"idArticle"="\d+"})
*/
public function show(CategoryRepository $categoryRepository, $slug, $id, $idArticle = false, $postSlug = false ): Response
{
$category = $categoryRepository->findOneBy(['id'=>$id]);
if(is_null($category)){
throw new NotFoundHttpException(); //404, nothing found
}else{
//Category found.
if($idArticle){ // https://myapp.com/56-category-name/23-post-title
//Article route, put your logic here
}else{ //https://myapp.com/category/56-category-name
// Category route, logic here
if($category->getSlug() !== $slug) {
return $this->redirectToRoute('category_show', [
'id' => $id,
'slug' => $category->getSlug()
]);
}
return $this->render('category/show.html.twig', [
'category' => $category
]);
}
}
}
here is what i found good for my app :
in my CategoryController.php i create, the show method :
/**
* #Route("/{id}-{slug}", name="category_show", requirements={"id"="\d+"})
*/
public function show(CategoryRepository $categoryRepository, $slug = null, $id): Response
{
$category = $categoryRepository->find($id);
if (!$category) {
throw new NotFoundHttpException();
}
if($category->getSlug() !== $slug) {
return $this->redirectToRoute('category_show', [
'id' => $id,
'slug' => $category->getSlug()
]);
}
return $this->render('category/show.html.twig', [
'category' => $category
]);
}
in my index template to display the category_show link :
show
in my ArticleController.php i create, the show method :
/**
* #Route("/{category}/{id}-{slug}", name="article_show", requirements={"id"="\d+"})
*/
public function show(ArticleRepository $articleRepository, $slug = null, $id, $category = null): Response
{
$article = $articleRepository->find($id);
if (!$article) {
throw new NotFoundHttpException();
}
$cat = $article->getCategory()->getId() . '-' . $article->getCategory()->getSlug();
if($article->getSlug() !== $slug || $cat !== $category) {
return $this->redirectToRoute('article_show', [
'id' => $id,
'slug' => $article->getSlug(),
'category' => $cat
]);
}
return $this->render('article/show.html.twig', [
'article' => $article,
]);
}
in my index template to display the article_show link :
show
For me that solves my problem. But still, if we can improve the process, I'm a buyer.
Thanks
I have a custom post type and on the admin edit post screen I'm using wp.media to attach the track to the post. And I'm attaching some post meta to that track also.
Is there easy way to force wp.media JS returns track with meta data?
trackMediaUploader = wp.media.frames.file_frame = wp.media( { ... } );
trackMediaUploader.on( 'select', () => {
const attachment = trackMediaUploader.state().get( 'selection' ).first().toJSON();
// want to get post meta of this attachment
console.log( attachment );
});
I've tried to use wp_get_attachment_metadata filter, but it's wont works with wp.media js:
function add_attachment_metadata( $data, $id ) {
$lyrics = get_post_meta( $id, '_track_lyrics', true );
if( $lyrics ) {
$data[ 'track-lyrics' ] = $lyrics;
}
return $data;
}
You can use wp_prepare_attachment_for_js hook:
add_filter( 'wp_prepare_attachment_for_js', 'prepare_attachment_for_js', 10, 3 );
function prepare_attachment_for_js( $response, $attachment, $meta ) {
$response[ 'trackLyrics' ] = get_post_meta( $attachment->ID, '_track_lyrics', true );
return $response;
}
// in admin js:
trackMediaUploader = wp.media.frames.file_frame = wp.media( { ... } );
trackMediaUploader.on( 'select', () => {
const attachment = trackMediaUploader.state().get( 'selection' ).first().toJSON();
console.log( attachment.trackLyrics );
});
I have been trying to pass a meta array to a post via front-end using WP-REST API but to no avail.
functions.php:
//Add custom field to REST API
function filter_post_json( $data, $post, $context ) {
$social_media = get_post_custom_values( 'social_media' );
$sm = [];
if($social_media):
foreach ( $social_media as $key => $value ) {
$sm[] = $value;
}
endif;
$data->data['social_media'] = $sm;
return $data;
}
add_filter( 'rest_prepare_custom-post-type', 'filter_post_json', 10, 3 );
add_action('rest_api_init', 'register_custom_meta');
function register_custom_meta() {
$post_custom_fields = array(
'social_media'
);
foreach ($post_custom_fields as $key) {
register_rest_field('custom-post-type', $key, array(
'schema' => null,
'get_callback' => 'get_meta_field',
'update_callback' => 'update_meta_field',
));
}
}
/**
* Handler for getting custom field data.
*
* #since 0.1.0
*
* #param array $object The object from the response
* #param string $field_name Name of field
* #param WP_REST_Request $request Current request
*
* #return mixed
*/
function get_meta_field( $object, $field_name, $request ) {
return get_post_meta( $object[ 'id' ], $field_name );
}
/**
* Handler for updating custom field data.
*
* #since 0.1.0
*
* #param mixed $value The value of the field
* #param object $object The object from the response
* #param string $field_name Name of field
*
* #return bool|int
*/
function update_meta_field( $value, $object, $field_name ) {
if ( ! $value || ! is_string( $value ) ) {
return;
}
return update_post_meta( $object->ID, $field_name, strip_tags( $value ) );
}
jQuery:
var sm1 = ['hi','hello'];
console.log(sm1);
var data = {
social_media: sm1
};
$.ajax({
method: "POST",
url: POST_SUBMITTER.root + 'wp/v2/custom',
data: data,
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', POST_SUBMITTER.nonce );
},
success : function( response ) {
console.log( response );
alert( POST_SUBMITTER.success );
},
fail : function( response ) {
console.log( response );
alert( POST_SUBMITTER.failure );
}
This is the JSON output when I try to insert a post:
{
"id": 120,
"date": "2017-04-07T09:48:39",
"date_gmt": "2017-04-07T08:48:39",
"author": 1,
"featured_media": 0,
"menu_order": 0,
"template": "",
"format": "standard",
"social_media": [],
}
}
JSON output when I view a post (for brevity I have kept it short):
[
{
"id": 116,
"date": "2017-04-07T09:43:53",
"date_gmt": "2017-04-07T08:43:53",
"social_media": [
"facebook",
"instagram"
]
}]
I'm looking for a way to extend the wc-api/vX/orders/ reponse. I've added multiple custom fields to the checkout (for eg: relation number, delivery date etc). These meta are saved within the order (wp_postmeta table). But why are they not returned with the api?
Normally you can extend the api response with some code like:
add_action( 'rest_api_init', 'custom_register_api_fields' );
function custom_register_api_fields() {
register_rest_field( 'shop_order','relation_number',
array(
'get_callback' => 'custom_api_meta_callback',
'update_callback' => null,
'schema' => null,
)
);
}
/**
*
* #param array $object Details of current post.
* #param string $field_name Name of field.
* #param WP_REST_Request $request Current request
*
* #return mixed
*/
function custom_api_meta_callback( $object, $field_name, $request ) {
return get_post_meta( $object[ 'id' ], $field_name, true );
}
But when I test the response (with Postman and the php lib), my-website.co/wc-api/v2/orders the custom meta are not visible.
Is there a way to register api fields for the wc-api?
Tnx!
i have the same requirement, add new value to "line_items" in order response
am using wc api v2
https://website.com/wp-json/wc/v2/orders
function get_product_order_image( $response, $object, $request ) {
if( empty( $response->data ) )
return $response;
$order_pid= $response->data['line_items'][0]['product_id'];
$l_w_product_meta = get_post_meta($response->data['line_items'][0]['product_id']);
$order_imgUrl= wp_get_attachment_url( $l_w_product_meta['_thumbnail_id'][0], 'full' );
$response->data['line_items'][0]['cover_image'] = $order_imgUrl;
return $response;
}
add_filter( "woocommerce_rest_prepare_shop_order_object", array( $this, "get_product_order_image"), 10, 3 );
Result
cover image added to line item result
i hope this will help someone in future.
REST API hook for add new value (product image) to "line_items" in order response for simple product and variable product both
Also Use for multiple products
function get_product_order_image( $response, $object, $request ) {
if( empty( $response->data ) )
return $response;
$images = array();
foreach($response->data['line_items'] as $key => $productItems){
$productID = $productItems['product_id'];
$variationID = $productItems['variation_id'];
if($variationID == 0){
$thumbnailID = get_post_meta( $productID, '_thumbnail_id', true);
$attachment = wp_get_attachment_image_src($thumbnailID, 'woocommerce_thumbnail' );
$image = $attachment[0];
}else{
$variation = new WC_Product_Variation( $variationID );
$image_id = $variation->get_image_id();
$attachment = wp_get_attachment_image_src($image_id, 'woocommerce_thumbnail' );
$image = $attachment[0];
}
$response->data['line_items'][$key]['image'] = $image;
}
return $response;
}
add_filter( "woocommerce_rest_prepare_shop_order_object", "get_product_order_image", 10, 3 );
Request:
wp-json/wc/v3/orders
wp-json/wc/v3/orders/XXX
wp-json/wc/v3/orders/?customers=XXX