Support

Account

Home Forums General Issues Convert an ACF field to taxonomy

Solving

Convert an ACF field to taxonomy

  • My client has thousands of custom posts and wants to categorize them using custom field values.

    For example, he wants to categorize students according to the state. And there is already a field named state. Is there a way we can use that field to add each custom post into State taxonomy? Otherwise, it’ll take weeks to do it manually.

  • There is no easy way to do this. I do not know how the current field is saved but the taxonomy field stores values as a taxonomy ID, and categorizing by this I assume you mean you want to assign the terms to posts in the normal WP way. I can only give you an example. I am unable to give you all the code, a lot of what I am going to give you is just what you need to do.

    What I am going to give you is a temporary function that you put in functions PHP an run it by loading every page until you get the “completed” message and then you remove it.

    
    add_action('init', 'convert_field_to_terms');
    function convert_field_to_terms() {
      global $post;
      $args = array(
        'post_type' = 'your-post-type',
        'posts_per_page' => -1, // get all
        // get only posts that have not already been updated
        'meta_query' => array(
          'relation' =. 'OR',
          array(
            'key' => 'state_update_complete',
            'compare' => 'NOT EXISTS'
          ),
          array(
            'key' => 'state_update_complete',
            'value' => 0
          )
        )
      );
      $query = new WP_Query($args);
      if ($query->have_posts()) {
        while ($query->have_posts()) {
          $query->the_posts();
          // this is where you are going to need to figure out the details
    
          // get the ACF field value
          // ...
          // get the term that matches the ACF value or 
          // create the term if it does not exists
          // using get_term_by or insert_term()
          // ...
          // use wp_set_object_terms() to add terms to post
          // ...
          // set a meta value so we don't do this again if we need to run it multiple times
          update_post_meta($post->id, 'state_update_complete', '1');
        } // end while posts
      } // end if posts
    
      // the above loop will time out your site if there are a lot 
      // of posts that need to be updated
      // that means that anything after this point will only happen if
      // all posts are updated
      die('State Update Has Been Completed');
      // once you see the above message you can delete this action
    
    } // end function
    
  • So I was searching for how to do this and this support doc was the first result on Google. I have a case where we set-up custom fields for the admins to sort in the dashboard but now want to convert the fields to a taxonomy in order to display as categories on the front end. I ended up working with ChatGPT for an hour starting with this framework and have achieved this result–which surprisingly seems to work as expected. But I wanted to post it here not only because it is a potential solution for other users seeking this out, but also because I am a systems integrator more-so than a formal developer and I am wondering what more expert folks would make of this work? Is it sound?

    function convert_field_to_terms() {
        if (!is_admin()) {
            return; // Only run on the frontend
        }
    
        $args = array(
            'post_type' => 'portfolio',
            'posts_per_page' => -1,
        );
        $query = new WP_Query($args);
        if ($query->have_posts()) {
            while ($query->have_posts()) {
                $query->the_post();
                $acf_value = get_field('admin_theme');
                if ($acf_value) {
                    $term_ids = array(); // Array to store term IDs
    
                    if (!is_array($acf_value)) {
                        $acf_value = array($acf_value); // Convert to array if it's not already
                    }
    
                    foreach ($acf_value as $value) {
                        $term = get_term_by('name', $value, 'public-theme');
                        if (!$term) {
                            $term_args = array(
                                'slug' => sanitize_title($value),
                            );
                            $term = wp_insert_term($value, 'public-theme', $term_args);
                            if (!is_wp_error($term) && isset($term['term_id'])) {
                                $term_ids[] = $term['term_id']; // Add the term ID to the array
                            }
                        } elseif (!is_wp_error($term)) {
                            $term_ids[] = $term->term_id; // Add the term ID to the array
                        }
                    }
    
                    wp_set_object_terms(get_the_ID(), $term_ids, 'public-theme', false);
                }
                update_post_meta(get_the_ID(), 'state_update_complete', '1');
            }
        }
        wp_reset_postdata();
    }
    add_action('init', 'convert_field_to_terms');
    
  • I honestly do not see how this can work, there are multiple issues.

    1) the function does not include a global $post; statement, without this the line $query->the_post(); does not do what is expected and when you call get_the_ID() this will return the post ID of whatever page the function is called on and not the post ID for the current iteration of the post.

    2) The query does not include a meta query looking for only posts that have not been updated, a value you are attempting to set here update_post_meta(get_the_ID(), 'state_update_complete', '1');, note my previous comment about the fact that get_the_ID() is likely not returning the correct value, but that aside, without a meta query to exclude posts that have been updated already on a site with many, many posts (could be hundreds or thousands depending on the hosting) to process then it will likely time out and will start at the beginning each time it is run rather than picking up where it left off. Setting this meta value has no purpose if you do not then check the value in the query.

    2) the call to $acf_value = get_field('admin_theme'); will return the value for the current post and not the post of the current iteration of the loop for the same reason mentioned in #1

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

You must be logged in to reply to this topic.