Support

Account

Home Forums Backend Issues (wp-admin) Restrict meta value to only be assigned once

Solved

Restrict meta value to only be assigned once

  • Hi All,

    I am trying to work out how I can restrict a meta value to being assigned only once to a post type.

    For example, let’s say I have 10 posts, I then have a numeric meta value (called order) ranging from 1 – 10. I would then assign each post a value from 1-10.

    I would be using these meta values to allow for custom ordering in WP_QUERY.

    This works fine, but the problem is that a meta value (say ‘1’) can be assigned more than once to any post, meaning that all 10 posts could have a value of 5 etc. This would obviously cause the order system to not work as desired.

    I am trying to restrict the back end user to only being able to select one meta value per post.

    I have searched through the documentation but unfortunately, I still cannot work it out.

    Can anybody point me in the right direction? it would be greatly appreciated!

    Kind regards,

    Tom

  • I covered a way to validate an acf field to only accept unique values here https://support.advancedcustomfields.com/forums/topic/accept-only-unique-values/. let me know if you have any questions

  • Great John thanks for the link!

    Looks like this could point me in the right direction..

    My situation is slightly more complex as I need prevent duplicate values only in posts that share a taxonomy.

    For example, let’s say my CPT is called ‘knowledge base’ and I have a custom taxonomy called ‘topics’ with 5 terms ‘topic A, topic B, topic C, topic D, topic E,’.

    I also have a numeric meta key called ‘top_four’, this determines the order of the top four post links displayed under the term name (the remaining posts are hidden via a read more button). So, with 5 terms I would need to apply the meta value of ‘1’ five times (each per taxonomy term), along with values 2,3 and 4.

    You can see where my challenge starts to occur as the meta value needs to be duplicated 5 times in CPT, but only should be allowed to be used once within its term.

    I am wondering if I can use a loop to apply the rule you outlined in your other post on a per term basis, maybe a foreach loop that applies the rule.

    Thanks once again John

  • In the last function there is a query that checks to see if there is an existing post with a value. You should be able to modify that query to include a tax_query. The problem here is that ACF will not pass the taxonomy/term value for the post during the validation AJAX request unless there is a taxonomy field that is part of the field group.

  • Ah thanks John that makes sense,

    I will try and add a tax_query into the query and switch taxonomy/term value to belong to a field in the field group.

    FYI – The first section of your code in that posts caused a syntax error, heres the adjusted code that resovles the error.

    add_filter('acf/load_field/name=hidden_post_id', 'make_hidden_post_id_readonly');
    function make_field_readonly($field) {
      // sets readonly attribute for field
      $field['readonly'] = 1;
      return field;
    }
    add_filter('acf/load_value/name=hidden_post_id', 'set_hidden_post_id_value', 10, 3);
    function set_hidden_post_id_value($value, $post_id, $field) {
      // set the value of the field to the current post id
      return $post_id;
    }

    Working through your steps now hopefully I’ll have this working soon 🙂

    Thanks again!

  • I corrected the typo in that topic.

    By the way, you can hide the standard taxonomy box shown by WP by setting the meta_box_cb to false when registering your custom taxonomy.

  • Running into a brick wall trying to get the code working at the level you outlined in the original topic. (For it to validate across the whole post type).

    I have created a test field called ‘Validation Test’ with the name ‘test’.
    I am able to get the post ID to auto generate as you outlined. I have inspected the field to obtain its field key, to which I have then referenced in the necessary places in the code.

    I have also made sure that the filters are referencing the correct field i.e.

    load_value is using the field name=hidden_post_id (post id field)

    and

    validate_value is using name=test (validation test field name)

    Scratching my head as to why it won’t valid, I am continuing to try and prod around to get to the bottom of this.

    Is there anything obvious in my code that you can see? (I left out the ‘hide field’ code snippet you outlined in the original topic)

    //Auto fill in post id 
    add_filter('acf/load_field/name=hidden_post_id', 'make_hidden_post_id_readonly');
    function make_field_readonly($field) {
      // sets readonly attribute for field
      $field['readonly'] = 1;
      return field;
    } 
    add_filter('acf/load_value/name=hidden_post_id', 'set_hidden_post_id_value', 10, 3);
    function set_hidden_post_id_value($value, $post_id, $field) {
      // set the value of the field to the current post id
      return $post_id;
    }
    //Validate field 
      add_filter('acf/validate_value/name=test', 'require_unique', 10, 4);
    function require_unique($valid, $value, $field, $input) {
      if (!$valid) {
        return $valid;
      }
      // get the post id
      // using field key of post id field
      $post_id = $_POST['acf']['field_57765d437d860'];
      // query existing posts for matching value
      $args = array(
        'post_type' => 'knowledge-base',
        'posts_per_page' => 1, // only need to see if there is 1
        'post_status' => 'publish, draft, trash',
        'post__not_in' => array($post_id),
        'meta_query' => array(
          array(
            'key' => $field['test'],
            'value' => $value
          )
        )
      );
      $query = new WP_Query($args);
      if (count($query->posts)){
        $valid = 'This Value is not Unique';
      }
      return $valid;
    }

    Thanks

  • The only thing I found is this 'key' => $field['test'], should be 'key' => $field['name'],

    In my application I use the same filter for multiple fields and since ACF passes the field array to the filter you can get the field name from there rather than building a specific filter for each field. If you want the filer to only work on this field then the code should be 'key' => 'test',

  • Thanks John,

    So I have got this to work now.

    I created a taxonomy field and then used the validate_value filter to auto populate the field based on the existing taxonomy that had been selected for post.

    I then used a tax_query combined with get_the_terms to populate the terms parameter in the tax_query based on the posts term id.

    The only thing that is odd is that the validation message appears in on new page i.e. /wp-admin/post.php as opposed to being on the page.

    Below is my code for reference, hopefully this helps anyone that has a similar requirement.

     add_filter('acf/load_value/name=hidden_post_id', 'set_hidden_post_id_value', 10, 3);
    function set_hidden_post_id_value($value, $post_id, $field) {
      // set the value of the field to the current post id
      return $post_id;
    }
    
    //Auto populate tax field from post terms
    add_filter('acf/load_value/name=topic', 'set_topic_value', 10, 3);
    function set_topic_value($value, $post_id, $field) {
    
     // Get term id for current post
      $terms = get_the_terms(get_the_ID(), 'topic');
    
            if ( $terms && !is_wp_error( $terms )) {
                $term_list = wp_list_pluck( $terms, 'term_id' );
               // set the value of the field to the current term id
              return $term_list;
              }
        }
    
      add_filter('acf/validate_value/name=top_four_num', 'require_unique', 10, 4);
    function require_unique($valid, $value, $field, $input) {
    
     // Get term id for current post
      $terms = get_the_terms(get_the_ID(), 'topic');
      if ( $terms && !is_wp_error( $terms )) {    
                $term_list = wp_list_pluck( $terms, 'term_id' );          
              }
    
      if (!$valid) {
        return $valid;
      }
      // get the post id
      // using field key of post id field
      $post_id = $_POST['acf']['field_57765d437d860'];
      // query existing posts for matching value
      $args = array(
        'post_type' => 'knowledge-base',
        'posts_per_page' => 1, // only need to see if there is 1
        'post_status' => 'publish, draft, trash',
        'post__not_in' => array($post_id),
        'meta_query' => array(
          array(
            'key' => $field['name'],
            'value' => $value
          ),
        ),
        'tax_query' => array(
                array(
                    'taxonomy' => 'topic',
                    'terms'    => $term_list,                                       
                ),
            ),
      );
      $query = new WP_Query($args);
      if (count($query->posts)){
        $valid = 'Value is not unqiue. Please ensure this is selected once.';
      }
      return $valid;
    }

    Thanks once again John!

  • Check for PHP errors during the ajax request. You’ll need to turn on error reporting and logging, https://codex.wordpress.org/Debugging_in_WordPress. If there is an error during the ajax request it can cause what you describe.

Viewing 10 posts - 1 through 10 (of 10 total)

The topic ‘Restrict meta value to only be assigned once’ is closed to new replies.