Adding a hidden checkout field in WooCommerce? - php

I want to include a link to a profile of the current user who submitted a checkout form through WooCommerce.
That is, to place automatically a current user’s author link like this in the hidden field: example.com/author/username
I want to achieve this by adding a hidden field in checkout form. So to get a link I would write something likes this:
<?php
$currentUser = get_current_user_id();
$user = get_user_by( 'id', $currentUser );
$userUrl = get_bloginfo( 'home' ) . '/author/' . $user->user_login;
echo $userUrl;
?>
My question is how can I create this type of hidden field in checkout form?

With a custom function hooked in woocommerce_after_order_notes action hook, you can also directly output a hidden field with this user "author link" as a hidden value, that will be submitted at the same time with all checkout fields when customer will place the order.
Here is that code:
add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_hidden_field', 10, 1 );
function my_custom_checkout_hidden_field( $checkout ) {
// Get an instance of the current user object
$user = wp_get_current_user();
// The user link
$user_link = home_url( '/author/' . $user->user_login );
// Output the hidden link
echo '<div id="user_link_hidden_checkout_field">
<input type="hidden" class="input-hidden" name="user_link" id="user_link" value="' . $user_link . '">
</div>';
}
Then you will need to save this hidden field in the order, this way:
add_action( 'woocommerce_checkout_update_order_meta', 'save_custom_checkout_hidden_field', 10, 1 );
function save_custom_checkout_hidden_field( $order_id ) {
if ( ! empty( $_POST['user_link'] ) )
update_post_meta( $order_id, '_user_link', sanitize_text_field( $_POST['user_link'] ) );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
The code is tested and working

Add this to your functions.php file (or a plugin file,etc.)
add_action( 'woocommerce_after_order_notes', 'hidden_author_field' );
function hidden_author_field( $checkout ) {
$currentUser = get_current_user_id();
$user = get_user_by( 'id', $currentUser );
$userUrl = get_bloginfo('home').'/author/'.$user->user_login;
woocommerce_form_field( 'hidden_author', array(
'type' => 'hidden',
'class' => array('hidden form-row-wide'),
), $userUrl);
}
This code is untested, more reading here https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/ and here http://woocommerce.wp-a2z.org/oik_api/woocommerce_form_field/. Please let me know if this worked for you and if not what the problem is.

Related

Allow a custom field value to be removable in WooCommerce

I added a custom subtitle field for woo-commerce products. When I fill its field from the dashboard it appears in the product. I can update the text but I can't remove its value it appears again when I update the product.
Here the code. I copied from somewhere
<?php
// Display Fields
add_action('woocommerce_product_options_general_product_data',
'woocommerce_product_custom_fields');
// Save Fields
add_action('woocommerce_process_product_meta', 'woocommerce_product_custom_fields_save');
function woocommerce_product_custom_fields()
{
global $woocommerce, $post;
echo '<div class="product_custom_field">';
// Custom Product Text Field
woocommerce_wp_text_input(
array(
'id' => '_custom_product_subtitle',
'placeholder' => 'Custom Product Subtitle',
'label' => __('Custom Product Subtitle', 'woocommerce'),
'desc_tip' => 'true'
)
);
}
function woocommerce_product_custom_fields_save($post_id)
{
// Custom Product Text Field
$woocommerce_custom_product_text_field = $_POST['_custom_product_subtitle'];
if (!empty($woocommerce_custom_product_text_field))
update_post_meta($post_id, '_custom_product_subtitle',
esc_attr($woocommerce_custom_product_text_field));
}
// To show after the title
add_action( 'woocommerce_after_shop_loop_item_title', 'custom_field_display_below_title', 2 );
function custom_field_display_below_title(){
global $product;
// Get the custom field value
$custom_field = get_post_meta( $product->get_id(), '_custom_product_subtitle', true );
// Display
if( ! empty($custom_field) ){
echo '<p class="custom-product-subtitle">'.$custom_field.'</p>';
}
}
This is the result of the code, it also displays where I want to, but I can't make remove the text it appears again when I update
To be able to reset (empty) this custom field, just replace the code line (from your 2nd function):
if( ! empty($woocommerce_custom_product_text_field) ){
by:
if( isset($woocommerce_custom_product_text_field) ){
So now you can remove the field value and save it.
Now since WooCommerce 3, your code is a bit outdated… Also, you should use shorter keys and variable names.
Below is your revisited code (changed the field meta key from '_custom_product_subtitle' to simply '_subtitle', replaced a hook and made some other changes).
// Display a text Field (admin single product)
add_action( 'woocommerce_product_options_general_product_data', 'display_admin_product_custom_text_field' );
function woocommerce_product_custom_fields() {
echo '<div class="product_custom_field">';
woocommerce_wp_text_input( array(
'id' => '_subtitle',
'label' => __('Custom subtitle', 'woocommerce'),
'placeholder' => __('You can add optionally a custom subtitle', 'woocommerce'),
'desc_tip' => 'true'
) );
echo '</div>'; // <== missing
}
// Save Text Field value (admin)
add_action( 'woocommerce_admin_process_product_object', 'save_admin_product_custom_text_field_value' );
function save_admin_product_custom_text_field_value( $product ) {
if ( isset($_POST['_subtitle']) ) {
$product->update_meta_data( '_subtitle', sanitize_text_field($_POST['_subtitle']) );
}
}
// Display product subtitle (front end)
add_action( 'woocommerce_after_shop_loop_item_title', 'custom_field_display_below_title', 2 );
function custom_field_display_below_title(){
global $product;
$value = $product->get_meta('_subtitle'); // Get the custom field value
if( ! empty($value) ){
echo '<p class="product-subtitle">' . $value . '</p>'; // Display
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

How to display custom product field on WooCommerce checkout page?

I'm trying to display custom product field checkout_name on the checkout page but I can't seem to figure out how. I'm following checkout hooks visual guide from here.
add_action( 'woocommerce_checkout_before_customer_details', 'custom_before_checkout_form', 10 );
function custom_before_checkout_form( $cart_data ){
$meta_key = 'checkout_name';
$product_id = $cart_item['product_id'];
$meta_value = get_post_meta( $product_id, $meta_key, true );
if( !empty( $cart_data ) )
$custom_items = $cart_data;
if( !empty($meta_value) ) {
$custom_items[] = array(
'key' => __('Store Name', 'woocommerce'),
'value' => $meta_value,
'display' => $meta_value,
);
}
return $custom_items;
}
Custom checkout fields need to be inside the checkout form. If not the field values are not posted on submission.
There is also some errors in your code. Try the following instead using a hook located inside the checkout form, just before billing fields (assuming that the custom product field checkout_name exist).
add_action( 'woocommerce_checkout_before_customer_details', 'custom_before_checkout_form' );
function custom_before_checkout_form(){
// Loop though cart items
foreach ( WC()->cart->get_cart() as $item ) {
// Get the WC_Product Object
$product = $item['data'];
echo '<div align="center">' . $product->get_meta( 'checkout_name' ) . '</div><br>';
}
}
Code goes in functions.php file of your active child theme (or active theme). It should better work.

Adding custom field through functions.php

I'm trying to add a custom field just below the price in my Woocommerce theme. I was able to add simple html by using:
add_action( 'woocommerce_before_add_to_cart_form', 'SomeName' );
function SomeName() {
echo '<p>Some Text Here</p>';
}
But what I want to do is add a custom field key instead. I'm using this code for placing custom fields:
<?php
$naslov = get_post_meta($post->ID, 'Naslov', true);
if ($naslov) { ?>
<h2 class="single-naslov-kat"><? echo $naslov; ?></h2>
<?php
} else {
// do nothing;
}
?>
The code works great when I add it to content-single-product.php theme file. But I can't add it below the price through that file. And I have no idea how to incorporate it through functions.php.
If you have any other suggestions on how I might be able to add custom text below the price for each specific product that's ok too.
Any help would be greatly appreciated.
In your themes functions.php add the code,
//create custom field
function cfwc_create_custom_field() {
$args = array(
'id' => 'custom_field',
'label' => __( 'Custom Field', 'cfwc' ),
'class' => 'cfwc-custom-field',
'desc_tip' => true,
'description' => __( 'Enter Custom Field Description.', 'ctwc' ),
);
woocommerce_wp_text_input( $args );
}
add_action( 'woocommerce_product_options_general_product_data', 'cfwc_create_custom_field' );
// save custom field
function cfwc_save_custom_field( $post_id ) {
$link = wc_get_product( $post_id );
$title = isset( $_POST['custom_field'] ) ? $_POST['custom_field'] : '';
$link->update_meta_data( 'custom_field', sanitize_text_field( $title ) );
$link->save();
}
add_action( 'woocommerce_process_product_meta', 'cfwc_save_custom_field' );
// display custom field in single.php page
add_action('woocommerce_before_add_to_cart_form','cmk_additional_button');
function cmk_additional_button() {
global $product;
$custom_field = $product->get_meta('custom_field');
if(!empty($custom_field)) {
echo "<a href='$custom_field' target='_blank'><button type='button' class='button alt'>Custom Field</button></a>";
}
}

Add a custom order note programmatically in Woocommerce admin order edit pages

In woocommerce I am trying to add a custom order note in the admin order edit pages through php (so programmatically). I haven't find the way yet.
Any help will be appreciated.
From a dynamic Order Id you can use WC_Order add_order_note() method this way:
// If you don't have the WC_Order object (from a dynamic $order_id)
$order = wc_get_order( $order_id );
// The text for the note
$note = __("This is my note's text…");
// Add the note
$order->add_order_note( $note );
Tested and works.
Thank you guys I was trying to find a way to add the notes to a new order. I was looking for the right hook using the solution that #LoicTheAztec posted. This is the solution that worked for me hope it helps someone else out there.
add this to the Functions.php file
add_action( 'woocommerce_new_order', 'add_engraving_notes', 1, 1 );
function add_engraving_notes( $order_id ) {
//note this line is different
//because I already have the ID from the hook I am using.
$order = new WC_Order( $order_id );
// The text for the note
$note = __("Custom Order Note Here");
// Add the note
$order->add_order_note( $note );
}
This code will do trick for you add code in functions.php
<?php
add_action('woocommerce_after_order_notes', 'customise_checkout_field');
function customise_checkout_field($checkout)
{
echo '<div id="customise_checkout_field"><h2>' . __('Heading') . '</h2>';
woocommerce_form_field('customised_field_name', array(
'type' => 'text',
'class' => array(
'my-field-class form-row-wide'
) ,
'label' => __('Customise Additional Field') ,
'placeholder' => __('Guidence') ,
'required' => true,
) , $checkout->get_value('customised_field_name'));
echo '</div>';
}
For data validation of the custom field use the code given below:
add_action('woocommerce_checkout_process', 'customise_checkout_field_process');
function customise_checkout_field_process()
{
// if the field is set, if not then show an error message.
if (!$_POST['customised_field_name']) wc_add_notice(__('Please enter value.') , 'error');
}
Update value of field
add_action('woocommerce_checkout_update_order_meta', 'customise_checkout_field_update_order_meta');
function customise_checkout_field_update_order_meta($order_id)
{
if (!empty($_POST['customised_field_name'])) {
update_post_meta($order_id, 'Some Field', sanitize_text_field($_POST['customised_field_name']));
}
}

Make specific woocommerce billing fields hidden

I have an url to woocommerce checkout, with variables to put into the billing fields automatically, so they should not be shown at the checkout page.
How can we do so?
Adding type="hidden" to the input fields?
Thanks.
We should minimize "user involvement" as much as we can (removing type=hidden is a very easy thing to do), so if you have data that should be automatically added, I would advise you to disable those fields completely and insert data via WooCommerce filters.
1. Remove fields you want to hide
First filter that you need is woocommerce_billing_fields. With that filter, you can remove or add fields. It accepts one argument, and that's array of billing fields. For example:
/**
* Used to remove WooCommerce billing fields
*
* #param array $fields
*
* #return array Modified billing fields
*/
function so_remove_billing_fields( $fields ){
// FYI: These are all default WooCommerce billing fields
// (remove those which need to stay)
$fields_to_remove = array(
'billing_first_name',
'billing_last_name',
'billing_company',
'billing_address_1',
'billing_address_2',
'billing_city',
'billing_postcode',
'billing_country',
'billing_state',
'billing_email',
'billing_phone',
);
foreach( $fields_to_remove as $field ){
unset( $fields[$field] );
}
return $fields;
}
add_filter( 'woocommerce_billing_fields', 'so_remove_billing_fields' );
2. Add data that should be saved
We should now save the custom data to the post (order) meta, and for that, we will use woocommerce_checkout_update_order_meta filter. It has one argument, and that is integer order ID. For example:
/**
* Save custom data to the database
*
* #param int $order_id
*
* #return void
*/
function so_add_billing_fields_data( $order_id ){
$data_to_add = array(
'field_name' => apply_filters( 'so_custom_field_name_data', null ),
);
foreach( $data_to_add as $field_name => $data ){
if ( ! empty( $data ) )
update_post_meta( $order_id, $field_name, sanitize_text_field( $data ) );
}
}
add_filter( 'woocommerce_checkout_update_order_meta', 'so_add_billing_fields_data' );
Maybe sanitize_text_field() was not necessary here, but better safe than sorry. I don't know the source of your data. ;)
By the way, I opted for apply_filters in this example to add data to the array, but if you can also gather data in this function and put it into a variable.
See more: WooCommerce: Customizing checkout fields | WordPress: Filter API Reference | Validating Sanitizing and Escaping User Data
Yes, they are telling you, there's no type hidden on billing fields.
But there's room for it if you'll create one.
something like this would do.
1. First, let's change the field type to hidden depending on what is passed on the url.
function woocommerce_billing_fields( $fields ){
// let's not do anything if not on checkout page.
if ( !is_checkout() ) return $fields;
// these are expected fields.
// please remove those that are not needed.
$url_param_fields = array(
'first_name',
'last_name',
'company',
'address_1',
'address_2',
'city',
'postcode',
'country',
'state',
'email',
'phone',
);
foreach( $url_param_fields as $param ){
$billing_key = 'billing_' . $param;
if ( isset( $_GET[$param] ) && array_key_exists( $billing_key, $fields) ) {
$fields[$billing_key]['type'] = 'hidden'; // let's change the type of this to hidden.
$fields[$billing_key]['default'] = $_GET[$param]; // you need to sanitized $_GET[$param] here.
}
}
return $fields;
}
add_filter( 'woocommerce_billing_fields', 'woocommerce_billing_fields' );
2. Of course there's no type hidden as for the default WooCommerce.
But below code will create it.
function woocommerce_form_field_hidden( $field, $key, $args ){
$field = '<input type="hidden" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" value="' . esc_attr( $args['default'] ) . '" />';
return $field;
}
add_filter( 'woocommerce_form_field_hidden', 'woocommerce_form_field_hidden', 10, 3 );
The expected url would then be something like http://reigelgallarde.me/checkout/?company=reigelgallarde.me. In this case the billing company field will be change to something like
<input type="hidden" name="billing_company" id="billing_company" value="reigelgallarde.me">

Categories