Add custom product fields to WooCommerce - php

In the past, I've added custom fields to my products in WooCommerce. This was only visible at the back and not directly visible on the front end.
Now I can't get it done in any way. When I work with plugins, this only works on the product page as a selection. But I would like to configure it on the product page in the back for example after the regular price field (see example).
I'm looking for the right hooks to do this. Anyone have an idea where I can find this?

add_action('woocommerce_product_options_pricing', 'add_custom_fields_to_poduct_general');
function add_custom_fields_to_poduct_general() {
global $woocommerce, $post;
woocommerce_wp_text_input(
array(
'id' => '_custom_text',
'value' => get_post_meta($post->ID, '_custom_text', true),
'label' => __('Custom text', 'woocommerce'),
)
);
}
Add more fields after price using the hook woocommerce_product_options_pricing
add_action('woocommerce_process_product_meta', 'save_custom_product_field');
function save_custom_product_field($post_id) {
$key = '_custom_text';
$value = (!empty($_POST[$key]) ? wc_clean(wp_unslash($_POST[$key])) : '' ); // phpcs:ignore WordPress.Security.NonceVerification
if ($value) {
update_post_meta($post_id, $key, $value);
} else {
delete_post_meta($post_id, $key);
}
}
The hook woocommerce_process_product_meta is used to save the data added using the above hook

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.

Set a custom product field programmatically using a method in Woocommerce

I'm trying to add a custom field in the general section of a product and initialize it with a frontend form.
I had no problem in adding it, but I'm little lost on how to set it.
TO ADD AND SAVE THE CUSTOM FIELD:
// The code for displaying WooCommerce Product Custom Fields
add_action('woocommerce_product_options_general_product_data', 'woocommerce_product_custom_fields');
// Following code Saves WooCommerce Product Custom 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' => 'tipologiaAppunto',
'label' => __('Tipologia appunto:', 'woocommerce'),
'placeholder' => '',
'desc_tip' => 'true'
)
);
echo '</div>';
}
function woocommerce_product_custom_fields_save($post_id)
{
// Custom Product Text Field
$woocommerce_custom_product_text_field = $_POST['tipologiaAppunto'];
if (!empty($woocommerce_custom_product_text_field))
update_post_meta($post_id, 'tipologiaAppunto', esc_attr($woocommerce_custom_product_text_field));
}
To set it I've tried to extend the WC_PRODUCT CLASS
EXTENSION OF THE WC_PRODUCT CLASS:
add_action('init', 'register_myclass');
function register_myclass()
{
class WC_ProductExtended extends WC_Product
{
function __construct() {
parent::__construct();
if (!array_key_exists("tipologiaAppunto", $this->data)) {
$this->data["tipologiaAppunto"] = "";
}
}
/**
* Set product tipologiaAppunto.
*
* #since 3.0.0
* #param string $tipologiaAppunto Product tipologiaAppunto.
*/
public function set_tipologiaAppunto($tipologiaAppunto)
{
$this->set_prop( 'tipologiaAppunto', $tipologiaAppunto );
}
}
}
And now by calling the setter I was hoping to initialize the product custom field, but nothing happened.
$product->set_regular_price($_POST['price']);
$productExtendend = new WC_ProductExtended();
$productExtendend->set_tipologiaAppunto("Hey");
$productExtendend->save();
I don't know If this is the right I way, I found a lot of tutorial on how to add the custom field but so little on how to initialize it from the frontend, I've tried by mimic the behaviour of the existing fields but with no luck.
Why you don't simply use WC_Data update_meta_data() and get_meta() methods as follow:
$product->set_regular_price($_POST['price']);
$product->update_meta_data("tipologiaAppunto", "Hey"); // <== Set (or update) the custom field value from a meta key
$product->save();
echo $product->get_meta("tipologiaAppunto"); // <== Get (or read) the custom field value from a meta key
Also since Woocommerce 3, you can replace woocommerce_process_product_meta action hook, by woocommerce_admin_process_product_object so your code will be instead:
// Display admin product custom setting field(s)
add_action('woocommerce_product_options_general_product_data', 'woocommerce_product_custom_fields');
function woocommerce_product_custom_fields() {
global $product_object;
echo '<div class=" product_custom_field ">';
// Custom Product Text Field
woocommerce_wp_text_input( array(
'id' => 'tipologiaAppunto',
'label' => __('Tipologia appunto:', 'woocommerce'),
'placeholder' => '',
'desc_tip' => 'true' // <== Not needed as you don't use a description
) );
echo '</div>';
}
// Save admin product custom setting field(s) values
add_action('woocommerce_admin_process_product_object', 'woocommerce_product_custom_fields_save');
function woocommerce_product_custom_fields_save( $product ) {
if ( isset($_POST['tipologiaAppunto']) ) {
$product->update_meta_data( 'tipologiaAppunto', sanitize_text_field( $_POST['tipologiaAppunto'] ) );
}
}

Add a field to coupon settings and display the value on Woocommerce admin order list

I am having some really hard times trying to make it work.
I've had an idea in back of my head to:
be able to assign single user to a coupon code through an extra field in general coupon tab, which is listing unassigned users to coupon codes
I dont want to use third party extensions, custom-fields, etc. I was hoping I'll be able to do it through meta data but I failed. Not sure how to get it done properly.
add two extra columns on orders page and display both coupon code and user assigned to it.
After some time reading docs and xDebugging in phpstorm I have also failed to get it done.
function order_sellers_and_coupons_columns_values($column)
{
global $post, $the_order;
if ($column == 'order_coupon_code') {
$coupons = $the_order->get_used_coupons(); // not sure how to get coupon object by the coupon code
echo (count($coupons)) ? $coupons[0] : '';
}
}
// even though I see the order objects have an items and coupon lines property,
// which is an object, i can't get access to it
$the_order->items["coupon_lines"]
I am not asking for ready-to-go solution, but to show me the way how to get it done.
Thanks in advance for any kind of help.
In WooCommerce admin single coupon pages, we add an extra field for the seller (dealer):
// Add a custom field to Admin coupon settings pages
add_action( 'woocommerce_coupon_options', 'add_coupon_text_field', 10 );
function add_coupon_text_field() {
woocommerce_wp_text_input( array(
'id' => 'seller_id',
'label' => __( 'Assing a seller (dealer)', 'woocommerce' ),
'placeholder' => '',
'description' => __( 'Assign a seller / dealer to a coupon', 'woocommerce' ),
'desc_tip' => true,
) );
}
// Save the custom field value from Admin coupon settings pages
add_action( 'woocommerce_coupon_options_save', 'save_coupon_text_field', 10, 2 );
function save_coupon_text_field( $post_id, $coupon ) {
if( isset( $_POST['seller_id'] ) ) {
$coupon->update_meta_data( 'seller_id', sanitize_text_field( $_POST['seller_id'] ) );
$coupon->save();
}
}
Then using the following you will add to admin orders list the coupon code (when it's used in the order) with the seller / dealer name:
// Adding a new column to admin orders list
add_filter( 'manage_edit-shop_order_columns', 'custom_shop_order_column' );
function custom_shop_order_column($columns)
{
$reordered_columns = array();
// Inserting columns to a specific location
foreach( $columns as $key => $column){
$reordered_columns[$key] = $column;
if( $key == 'order_status' ){
// Inserting after "Status" column
$reordered_columns['coupons'] = __( 'Coupon','theme_domain');
}
}
return $reordered_columns;
}
// Adding used coupon codes
add_action( 'manage_shop_order_posts_custom_column' , 'custom_orders_list_column_content', 10, 2 );
function custom_orders_list_column_content( $column, $post_id )
{
global $the_order;
if ( $column == 'coupons' ) {
$coupons = (array) $the_order->get_used_coupons();
$dealers = [];
foreach( $coupons as $coupon_code ) {
$coupon = new WC_Coupon( $coupon_code );
$dealers[] = $coupon->get_meta('seller_id');
}
if( count($coupons) > 0 )
echo implode( ', ', $coupons );
if( count($dealers) > 0 )
echo '<br><small>(' . implode( ', ', $dealers ) . ')</small>';
}
}
All code goes in functions.php file of your active child theme (or active theme). Tested and works.
On Admin coupon single pages:
On Admin edit orders list:

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']));
}
}

WordPress - Update permalink automatically after posting an update

I am calculating custom title for a product using WooCommerce add product page. After the user post product's information, title is generated and saved by a save_post filter hook.
add_filter('save_post', 'modify_post_title', '99', 1);
function modify_post_title($post_id)
{
// some logic to form a new $title
// ...
if (!empty($title)) {
// update the title in database
$wpdb->update($wpdb->posts, array('post_title' => $title), array('ID' => $post_id));
// UPDATE PERMALINK
}
}
I need to know what function to use to re-generate the permalink after updating title.
Thanks in advance
add_filter( 'wp_insert_post_data', 'custom_slug_change', 50, 2 );
function custom_slug_change( $data, $postarr ) {
//Check for the post statuses you want to avoid
if ( !in_array( $data['post_status'], array( 'draft', 'pending', 'auto-draft' ) ) ) {
$data['post_name'] = sanitize_title( $data['post_title'] );
}
return $data;
}
Would you please add above code in your functions.php ?
I think you can go with the window.history.pushState to maipulate the Browser History.
I think these may help you.
window.history.pushState("object or string", "Title", surl[0]);

Categories