How to save custom meta boxes in Wordpress - php

I've been trying to get my custom meta box data to save in Wordpress, and I haven't had any luck. I've tried researching other posts, but since everyone does it a little bit differently, I haven't had any success at using the tutorials and other posts out there.
I created a metabox:
add_action( 'add_meta_boxes', 'ic_add_heading_box' );
function ic_add_heading_box( $post ) {
add_meta_box(
'Meta Box',
'Heading Titles',
'ic_heading_box_content',
'page',
'normal',
'high'
);
}
function ic_heading_box_content( $post ) {
echo '<label>Main Heading (h1)</label>';
echo '<input type="text" name="heading_box_h1" value="" />';
echo '<label>Sub Heading (h3)</label>';
echo '<input type="text" name="heading_box_h3" value="" />';
}
I just can't for the life of me get the data I insert in to the fields to save in Wordpress. Any help would be greatly appreciated.

The function you are using is only a display function.
You are not actually doing nothing with the data . it is only for creating the metabox. not handling it.
You need to add
add_action( 'save_post', 'myplugin_save_postdata' );
and then use update_post_meta() with a function like in the codex example :
function myplugin_save_postdata( $post_id ) {
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return $post_id;
// Check the user's permissions. If want
if ( 'page' == $_POST['post_type'] ) {
if ( ! current_user_can( 'edit_page', $post_id ) )
return $post_id;
} else {
if ( ! current_user_can( 'edit_post', $post_id ) )
return $post_id;
}
/* OK, its safe for us to save the data now. */
// Sanitize user input. if you want
$mydata = sanitize_text_field( $_POST['myplugin_new_field'] );
// Update the meta field in the database.
update_post_meta( $post_id, '_my_meta_value_key', $mydata ); // choose field name
}

Related

How to add a custom field to the Edit Order page

I've been googling and searching here for a simple way to add an empty field box to the Edit Orders page. We will use this to put in a reference for the shipment from our courier.
We would add it to the order notes, but we want it to be searchable, and also want to add it as a column in the Orders Admin page (I have Admin Columns plugin that I think can do that bit, I just need to add this field to start).
Hope someone can help, thanks!
EDIT:
I found this question which seems to be similar, but more complicated, than what I am looking for and I cant figure out how to simplify it. Add a custom meta box on order edit pages and display it on the customer order pages
I don't need anything that will display on the front end to customers like this. Just a simple empty box that displays on every order-edit page (perhaps below the order notes) that can be searched. I will then display it in a column on the order admin page too.
Managed to get an answer, this is working great!
//from::https://codex.wordpress.org/Plugin_API/Action_Reference/manage_posts_custom_column
// For displaying in columns.
add_filter( 'manage_edit-shop_order_columns', 'set_custom_edit_shop_order_columns' );
function set_custom_edit_shop_order_columns($columns) {
$columns['custom_column'] = __( 'Custom Column', 'your_text_domain' );
return $columns;
}
// Add the data to the custom columns for the order post type:
add_action( 'manage_shop_order_posts_custom_column' , 'custom_shop_order_column', 10, 2 );
function custom_shop_order_column( $column, $post_id ) {
switch ( $column ) {
case 'custom_column' :
echo esc_html( get_post_meta( $post_id, 'custom_column', true ) );
break;
}
}
// For display and saving in order details page.
add_action( 'add_meta_boxes', 'add_shop_order_meta_box' );
function add_shop_order_meta_box() {
add_meta_box(
'custom_column',
__( 'Custom Column', 'your_text_domain' ),
'shop_order_display_callback',
'shop_order'
);
}
// For displaying.
function shop_order_display_callback( $post ) {
$value = get_post_meta( $post->ID, 'custom_column', true );
echo '<textarea style="width:100%" id="custom_column" name="custom_column">' . esc_attr( $value ) . '</textarea>';
}
// For saving.
function save_shop_order_meta_box_data( $post_id ) {
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// Check the user's permissions.
if ( isset( $_POST['post_type'] ) && 'shop_order' == $_POST['post_type'] ) {
if ( ! current_user_can( 'edit_shop_order', $post_id ) ) {
return;
}
}
// Make sure that it is set.
if ( ! isset( $_POST['custom_column'] ) ) {
return;
}
// Sanitize user input.
$my_data = sanitize_text_field( $_POST['custom_column'] );
// Update the meta field in the database.
update_post_meta( $post_id, 'custom_column', $my_data );
}
add_action( 'save_post', 'save_shop_order_meta_box_data' );
Use the default WooCommerce custom field in the order edit page bottom section.

How to set Payment Gateway by change order from admin side in WooCommerce

please help! I'm trying to define Payment Gateway by changing order details from admin.
As a default option I want to use 'bacs' payment gateway. Customer make order and then I want to change order and turn payment method to custom 'payment2' gateway.
For this, I've made metabox with checkbox which should turn on/off 'payment2' method and unset default 'bacs'. Checkbox working properly.
But, I can't get it to work. First of all, I can't get post meta with checkbox value. Check code below please:
function show_payment2_payment_gateway( $available_gateways ) {
$use_payment2 = get_post_meta( $post->ID, 'use_payment2', true );
if($use_payment2 == "yes") {
unset( $available_gateways['bacs'] );
}
else {
unset( $available_gateways['payment2'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'show_payment2_payment_gateway', 10, 1 );
UPD
This is my code for backend checkbox. As I said it's working well and save meta value as 'yes'
//
//Adding Meta container admin shop_order pages
//
add_action( 'add_meta_boxes', 'mv_add_meta_boxes' );
if ( ! function_exists( 'mv_add_meta_boxes' ) )
{
function mv_add_meta_boxes()
{
global $woocommerce, $order, $post;
add_meta_box( 'mv_other_fields', __('PAYMENT2','woocommerce'), 'mv_add_other_fields_for_packaging', 'shop_order', 'side', 'core' );
}
}
//
//adding Meta field in the meta container admin shop_order pages
//
if ( ! function_exists( 'mv_save_wc_order_other_fields' ) )
{
function mv_add_other_fields_for_packaging()
{
global $woocommerce, $order, $post;
$meta_field_data = get_post_meta( $post->ID, 'use_payment2', true );
$meta_field_data_checked = $meta_field_data["use_payment2"][0];
if($meta_field_data == "yes") $meta_field_data_checked = 'checked="checked"';
echo '
<label for="use_epay">TURN PAYMENT2 ON?</label>
<input type="hidden" name="mv_other_meta_field_nonce" value="' . wp_create_nonce() . '">
<input type="checkbox" name="use_payment2" value="yes" '.$meta_field_data_checked.'>';
}
}
//
//Save the data of the Meta field
//
add_action( 'save_post', 'mv_save_wc_order_other_fields', 10, 1 );
if ( ! function_exists( 'mv_save_wc_order_other_fields' ) )
{
function mv_save_wc_order_other_fields( $post_id ) {
// We need to verify this with the proper authorization (security stuff).
// Check if our nonce is set.
if ( ! isset( $_POST[ 'mv_other_meta_field_nonce' ] ) ) {
return $post_id;
}
$nonce = $_REQUEST[ 'mv_other_meta_field_nonce' ];
//Verify that the nonce is valid.
if ( ! wp_verify_nonce( $nonce ) ) {
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// Check the user's permissions.
if ( 'page' == $_POST[ 'post_type' ] ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
}
} else {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
}
// --- Its safe for us to save the data ! --- //
// Sanitize user input and update the meta field in the database.
update_post_meta( $post_id, 'use_payment2', $_POST[ 'use_payment2' ] );
}
}
UPD
This is working code for Back-End (custom checkbox metabox). It save checkbox value and change payment method in order details:
//
//Adding Meta container admin shop_order pages
//
add_action( 'add_meta_boxes', 'mv_add_meta_boxes' );
if ( ! function_exists( 'mv_add_meta_boxes' ) )
{
function mv_add_meta_boxes()
{
global $woocommerce, $order, $post;
add_meta_box( 'mv_other_fields', __('PAYMENT2','woocommerce'), 'mv_add_other_fields_for_packaging', 'shop_order', 'side', 'core' );
}
}
//
//adding Meta field in the meta container admin shop_order pages
//
if ( ! function_exists( 'mv_save_wc_order_other_fields' ) )
{
function mv_add_other_fields_for_packaging()
{
global $woocommerce, $order, $post;
$meta_field_data = get_post_meta( $post->ID, 'use_payment2', true );
echo '<label for="use_payment2">USE PAYMENT2?</label>
<input type="hidden" name="mv_other_meta_field_nonce" value="' . wp_create_nonce() . '">';
if($meta_field_data == "yes") {
$meta_field_data_checked = 'checked="checked"';
echo'<input type="checkbox" name="use_payment2" value="yes" '.$meta_field_data_checked.'>';
}
else {
echo'<input type="checkbox" name="use_payment2" value="yes">';
}
}
}
//Save the data of the Meta field
add_action( 'save_post', 'mv_save_wc_order_other_fields', 10, 1 );
if ( ! function_exists( 'mv_save_wc_order_other_fields' ) )
{
function mv_save_wc_order_other_fields( $post_id ) {
// We need to verify this with the proper authorization (security stuff).
// Check if our nonce is set.
if ( ! isset( $_POST[ 'mv_other_meta_field_nonce' ] ) ) {
return $post_id;
}
$nonce = $_REQUEST[ 'mv_other_meta_field_nonce' ];
//Verify that the nonce is valid.
if ( ! wp_verify_nonce( $nonce ) ) {
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// Check the user's permissions.
if ( 'page' == $_POST[ 'post_type' ] ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
}
} else {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
}
// --- Its safe for us to save the data ! --- //
// Sanitize user input and update the meta field in the database.
$use_payment2 = sanitize_text_field($_POST[ 'use_payment2' ]);
update_post_meta( $post_id, 'use_payment2', $use_payment2 );
if($_POST[ 'use_payment2' ] == 'yes') {
update_post_meta( $post_id, '_payment_method', 'payment2' );
}
elseif (get_post_meta( $post_id, '_payment_method', true ) != 'bacs') {
update_post_meta( $post_id, '_payment_method', 'bacs' );
}
}
}
But, how I can use checkbox state on my front-end? I still can't get checkbox value using this code:
function show_payment2_payment_gateway( $available_gateways ) {
global $woocommerce, $order, $post;
$payment_method = get_post_meta( $post_id, 'use_payment2', true );
if(isset($payment_method) == 'yes') {
unset( $available_gateways['bacs'] );
}
else {
unset( $available_gateways['payment2'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'show_payment2_payment_gateway', 10, 1 );
Now, it's always showing Payment2 option even if checkbox is checked or unchecked.
Update 2 related to your comments (and your question update)
The hook your are using is a front end hook (not admin), so it will not work.
To achieve what want, you need to replace some code inside the function that is going to save your custom checkbox value when you update the order in backend (Admin) edit order pages.
So your code will be now like this:
add_action( 'save_post', 'mv_save_wc_order_other_fields', 10, 1 );
if ( ! function_exists( 'mv_save_wc_order_other_fields' ) )
{
function mv_save_wc_order_other_fields( $post_id ) {
// We need to verify this with the proper authorization (security stuff).
// Check if our nonce is set.
if ( ! isset( $_POST[ 'mv_other_meta_field_nonce' ] ) )
return $post_id;
// Passing the value to a variable
$nonce = $_REQUEST[ 'mv_other_meta_field_nonce' ];
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return $post_id;
// Check the user's permissions.
if ( 'page' == $_POST[ 'post_type' ] ) {
if ( ! current_user_can( 'edit_page', $post_id ) )
return $post_id;
} else {
if ( ! current_user_can( 'edit_post', $post_id ) )
return $post_id;
}
// --- Its safe for us to save the data ! --- //
// Sanitize user input and update the meta field in the database.
$use_payment2 = sanitize_text_field($_POST[ 'use_payment2' ]);
update_post_meta( $post_id, 'use_payment2', $use_payment2 );
// Updating securely the data with your conditions
if($use_payment2 == 'yes')
update_post_meta( $post_id, '_payment_method', 'payment2' );
else
update_post_meta( $post_id, '_payment_method', 'bacs' );
}
}
This should work as you expect now…
Code goes in function.php file of your active child theme (or theme). Or also in any plugin php files.
As this code comme from one of my answers, you are not obliged to keep the same functions beginning names with "mv_" that was related to the username of the question. You can change it to "dan_" for example…
Reference: WooCommerce : Add custom Metabox to admin order page
The function that lists default payment gateways in WooCommerce is core_gateways(). This function is hooked to a filter called woocommerce_payment_gateways. So, the first step is to remove that filter and add our own. I will work only in the functions.php file within the theme folder (remember? Never modify core files). To do so, we’ll use the remove_filter() and the add_filter() functions:
remove_filter( 'woocommerce_payment_gateways', 'core_gateways' );
add_filter( 'woocommerce_payment_gateways', 'my_core_gateways' );
Now that we have removed the filter, you can see that in the add_filter() function we have a callback named my_core_gateways. This callback is the name of a function that will replace the default core_gateways() function. This function is the one that list WooCommerce default payment gateways. I will change the content of that function and replace the call to the WC_Gateway_BACS class. This class is the bank transfer default class. Here is the code of that new function:
/**
* core_gateways function modified.
*
* #access public
* #param mixed $methods
* #return void
*/
function my_core_gateways( $methods ) {
$methods[] = 'WC_Gateway_BACS_custom';
$methods[] = 'WC_Gateway_Cheque';
$methods[] = 'WC_Gateway_COD';
$methods[] = 'WC_Gateway_Mijireh';
$methods[] = 'WC_Gateway_Paypal';
return $methods;
}
As you can see the only change I made is that I replaced WC_Gateway_BACS by WC_Gateway_BACS_custom.
Are you still with me huh? Well, to summarize, I need to remove the filter that calls the default payment gateways, and use a custom function. In this custom function, I replace the call to the BACS class, and now i need to create this new BACS class. To do so, use that code:
class WC_Gateway_BACS_custom extends WC_Gateway_BACS {
/**
* Process the payment and return the result
*
* #access public
* #param int $order_id
* #return array
*/
function process_payment( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
// Mark as processing (that's what we want to change!)
$order->update_status('processing', __( 'Awaiting BACS payment', 'woocommerce' ));
// Reduce stock levels
$order->reduce_order_stock();
// Remove cart
$woocommerce->cart->empty_cart();
// Return thankyou redirect
return array(
'result' => 'success',
'redirect' => add_query_arg('key', $order->order_key, add_query_arg('order', $order->id, get_permalink(woocommerce_get_page_id('thanks'))))
);
}
}
In this snippet, I only changed the default status from “on-hold” to “processing”…. and boom the magic appears! Now each order paid using the BACS payment gateway will be marked as processing, not as on hold.
After few days of headache I found easy way how to show defined payment gateway only when I send link to customer.
Now customer can make order with default 'bacs' method, and Admin can check it before payment. Then admin change order status to Waiting for payment and link sends to customer. When customer opens link, my custom payment gateway becomes active.
I decided to use woocommerce endpoints to check if it 'order-pay' page. I used code below:
function show_payment2_payment_gateway( $available_gateways ) {
global $woocommerce, $order, $post;
if (is_wc_endpoint_url( 'order-pay' )) {
unset( $available_gateways['bacs'] );
}
else {
unset( $available_gateways['payment2'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'show_payment2_payment_gateway', 10, 1 );
Now it works exactly as I wanted before. I hope this will be useful. Thanks to #LoicTheAztec for help!

How to show custom data on custom post type admin screen edit page?

I have created form for enquiry. When user fill this form then I am saving it into database as a custom post type. In backend I need to show extra information on custom post edit page. But did not find any hook.
I have tried this code:
[![function add_extra_info_column( $columns ) {
return array_merge( $columns,
array( 'sticky' => __( 'Extra Info', 'your_text_domain' ) ) );
}
add_filter( 'manage_posts_columns' , 'add_extra_info_column' );][1]][1]
But it adds a new column in custom post.
I need to show extra info when we click on edit page link for every post.
This is just an example and you have to customize it for your needs:
First step: Adding Meta container hook to backend (for example here for products post type):
add_action( 'add_meta_boxes', 'extra_info_add_meta_boxes' );
if ( ! function_exists( 'extra_info_add_meta_boxes' ) )
{
function extra_info_add_meta_boxes()
{
global $post;
add_meta_box( 'extra_info_data', __('Extra Info','your_text_domain'), 'extra_info_data_content', 'product', 'side', 'core' );
}
}
(replace 'product' by your post type and this meta box could be like here on 'side' or by 'normal' to get it on main column)
Second step: Adding information in this metabox (fields, data, whatever…)
function extra_info_data_content()
{
global $post;
// Here you show your data <=====
}
References:
function add_meta_box()
How to add custom fields for WooCommerce order page (admin)?
How to add option to woo commerce edit order page?
Third step (optional): Save the data of the custom meta post (needed if you have some fields).
add_action( 'save_post', 'extra_info_save_woocommerce_other_fields', 10, 1 );
if ( ! function_exists( 'extra_info_save_woocommerce_other_fields' ) )
{
function extra_info_save_woocommerce_other_fields( $post_id )
{
// Check if our nonce is set.
if ( ! isset( $_POST[ 'extra_info_other_meta_field_nonce' ] ) )
{
return $post_id;
}
$nonce = $_REQUEST[ 'extra_info__other_meta_field_nonce' ];
//Verify that the nonce is valid.
if ( ! wp_verify_nonce( $nonce ) )
{
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
{
return $post_id;
}
// Check the user's permissions.
if ( 'page' == $_POST[ 'post_type' ] )
{
if ( ! current_user_can( 'edit_page', $post_id ) )
{
return $post_id;
}
}
else
{
if ( ! current_user_can( 'edit_post', $post_id ) )
{
return $post_id;
}
}
/* --- !!! OK, its safe for us to save the data now. !!! --- */
// Sanitize user input and Update the meta field in the database.
}
}

Wordpress: Saving post metadata entry in the admin post panel

I'm working on a plugin, where I have defined a hook which is supposed to create a custom post field in the admin panel. The code for the same:
//ADDING CUSTOM FIELDS IN ADMIN PANEL
add_action('add_meta_boxes', 'jericho_meta');
add_action('save_post', 'jericho_saved');
function jericho_meta()
{
add_meta_box('jericho_name', 'Favorite PPV', 'jericho_handler', 'post');
}
function jericho_handler()
{
$value = get_post_custom($post->ID);
$namey = esc_attr($value['jericho_name'][0]);
echo '<label for = "jericho_name">Favorite PPV</label><input type = "text" id = "jericho_name" name = "jericho_name" value = "'.$namey.'" />';
}
function jericho_saved()
{
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
{
return;
}
if(!current_user_can('edit_post'))
{
return;
}
if(isset($_POST['jericho_name']))
{
update_post_meta($post_id, 'jericho_name', $_POST['jericho_name']);
}
}
This code generates a custom post field in the admin post panel as shown in the screenshot below:
However, when I enter a value in that text field and click on Update, the input value never gets saved inside the text field when I try checking the field on refreshing the page.
What seems to be wrong with my code?
EDIT 1:
I have updated my code and added a new action named save_post and defined its corresponding function. However, the problem seems to be with the way I have defined the input field itself, because when I tried inspecting the text field's element, this is what I got:
<input type="text" id="jericho_name" name="jericho_name" value>
Based on the code you provided i can see that you are not registering callback/trigger for saving post meta data.
You need to handle this by yourself (will not be handled automaticly).
Currently, what you did is you tied "jericho_handler()" function to render data when post edit page renders. And that works just fine, as it should.
You need to add additional function which will be triggered on 'save_post' where you will handle saving data into the database.
add_action( 'save_post', 'cd_meta_box_save' );
function cd_meta_box_save( $post_id )
{
// Bail if we're doing an auto save
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
// if our nonce isn't there, or we can't verify it, bail
if( !isset( $_POST['meta_box_nonce'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'my_meta_box_nonce' ) ) return;
// if our current user can't edit this post, bail
if( !current_user_can( 'edit_post' ) ) return;
// now we can actually save the data
$allowed = array(
'a' => array( // on allow a tags
'href' => array() // and those anchors can only have href attribute
)
);
// Make sure your data is set before trying to save it
if( isset( $_POST['my_meta_box_text'] ) )
update_post_meta( $post_id, 'my_meta_box_text', wp_kses( $_POST['my_meta_box_text'], $allowed ) );
if( isset( $_POST['my_meta_box_select'] ) )
update_post_meta( $post_id, 'my_meta_box_select', esc_attr( $_POST['my_meta_box_select'] ) );
// This is purely my personal preference for saving check-boxes
$chk = isset( $_POST['my_meta_box_check'] ) && $_POST['my_meta_box_select'] ? 'on' : 'off';
update_post_meta( $post_id, 'my_meta_box_check', $chk );
}
?>
Please check detail tutorial over here. Code i pasted above is from this link.
If you are already registering this handler and you are still encountering issues, please update your question with other parts of code as well.

How to add multiple meta boxes in wordpress using the users input for any post in a custom post type?

What i am actually trying to do here is :
- I have a custom post type to add videos.
- Now in every video a user can add multiple fields for a video for eg.
-- I have a video on which there will be multiple overlays containing (title, desc, button , link etc) and the number of overlays are completely dynamic so the user should be able to set it for every video.
-- So if the user says 5, then the user should be get 5 title, desc, button fields to add
I can add this statically for a particular amount, but how do i make this dynamic.
Thanks
You can create your own fields in your plugin, it is not difficult, you just need to know what you want to put in your post type ...
To add your fields you need to know jQuery to add more fields dynamically...
No need for another plugin created because you'd have many things that would use...
<?php
add_meta_box( "my-new-meta", "Video Options", "metas_form", "your_post_type_name", "normal", "high")
function metas_form( $post ){
$post_id = $post->ID;
$meta_value = get_post_meta( $post_id, 'meta_key_text', true );
?>
<div>
<label id="my_field">Name</label>
<input type="text" id="my_field" name="my_field" value="<?php echo $meta_value ?>">
</div>
<input type="hidden" name="field_nonce" id="field_nonce" value="<?php echo wp_create_nonce( plugin_basename(__FILE__) ); ?>" />
<?php
}
add_action( 'save_post', 'save_fn' );
function save_fn( ) {
global $post, $post_id, $typenow;
if ( $typenow == 'your_post_type_name' && isset( $_POST ) ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return $post_id;
if ( !isset( $_POST['field_nonce'] ) || !wp_verify_nonce( $_POST['field_nonce'], plugin_basename(__FILE__) )) return $post_id;
$meta_value = $_POST['my_field'];
update_post_meta( $post->ID, 'meta_key_text', $meta_value );
}
}

Categories