Send custom select shipping method from cart to checkout page - wordpress

I have this code for adding custom select field for method shipping
// Add custom fields to a specific selected shipping method
add_action( 'woocommerce_after_shipping_rate', 'carrier_custom_fields', 20, 2 );
function carrier_custom_fields( $method, $index ) {
if( (is_checkout() === 'false') OR (is_cart() === 'false') ) { return; } // Only on checkout page
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
if( $method->id != 'flat_rate:3' ) return;
if ($chosen_shipping == 'flat_rate:3') {
echo '<div class="tk"><div class="td_title">Выберите транспортную компанию:</div>';
woocommerce_form_field( 'shipping_tk', array(
'type' => 'select',
'options' => array(
'delovye-linii' => __('Деловые линии', 'woocommerce' ),
'bajkal-servis' => __('Байкал Сервис', 'woocommerce' ),
'trans-vektor' => __('Транс Вектор', 'woocommerce' ),
'mejdzher-ehkspress' => __('Мейджер экспресс', 'woocommerce' ),
'cdek' => __('CDEK', 'woocommerce' ),
'transportnye-tekhnologii' => __('Транспортные технологии', 'woocommerce' ),
'zheldorehkspediciya' => __('Желдорэкспедиция', 'woocommerce' ),
'zheldoralyans' => __('Желдоральянс', 'woocommerce' ),
'kashalot' => __('Кашалот', 'woocommerce' ),
'dpd' => __('ДПД', 'woocommerce' ),
'magic-trans' => __('Мейджик Транс', 'woocommerce' ),
'severyug' => __('Север-Юг', 'woocommerce' ),
'skif' => __('Скиф Карго', 'woocommerce' ),
'vozovoz' => __('Возовоз', 'woocommerce' ),
'express-avto' => __('Экспресс Авто', 'woocommerce' ),
'nord-tranzit' => __('Норд Транзит', 'woocommerce' )
),
'default' => 'delovye-linii',
'class' => array('shipping_tk'),
'input_class' => array('shipping_tk'),
'required' => false,
), WC()->checkout->get_value( 'shipping_tk' ));
echo '</div>';
}
}
// Save custom fields to order meta data
add_action( 'woocommerce_checkout_update_order_meta', 'carrier_update_order_meta', 30, 1 );
function carrier_update_order_meta( $order_id ) {
$name_tk = array(
'delovye-linii' => 'Деловые Линии ТК',
'bajkal-servis' => 'Байкал-Сервис ТК',
'trans-vektor' => 'Вектор Экспресс (Транс Вектор) ТК',
'mejdzher-ehkspress' => 'МейджерЭкспресс ТК',
'cdek' => 'СДЭК Глобал ТК',
'transportnye-tekhnologii' => 'Транспортные Технологии ТК',
'zheldorehkspediciya' => 'ЖелдорЭкспедиция ТК',
'zheldoralyans' => 'Азбука логистики (ЖелДорАльянс) ТК',
'kashalot' => 'Кашалот (КИТ) ТК',
'dpd' => 'ДПД-Рус ТК',
'magic-trans' => 'Мейджик Транс ТК',
'severyug' => 'Север-Юг ТК',
'skif' => 'Скиф Карго ТК',
'vozovoz' => 'ТК Возовоз',
'express-avto' => 'Экспресс Авто',
'nord-tranzit' => 'Норд Транзит ТК'
);
if( isset( $_POST['shipping_tk'] )) {
$key_tk = $_POST['shipping_tk'];
update_post_meta( $order_id, '_shipping_tk', sanitize_text_field( $name_tk[$key_tk] ) ); }
if( isset( $_POST['shipping_tk2'] )) {
$key_tk = $_POST['shipping_tk'];
update_post_meta( $order_id, '_shipping_tk', sanitize_text_field( $name_tk[$key_tk] ) ); }
if( isset( $_POST['order_track'] )) {
$key_tk = $_POST['order_track'];
update_post_meta( $order_id, '_order_track', sanitize_text_field( $name_tk[$key_tk] ) ); }
}
enter image description here
But when go in checkout field my selected option in custom field is default. For example, in cart i select 3 option in select, but in checkout it is not saved.
code in cart-shipping.php file
<ul id="shipping_method" class="woocommerce-shipping-methods">
<?php foreach ( $available_methods as $method ) : ?>
<li>
<?php
if ( 1 < count( $available_methods ) ) {
printf( '<input type="radio" name="shipping_method[%1$d]" data-index="%1$d" id="shipping_method_%1$d_%2$s" value="%3$s" class="shipping_method" %4$s />', $index, esc_attr( sanitize_title( $method->id ) ), esc_attr( $method->id ), checked( $method->id, $chosen_method, false ) ); // WPCS: XSS ok.
} else {
printf( '<input type="hidden" name="shipping_method[%1$d]" data-index="%1$d" id="shipping_method_%1$d_%2$s" value="%3$s" class="shipping_method" />', $index, esc_attr( sanitize_title( $method->id ) ), esc_attr( $method->id ) ); // WPCS: XSS ok.
}
if ( $method->id == 'flat_rate:3' OR $method->id == 'flat_rate:7' ) {
printf( '<label for="shipping_method_%1$s_%2$s">%3$s</label>', $index, esc_attr( sanitize_title( $method->id ) ), wc_cart_totals_shipping_method_label( $method ) );
// WPCS: XSS ok.
} else {
printf( '<label for="shipping_method_%1$s_%2$s">%3$s</label>', $index, esc_attr( sanitize_title( $method->id ) ), wc_cart_totals_shipping_method_label( $method ) ); // WPCS: XSS ok.
}
do_action( 'woocommerce_after_shipping_rate', $method, $index );
?>
</li>
<?php endforeach; ?>
</ul>
I want to save selected option and send it to checkout page

Related

Display custom DOB fields in WooCommerce admin order edit pages

I've added this code to functions.php
// Hook in
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
add_filter( 'woocommerce_ship_to_different_address_checked', '__return_false' );
add_action( 'woocommerce_before_order_notes', 'competitor_details' );
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
unset($fields['order']['order_comments']);
return $fields;
}
function competitor_details( $checkout ) {
echo '<div id="competitor_details"><h3>' . __('Competitor\'s Details') . '</h3>';
woocommerce_form_field( 'competitor_first_name',array('label' => 'First name', 'type' => 'text', 'required' => 'true')
, $checkout->get_value( 'my_field_name' ));
woocommerce_form_field( 'competitor_last_name',array('label' => 'Last name', 'type' => 'text', 'required' => 'true')
, $checkout->get_value( 'my_field_name' ));
echo '<div id="competitor_details"><h4>' . __('Date of birth') . '</h4>';
woocommerce_form_field( 'competitor_dob_day',array('label' => 'Day', 'type' => 'select', 'required' => 'true', 'options' => array(''=>'','1'=>'1','2'=>'2','3'=>'3','4'=>'4','5'=>'5','6'=>'6','7'=>'7','8'=>'8','9'=>'9','10'=>'10','11'=>'11','12'=>'12','13'=>'13','14'=>'14','15'=>'15','16'=>'16','17'=>'17','18'=>'18','19'=>'19','20'=>'20','21'=>'21','22'=>'22','23'=>'23','24'=>'24','25'=>'25','26'=>'26','27'=>'27','28'=>'28','29'=>'29','30'=>'30','31'=>'31'))
, $checkout->get_value( 'my_field_name' ));
woocommerce_form_field( 'competitor_dob_month',array('label' => 'Month', 'type' => 'select', 'required' => 'true', 'options' => array(''=>'','Jan'=>'Jan','Feb'=>'Feb','Mar'=>'Mar','Apr'=>'Apr','May'=>'May','Jun'=>'Jun','Jul'=>'Jul','Aug'=>'Aug','Sep'=>'Sep','Oct'=>'Oct','Nov'=>'Nov','Dec'=>'Dec'))
, $checkout->get_value( 'my_field_name' ));
woocommerce_form_field( 'competitor_dob_year',array('label' => 'Year', 'type' => 'text', 'required' => 'true')
, $checkout->get_value( 'my_field_name' ));
echo '<div id="consent_to_rules"><h4>' . __('I have read the Rules and agree to abide by them') . '</h4>';
woocommerce_form_field( 'consent_to_rules',array('label' => 'YES, I agree', 'type' => 'checkbox', 'required' => 'true')
, $checkout->get_value( 'my_field_name' ));
echo '</div>';
}
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['competitor_first_name'] )
wc_add_notice( __( 'Please enter Competitors First Name' ), 'error' );
if ( ! $_POST['competitor_last_name'] )
wc_add_notice( __( 'Please enter Competitors Last Name' ), 'error' );
if ( ! $_POST['competitor_dob_day'] )
wc_add_notice( __( 'Please enter Competitors date of birth' ), 'error' );
if ( ! $_POST['competitor_dob_month'] )
wc_add_notice( __( 'Please enter Competitors date of birth' ), 'error' );
if ( ! $_POST['competitor_dob_year'] )
wc_add_notice( __( 'Please enter Competitors date of birth' ), 'error' );
if ( ! $_POST['consent_to_rules'] )
wc_add_notice( __( 'Please agree that you have read the Rules' ), 'error' );
}
That adds the required fields to the checkout page. I don't want a date picker, because the DOB can be anything really - it just has to be easy to enter.
The checkout works fine, but I don't see the field values when I'm checking the order details in the admin area.
Any help with that?
First of all, I've rewritten your current code, as it had some minor bugs
// Unset order comments field
function filter_woocommerce_checkout_fields( $fields ) {
unset( $fields['order']['order_comments'] );
return $fields;
}
add_filter( 'woocommerce_checkout_fields' , 'filter_woocommerce_checkout_fields', 10, 1 );
// NOT checked by default
add_filter( 'woocommerce_ship_to_different_address_checked', '__return_false' );
// Add custom fields
function action_woocommerce_before_order_notes( $checkout ) {
echo '<h3>' . __( 'Competitor\'s Details', 'woocommerce' ) . '</h3>';
// First name
woocommerce_form_field( 'competitor_first_name', array(
'label' => __( 'First name', 'woocommerce' ),
'type' => 'text',
'required' => 'true'
), $checkout->get_value( 'competitor_first_name' ) );
// Last name
woocommerce_form_field( 'competitor_last_name', array(
'label' => __( 'Last name', 'woocommerce' ),
'type' => 'text',
'required' => 'true'
), $checkout->get_value( 'competitor_last_name' ) );
echo '<h4>' . __( 'Date of birth', 'woocommerce' ) . '</h4>';
// Options day
$options_day = array( '' => __( 'Please select a day', 'woocommerce' ) );
$from = 1;
$to = 31;
$options_day_combine = $options_day + array_combine( range( $from, $to ), range( $from, $to ) );
// Dob day
woocommerce_form_field( 'competitor_dob_day', array(
'label' => __( 'Day', 'woocommerce' ),
'type' => 'select',
'required' => 'true',
'options' => $options_day_combine
), $checkout->get_value( 'competitor_dob_day' ) );
// Dob month
woocommerce_form_field( 'competitor_dob_month', array(
'label' => __( 'Month', 'woocommerce' ),
'type' => 'select',
'required' => 'true',
'options' => array(
'' => __( 'Please select a month', 'woocommerce' ),
'Jan' => __( 'Jan', 'woocommerce' ),
'Feb' => __( 'Feb', 'woocommerce' ),
'Mar' => __( 'Mar', 'woocommerce' ),
'Apr' => __( 'Apr', 'woocommerce' ),
'May' => __( 'May', 'woocommerce' ),
'Jun' => __( 'Jun', 'woocommerce' ),
'Jul' => __( 'Jul', 'woocommerce' ),
'Aug' => __( 'Aug', 'woocommerce' ),
'Sep' => __( 'Sep', 'woocommerce' ),
'Oct' => __( 'Oct', 'woocommerce' ),
'Nov' => __( 'Nov', 'woocommerce' ),
'Dec' => __( 'Dec', 'woocommerce' ),
)
), $checkout->get_value( 'competitor_dob_month' ) );
// Options year
$options_year = array( '' => __( 'Please select a year', 'woocommerce' ) );
$from = 2021;
$to = 1910;
$options_year_combine = $options_year + array_combine( range( $from, $to ), range( $from, $to ) );
// Dob year
woocommerce_form_field( 'competitor_dob_year', array(
'label' => __( 'Year', 'woocommerce' ),
'type' => 'select',
'required' => 'true',
'options' => $options_year_combine
), $checkout->get_value( 'competitor_dob_year' ) );
echo '<h4>' . __( 'I have read the Rules and agree to abide by them', 'woocommerce' ) . '</h4>';
// Rules
woocommerce_form_field( 'consent_to_rules', array(
'label' => __( 'Yes, I agree', 'woocommerce' ),
'type' => 'checkbox',
'required' => 'true'
), $checkout->get_value( 'consent_to_rules' ) );
}
add_action( 'woocommerce_before_order_notes', 'action_woocommerce_before_order_notes', 10, 1 );
// Validate custom fields
function action_woocommerce_checkout_process() {
// Isset and empty, add an error
if ( isset( $_POST['competitor_first_name'] ) && empty( $_POST['competitor_first_name'] ) ) {
wc_add_notice( __( 'Please enter Competitors First Name', 'woocommerce' ), 'error' );
}
if ( isset( $_POST['competitor_last_name'] ) && empty( $_POST['competitor_last_name'] ) ) {
wc_add_notice( __( 'Please enter Competitors Last Name', 'woocommerce' ), 'error' );
}
if ( isset( $_POST['competitor_dob_day'] ) && empty( $_POST['competitor_dob_day'] ) ) {
wc_add_notice( __( 'Please enter Competitors date of birth - day', 'woocommerce' ), 'error' );
}
if ( isset( $_POST['competitor_dob_month'] ) && empty( $_POST['competitor_dob_month'] ) ) {
wc_add_notice( __( 'Please enter Competitors date of birth - month', 'woocommerce' ), 'error' );
}
if ( isset( $_POST['competitor_dob_year'] ) && empty( $_POST['competitor_dob_year'] ) ) {
wc_add_notice( __( 'Please enter Competitors date of birth - year', 'woocommerce' ), 'error' );
}
if ( ! isset( $_POST['consent_to_rules'] ) ) {
wc_add_notice( __( 'Please agree that you have read the Rules', 'woocommerce' ), 'error' );
}
}
add_action( 'woocommerce_checkout_process', 'action_woocommerce_checkout_process', 10, 0 );
To answer your question, save and display
Use the woocommerce_checkout_create_order and woocommerce_admin_order_data_after_billing_address actions hooks.
This parts can be optimized with a foreach loop as opposed to adding an if condition every time, but I have not applied this so that everything stays clear.
So you get:
// Save fields
function action_woocommerce_checkout_create_order( $order, $data ) {
// Isset and NOT empty, save
if ( isset( $_POST['competitor_first_name'] ) && ! empty( $_POST['competitor_first_name'] ) ) {
// Update meta data
$order->update_meta_data( 'competitor_first_name', sanitize_text_field( $_POST['competitor_first_name'] ) );
}
if ( isset( $_POST['competitor_last_name'] ) && ! empty( $_POST['competitor_last_name'] ) ) {
// Update meta data
$order->update_meta_data( 'competitor_last_name', sanitize_text_field( $_POST['competitor_last_name'] ) );
}
if ( isset( $_POST['competitor_dob_day'] ) && ! empty( $_POST['competitor_dob_day'] ) ) {
// Update meta data
$order->update_meta_data( 'competitor_dob_day', sanitize_text_field( $_POST['competitor_dob_day'] ) );
}
if ( isset( $_POST['competitor_dob_month'] ) && ! empty( $_POST['competitor_dob_month'] ) ) {
// Update meta data
$order->update_meta_data( 'competitor_dob_month', sanitize_text_field( $_POST['competitor_dob_month'] ) );
}
if ( isset( $_POST['competitor_dob_year'] ) && ! empty( $_POST['competitor_dob_year'] ) ) {
// Update meta data
$order->update_meta_data( 'competitor_dob_year', sanitize_text_field( $_POST['competitor_dob_year'] ) );
}
if ( isset( $_POST['consent_to_rules'] ) ) {
// Update meta data
$order->update_meta_data( 'consent_to_rules', sanitize_text_field( $_POST['consent_to_rules'] ) );
}
}
add_action( 'woocommerce_checkout_create_order', 'action_woocommerce_checkout_create_order', 10, 2 );
// Display the custom 'select' field value on admin order pages after billing adress
function action_woocommerce_admin_order_data_after_billing_address( $order ) {
// Get meta
$competitor_first_name = $order->get_meta( 'competitor_first_name' );
// NOT empty
if ( ! empty ( $competitor_first_name ) ) {
echo '<p><strong>' . __( 'Competitor first name', 'woocommerce' ) . ':</strong> ' . $competitor_first_name . '</p>';
}
// Get meta
$competitor_last_name = $order->get_meta( 'competitor_last_name' );
// NOT empty
if ( ! empty ( $competitor_last_name ) ) {
echo '<p><strong>' . __( 'Competitor last name', 'woocommerce' ) . ':</strong> ' . $competitor_last_name . '</p>';
}
// Get meta
$competitor_dob_day = $order->get_meta( 'competitor_dob_day' );
// NOT empty
if ( ! empty ( $competitor_dob_day ) ) {
echo '<p><strong>' . __( 'Competitor dob day', 'woocommerce' ) . ':</strong> ' . $competitor_dob_day . '</p>';
}
// Get meta
$competitor_dob_month = $order->get_meta( 'competitor_dob_month' );
// NOT empty
if ( ! empty ( $competitor_dob_month ) ) {
echo '<p><strong>' . __( 'Competitor dob month', 'woocommerce' ) . ':</strong> ' . $competitor_dob_month . '</p>';
}
// Get meta
$competitor_dob_year = $order->get_meta( 'competitor_dob_year' );
// NOT empty
if ( ! empty ( $competitor_dob_year ) ) {
echo '<p><strong>' . __( 'Competitor dob year', 'woocommerce' ) . ':</strong> ' . $competitor_dob_year . '</p>';
}
// Get meta
$consent_to_rules = $order->get_meta( 'consent_to_rules' );
// NOT empty
if ( ! empty ( $consent_to_rules ) ) {
echo '<p><strong>' . __( 'Yes, I agree', 'woocommerce' ) . '</strong></p>';
}
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'action_woocommerce_admin_order_data_after_billing_address', 10, 1 );

Checkbox custom fields for admin edit product in Woocommerce

I'm trying to add checkbox to settings tab in WooCommerce (in admin panel) and use this code:
add_action( 'woocommerce_product_options_general_product_data', 'wc_custom_add_custom_fields' );
function wc_custom_add_custom_fields() {
global $post;
woocommerce_wp_checkbox(array(
'id' => 'is_gift',
'label' => __('Gift', 'woocommerce' ),
'description' => __( 'Add gift label', 'woocommerce' ),
'value' => get_post_meta($post->ID, 'is_gift', true)
));
}
add_action( 'woocommerce_process_product_meta', 'wc_custom_save_custom_fields' );
function wc_custom_save_custom_fields() {
global $post;
if (!empty($_POST['is_gift'])) {
update_post_meta( $post->ID, 'is_gift', esc_attr( $_POST['is_gift'] ) );
}
}
This code showing checkbox, but not saving changes. It works only for one product. I guess something wrong with $post->ID?
Updated … Try this instead:
add_action( 'woocommerce_product_options_general_product_data', 'wc_custom_add_custom_fields' );
function wc_custom_add_custom_fields() {
global $post;
$input_checkbox = get_post_meta( $post->ID, 'is_gift', true );
if( empty( $input_checkbox ) ) $input_checkbox = '';
woocommerce_wp_checkbox(array(
'id' => 'is_gift',
'label' => __('Gift', 'woocommerce' ),
'description' => __( 'Add gift label', 'woocommerce' ),
'value' => $input_checkbox,
));
}
add_action( 'woocommerce_process_product_meta', 'wc_custom_save_custom_fields' );
function wc_custom_save_custom_fields($post_id) {
$_custom_text_option = isset( $_POST['is_gift'] ) ? 'yes' : '';
update_post_meta( $post_id, 'is_gift', $_custom_text_option );
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
try this
add_action( 'woocommerce_product_options_general_product_data', 'woo_add_custom_general_fields' );
function woo_add_custom_general_fields() {
global $woocommerce, $post;
$checkbox_value = get_post_meta( $post->ID, 'is_gift', true );
if( empty( $checkbox_value ) ){
$checkbox_value = '';
}
woocommerce_wp_checkbox(
array(
'id' => 'is_gift',
'label' => __('Gift', 'woocommerce' ),
'description' => __( 'Add gift label', 'woocommerce' ),
'value' => $checkbox_value,
)
);
}
// Save Fields
add_action( 'woocommerce_process_product_meta', 'woo_add_custom_general_fields_save' );
function woo_add_custom_general_fields_save( $post_id ){
// Checkbox
$_checkbox = $_POST['is_gift'];
if (isset( $_checkbox )){
update_post_meta( $post_id, '_is_gift', $_checkbox );
}
}

Wordpress Woocommerce custom field

I'm trying to create custom field in woo-commerce (not interested in plugins) in single product and variable product ( custom field price should change according to selected variable option) as that client should be able to enter price as show in 1st picture and customer could be able check the option.
My Requirement
// Display Fields
add_action( 'woocommerce_product_options_general_product_data', 'woocom_general_product_data_custom_field' );
function woocom_general_product_data_custom_field() {
// Create a custom text field
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_text_field',
'label' => __( 'Enter your choose', 'woocommerce' ),
'placeholder' => 'Custom text field',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' )
)
);
// Number Field
woocommerce_wp_text_input(
array(
'id' => '_number_field',
'label' => __( 'Enter your number', 'woocommerce' ),
'placeholder' => '',
'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'type' => 'number',
'custom_attributes' => array(
'step' => 'any',
'min' => '15'
)
)
);
// Checkbox
woocommerce_wp_checkbox(
array(
'id' => '_checkbox',
'label' => __('Select', 'woocommerce' ),
'description' => __( 'Check me!', 'woocommerce' )
)
);
// Select
woocommerce_wp_select(
array(
'id' => '_select',
'label' => __( 'option', 'woocommerce' ),
'options' => array(
'1' => __( 'Custom Option 1', 'woocommerce' ),
'2' => __( 'Custom Option 2', 'woocommerce' ),
'3' => __( 'Custom Option 3', 'woocommerce' )
)
)
);
// Textarea
woocommerce_wp_textarea_input(
array(
'id' => '_textarea',
'label' => __( 'Description', 'woocommerce' ),
'placeholder' => '',
'description' => __( 'Enter the custom value here.', 'woocommerce' )
)
);
}
// Hook to save the data value from the custom fields
add_action( 'woocommerce_process_product_meta', 'woocom_save_general_proddata_custom_field' );
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_top_category_desc', 1 );
function woocommerce_template_top_category_desc (){
$terms = get_the_terms( $post->ID, 'wc-attibute-class' );
if ( !empty($terms)) {
$term = array_pop($terms);
$text= get_field('txt-field', $term);
if (!empty($text)) {
echo $text;
}
}
}
/** Hook callback function to save custom fields information */
function woocom_save_general_proddata_custom_field( $post_id ) {
// Save Text Field
$text_field = $_POST['_text_field'];
if( ! empty( $text_field ) ) {
update_post_meta( $post_id, '_text_field', esc_attr( $text_field ) );
}
// Save Number Field
$number_field = $_POST['_number_field'];
if( ! empty( $number_field ) ) {
update_post_meta( $post_id, '_number_field', esc_attr( $number_field ) );
}
// Save Textarea
$textarea = $_POST['_textarea'];
if( ! empty( $textarea ) ) {
update_post_meta( $post_id, '_textarea', esc_html( $textarea ) );
}
// Save Select
$select = $_POST['_select'];
if( ! empty( $select ) ) {
update_post_meta( $post_id, '_select', esc_attr( $select ) );
}
// Save Checkbox
$checkbox = isset( $_POST['_checkbox'] ) ? 'yes' : 'no';
update_post_meta( $post_id, '_checkbox', $checkbox );
// Save Hidden field
$hidden = $_POST['_hidden_field'];
if( ! empty( $hidden ) ) {
update_post_meta( $post_id, '_hidden_field', esc_attr( $hidden ) );
}
}
I have tried some woocommerce custom plugin but it didn't solve my requirement as I have 25 above custom filed to be created and plugin seems to be very lengthy process for my work
My output is in picture 2 which I got from coding for not as my requirement
My output
I know you are not interested in plugins, but I highly recommend ACF plugin for custom fields. Check it out, it will save you a lot of time.

Custom post type saving and permalink problems

I created my CPT, but I have some problems:
when I publish or upgrade the data entered in the field 'ora' they are saved but disappear from the field.
The permalink does not take its name from the title of the post but from one of the elements of the Metabox 'Conduce' that takes his values from another cpt.
How can I fix it ???
This is my code.
<?php
add_action('init', 'palinsesto_manager');
function palinsesto_manager() {
$labels = array(
'name' => 'Palinsesto',
'singular_name' => 'programma',
'add_new' => 'Aggiungi Programma',
'add_new_item' => 'Nuovo Programma',
'edit_item' => 'Modifica Programma',
'new_item' => 'Nuovo Programma',
'all_items' => 'Palinsesto',
'view_item' => 'Visualizza ',
'search_items' => 'Cerca ',
'not_found' => 'Programma non trovato',
'not_found_in_trash' => 'Programma non trovato nel cestino',
);
$args = array(
'labels' => $labels,
'public' => true,
'show_ui' => true,
'rewrite' => array('slug' => 'palinsesto'),
'publicly_queryable' => true,
'has_archive' => true,
'capability_type' => 'post',
'hierarchical' => false,
'menu_icon' => 'dashicons-format-audio',
'menu_position' => 5,
'supports' => array(
'title',
'thumbnail'
),
);
register_post_type('palinsesto', $args);
}
if ( function_exists( 'add_theme_support' ) ) {
add_theme_support( 'post-thumbnails' );
add_image_size( 'cover', 640, 300 );
}
//orario
add_action('add_meta_boxes','palinsesto_box_add');
function palinsesto_box_add(){
add_meta_box('palinsesto_box','Programmazione','program_palinsesto','palinsesto','normal','high');
}
function program_palinsesto($post){
$values = get_post_custom( $post->ID );
$selected = isset( $values['giorno'] ) ? esc_attr( $values['giorno'][0] ) : '';
$text = isset( $values['ora'] ) ? esc_attr( $values['ora'][0] ) : '';
wp_nonce_field(__FILE__, 'palinsesto_nonce');
?>
<p>
<label for="giorno"><b>Giorno</b></label>
<select name="giorno" id="giorno">
<option value="lunedi" <?php selected( $selected, 'lunedi' ); ?>>Lunedi</option>
<option value="martedi" <?php selected( $selected, 'martedi' ); ?>>Martedi</option>
<option value="mercoledi" <?php selected( $selected, 'mercoledi' ); ?>>Mercoledi</option>
<option value="giovedi" <?php selected( $selected, 'giovedi' ); ?>>Giovedi</option>
<option value="venerdi" <?php selected( $selected, 'venerdi' ); ?>>Venerdi</option>
<option value="sabato" <?php selected( $selected, 'sabato' ); ?>>Sabato</option>
<option value="domenica" <?php selected( $selected, 'domenica' ); ?>>Domenica</option>
</select>
</p>
<p>
<label for="ora"> <b>Ora (formato hh.mm)</b></label>
<input type="text" name="ora" id="ora" value="<?php echo $text; ?>" />
</p>
<p>
</p>
<?php
}
//fine orario
add_action("add_meta_boxes", "palinsesto_box");
function palinsesto_box() {
add_meta_box("palinsesto-meta", "Conduce", "palinsesto_manager_meta_options", "palinsesto", "side" );
}
function palinsesto_manager_meta_options( $post ) {
wp_nonce_field( 'palinsesto_manager_meta_options', 'palinsesto_manager_meta_options_nonce' );
echo '<label for="speaker_id">';
_e("Speaker", 'speaker_id' );
echo '</label> ';
$args = array( 'post_type' => 'speaker');
$loop = new WP_Query( $args );
$speaker_id_values = get_post_meta( $post->ID, '_speaker_ids', true ); ?>
<?php if ( $loop->have_posts() ): ?>
<select name="speaker_id[]" id="speaker_id" multiple="multiple" required>
<?php while( $loop->have_posts() ): $loop->the_post(); ?>
<?php
$selected = ( in_array( get_the_ID(), $speaker_id_values ) ) ? 'selected="selected"' : '';
?>
<option value="<?php the_ID() ?>" <?php echo $selected; ?>><?php the_title(); ?> </option>
<?php endwhile; ?>
</select>
<p>Tieni premuto CTRL per selezionare i conduttori</p>
<?php endif ?>
<?php
}
add_action('save_post', 'save_palinsesto_manager_meta_options');
function save_palinsesto_manager_meta_options($post_id) {
// Check if our nonce is set.
if ( ! isset( $_POST['palinsesto_manager_meta_options_nonce'] ) )
return $post_id;
$nonce = $_POST['palinsesto_manager_meta_options_nonce'];
// Verify that the nonce is valid.
if ( ! wp_verify_nonce( $nonce, 'palinsesto_manager_meta_options' ) )
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;
}
if ( isset( $_POST['speaker_id'] ) ) {
$sanitized_data = array();
$data = (array) $_POST['speaker_id'];
foreach ($data as $key => $value) {
$sanitized_data[ $key ] = (int)strip_tags( stripslashes( $value ) );
}
update_post_meta( $post_id, '_speaker_ids', $sanitized_data );
}
}
//save
add_action('save_post','palinsesto_box_save');
function palinsesto_box_save($post_id){
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ($_POST && wp_verify_nonce($_POST['palinsesto_nonce'], __FILE__) ) {
if( isset( $_POST['giorno'] ) )
update_post_meta( $post_id, 'giorno', esc_attr( $_POST['giorno'] ) );
if( isset( $_POST['ora'] ) )
update_post_meta( $post_id, 'ora', esc_attr( $_POST['ora'] ) );
}}

Woocommerce, sort dropdown on shortcode based product lists

In our shop, we have a number of standard WP pages. On these pages we show ~40 products using the standard Woocommerce shortcodes.
For example:
[product_category category="boots" per_page="20" columns="4" orderby="price" order="desc"]
The products appears, but there are two things missing:
No sorting dropdown appears above the product lists, so the products cannot be sorted by our visitors.
We don't see any pagination buttons, so it's impossible to see more than the first 20 products on each page.
Any ideas how we can fix those two things?
Regarding your first issue, I have not found any good solutions beside hacking the shortcode within WC. Not entirely advisable as it will be overwritten each upgrade/patch of WC. If it's absolutely necessary, you could maintain the code by rewriting the hack each time you upgrade.
Alright, first download a copy of includes\class-wc-shortcodes.php in your woocommerce folder. Make a backup of the original before editing it, I usually rename the file with a -o or change the file type to .bak.
Assuming you'd want the original sort by dropdown that comes with WC on the Shop Page.
Step 1
Remove orderby and order arguments on the shortcode:
[product_category category="boots" per_page="20" columns="4"]
Step 2
Edit the Product Category shortcode on class-wc-shortcodes.php as such:
/**
* List products in a category shortcode
*
* #access public
* #param array $atts
* #return string
*/
public static function product_category( $atts ) {
global $woocommerce_loop, $wpdb;
if ( empty( $atts ) ) return '';
extract( shortcode_atts( array(
'per_page' => '12',
'columns' => '4',
'orderby' => 'title',
'order' => 'asc',
'category' => '',
'operator' => 'IN' // Possible values are 'IN', 'NOT IN', 'AND'.
), $atts ) );
if ( ! $category ) return '';
// Default ordering args
// $ordering_args = WC()->query->get_catalog_ordering_args( $orderby, $order ); // COMMENT THIS OUT
$orderby = 'title';
$order = 'asc';
if ( isset( $_GET['orderby'] ) ) {
$getorderby = $_GET['orderby'];
}
if ($getorderby == 'popularity') {
$orderby = 'meta_value_num';
$order = 'desc';
$meta_key = 'total_sales';
} elseif ($getorderby == 'rating') {
$fields .= ", AVG( $wpdb->commentmeta.meta_value ) as average_rating ";
$where .= " AND ( $wpdb->commentmeta.meta_key = 'rating' OR $wpdb->commentmeta.meta_key IS null ) ";
$join .= "
LEFT OUTER JOIN $wpdb->comments ON($wpdb->posts.ID = $wpdb->comments.comment_post_ID)
LEFT JOIN $wpdb->commentmeta ON($wpdb->comments.comment_ID = $wpdb->commentmeta.comment_id)
";
$orderby = "average_rating DESC, $wpdb->posts.post_date DESC";
$groupby = "$wpdb->posts.ID";
} elseif ($getorderby == 'date') {
$orderby = 'date';
$order = 'desc';
} elseif ($getorderby == 'price') {
$orderby = 'meta_value_num';
$order = 'asc';
$meta_key = '_price';
} elseif ($getorderby == 'price-desc') {
$orderby = 'meta_value_num';
$order = 'desc';
$meta_key = '_price';
}
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'ignore_sticky_posts' => 1,
'orderby' => $orderby, // $ordering_args['orderby'],
'order' => $order, // $ordering_args['order'],
'meta_key' => $meta_key,
'fields' => $fields,
'where' => $where,
'join' => $join,
'groupby' => $groupby,
'posts_per_page' => $per_page,
'meta_query' => array(
array(
'key' => '_visibility',
'value' => array('catalog', 'visible'),
'compare' => 'IN'
)
),
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'terms' => array( esc_attr( $category ) ),
'field' => 'slug',
'operator' => $operator
)
)
);
if ( isset( $ordering_args['meta_key'] ) ) {
$args['meta_key'] = $ordering_args['meta_key'];
}
ob_start();
$products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $args, $atts ) );
$woocommerce_loop['columns'] = $columns;
if ( $products->have_posts() ) : ?>
<div style="width:100%;">
<div style="float:right">
<form class="woocommerce-ordering" method="get">
<select name="orderby" class="orderby">
<?php
$catalog_orderby = apply_filters( 'woocommerce_catalog_orderby', array(
'menu_order' => __( 'Default sorting', 'woocommerce' ),
'popularity' => __( 'Sort by popularity', 'woocommerce' ),
'rating' => __( 'Sort by average rating', 'woocommerce' ),
'date' => __( 'Sort by newness', 'woocommerce' ),
'price' => __( 'Sort by price: low to high', 'woocommerce' ),
'price-desc' => __( 'Sort by price: high to low', 'woocommerce' )
) );
if ( get_option( 'woocommerce_enable_review_rating' ) === 'no' )
unset( $catalog_orderby['rating'] );
foreach ( $catalog_orderby as $id => $name )
echo '<option value="' . esc_attr( $id ) . '" ' . selected( $getorderby, $id, false ) . '>' . esc_attr( $name ) . '</option>';
?>
</select>
<?php
// Keep query string vars intact
foreach ( $_GET as $key => $val ) {
if ( 'orderby' === $key || 'submit' === $key )
continue;
if ( is_array( $val ) ) {
foreach( $val as $innerVal ) {
echo '<input type="hidden" name="' . esc_attr( $key ) . '[]" value="' . esc_attr( $innerVal ) . '" />';
}
} else {
echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $val ) . '" />';
}
}
?>
</form>
</div>
</div>
<div style="clear:both;"></div>
<?php woocommerce_product_loop_start(); ?>
<?php while ( $products->have_posts() ) : $products->the_post(); ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
<?php endif;
woocommerce_reset_loop();
wp_reset_postdata();
return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
}
Upload the file back into the includes folder and you're done! Your shortcode product pages will now have a working sort by dropdown same as the one that appears on the WC Shop Page.
Edit the sort options to your liking! Hope it helps!
Well for your second problem: Your shortcode is limiting to see only 20 products. Change the it to per_page="40" and you should see 40 products or simply remove the line and the number of products is not limited.
For your first problem I don't have an answer. I'm looking it for my self as well :).
If you add the paginate="true" attribute to your [products] shortcode, then the shortcode, then the Sort by dropdown menu will appear on the page.
Change this
[product_category category="boots" per_page="20" columns="4"]
to this
[product_category category="boots" paginate="true" limit="20" columns="4"]

Resources