skip to Main Content

I created a custom field for my products using this tutorial, but I need to set a default value for this field.
I have already created hundreds of products and I need to have this field updated at those as well. I’m then using this value to order the products.

Here is the whole code:

// 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' => 'priority',
                'placeholder' => 'Priority of the product - values a>b',
                'label' => __('Priority of the product', 'woocommerce'),
                'desc_tip' => 'true',
                //'default' => '0',
            )
        );
        echo '</div>';
    }

    function woocommerce_product_custom_fields_save($post_id)
    {
        // Custom Product Text Field
        $woocommerce_custom_product_text_field = $_POST['priority'];
        if (!empty($woocommerce_custom_product_text_field))
            update_post_meta($post_id, 'priority', esc_attr($woocommerce_custom_product_text_field));
    }

    function cw_add_postmeta_ordering_args( $args_sort_cw ) {
      $cw_orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) :
            apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
      switch( $cw_orderby_value ) {
           case 'priority':
                $args_sort_cw['orderby'] = 'meta_value';
                $args_sort_cw['order'] = 'asc';
                $args_sort_cw['meta_key'] = 'priority';
                break;
      }
      return $args_sort_cw;
    }
    add_filter( 'woocommerce_get_catalog_ordering_args', 'cw_add_postmeta_ordering_args' );
    function cw_add_new_postmeta_orderby( $sortby ) {
       $sortby['priority'] = __( 'Recommended', 'woocommerce' );
       return $sortby;
    }
    add_filter( 'woocommerce_default_catalog_orderby_options', 'cw_add_new_postmeta_orderby' );
    add_filter( 'woocommerce_catalog_orderby', 'cw_add_new_postmeta_orderby' );

I could’t find a working solution, so I’m kindly asking you for an advice. What I expect is that every existing product will have this value set and when creating a new one the default value will be displayed. Then it should be sorted according to this value. Thanks for your help!

Edit according to the first answer:
The data does’t update in the database. In the front-end I can only see the products I have manually altered and not those to which the 0 was added using this function. When I try to change the altered value back to 0, it is not updated. Actually I just need a function which would refresh all the products so that the value is stored to the database.

2

Answers


  1. Chosen as BEST ANSWER

    This is the solution which worked for me.

    // 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, $product_object;
            $value = $product_object->get_meta( 'priority', true );
    
            if ( ! $value ) {
                $value = 0;
            }
            
            echo '<div class="product_custom_field">';
            // Custom Product Text Field
            woocommerce_wp_text_input(
                array(
                    'id' => 'priority',
                    'placeholder' => 'Priority - number 1>0',
                    'label' => __('Priority', 'woocommerce'),
                    'type' => 'number',
                    'desc_tip' => 'true',
                    'value' => $value
                )
            );
            echo '</div>';
        }
    
        function woocommerce_product_custom_fields_save($post_id)
        {
            // Custom Product Text Field
            if (array_key_exists('priority', $_POST)) {
                update_post_meta($post_id, 'priority', intval($_POST['priority']));
            }
        }
    
        function cw_add_postmeta_ordering_args( $args_sort_cw ) {
          $cw_orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) :
                apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
          switch( $cw_orderby_value ) {
               case 'priority':
                    $args_sort_cw['orderby'] = 'meta_value';
                    $args_sort_cw['order'] = 'desc';
                    $args_sort_cw['meta_key'] = 'priority';
                    break;
          }
          return $args_sort_cw;
        }
        add_filter( 'woocommerce_get_catalog_ordering_args', 'cw_add_postmeta_ordering_args' );
        function cw_add_new_postmeta_orderby( $sortby ) {
           $sortby['priority'] = __( 'Recommended', 'woocommerce' );
           return $sortby;
        }
        add_filter( 'woocommerce_default_catalog_orderby_options', 'cw_add_new_postmeta_orderby' );
        add_filter( 'woocommerce_catalog_orderby', 'cw_add_new_postmeta_orderby' );
    

    I adjusted the woocommerce_product_custom_fields_save() function with array_key_exists() and it works fine now. Thanks helgatheviking for help!


  2. What I would do is use the value argument in the woocommerce_wp_text_input parameters. You can then pass it the current value OR a default if nothing exists yet.

    Also added new save routine via woocommerce_admin_process_product_object

    // Display Fields
    add_action('woocommerce_product_options_general_product_data', 'so_63588126_product_custom_fields');
    // Save Fields
    add_action('woocommerce_admin_process_product_object', 'so_63588126_product_custom_fields_save');
    
    
    function so_63588126_product_custom_fields()
    {
        global $product_object;
    
        $value = $product_object->get_meta( 'weight', true );
    
        if ( ! $value ) {
            $value = 0;
        }
    
        echo '<div class="product_custom_field">';
        // Custom Product Text Field
        woocommerce_wp_text_input(
            array(
                'id' => 'weight',
                'placeholder' => 'Weight of the product - values a>b',
                'label' => __('Weight of the product', 'your-textdomain'),
                'desc_tip' => 'true',
                'value' => $value 
            )
        );
        echo '</div>';
    }
    
    function so_63588126_product_custom_fields_save( $product )
    {
        // Custom Product Text Field
        $woocommerce_custom_product_text_field = $_POST['weight'];
        if ( ! empty( $_POST['weight'] ) ) {
            $product->update_meta_data( 'weight', sanitize_text_field( wp_unslash( $_POST['weight'] ) ) );
        } else {
            $product->update_meta_data( 'weight', 0 );
        }
    
    }
    

    Additional explanation:

    I used $product_object->update_meta_data() as WooCommerce (since 3.0) prefers to use CRUD (create, read, update, delete) methods on objects. update_post_meta() does still work, but CRUD will be future-proof if/when Woo ever decides to use custom tables for products and product meta.

    Read more about CRUD: https://docs.woocommerce.com/document/developing-using-woocommerce-crud-objects/

    And regarding text domains… This is custom code so in order for it to be properly translated you would need to use your own unique text domain that is not ‘woocommerce’.

    Read more about text domains: https://developer.wordpress.org/themes/functionality/internationalization/#text-domain

    Finally, sanitize_text_field() may not be the right choice for sanitizing, but I didn’t know what kind of data you were storing there. intval() would be better for numbers… and so would setting the input to be a numerical input type by setting the type parameter to 'number' in the woocommerce_wp_text_input() args.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search