Create a random unique 6 digit number as custom field for custom post type

I use the following function to create a random unique 6 digit number and save it in a custom post type meta field.

I am unsure about the use of rewind_posts() inside a while loop. The idea is that it checks if the $random number already exists inside any of the existing custom posts. If it exists it generates a new random number and checks again against all custom posts.

function create_random_unique_id() {

  // Create random 6 digit number
  $random   = substr( rand() * 900000 + 100000, 0, 6 );

  // Get all Custom Posts  
  $args = array( 'post_type' => 'my_custom_post_type', 'posts_per_page' => -1 );
  $loop = new WP_Query( $args );

  // For each Custom Post, check if $random matches $cpt_id
  while ( $loop->have_posts() ) {

    $loop->the_post();
    $cpt_id = get_post_meta ( get_the_id(), 'id', true );

    // If $random matches $subscriber_id assign a different random 6 digit number
    if ( $cpt_id == $random ) {
      $random = substr( rand() * 900000 + 100000, 0, 6 );
      rewind_posts();
    }

  }

  return $random;
}

Solutions Collecting From Web of "Create a random unique 6 digit number as custom field for custom post type"

This quite an expensive operation what you are doing, and IMHO wrong worksflow as well. What you want to do is, is the following

  • Get all the meta_values from the specific meta_key you need.

  • You can then check the random number against the values returned from a specific meta_key

Here is a very basic idea in code: (Credit to Chinmoy Paul from pwdtechnology.com for the code. Code is commented for easy understanding)

The following goes into functions.php

/**    
 * Description: Getting all the values associated with a specific custom post meta key, across all posts
 * Author: Chinmoy Paul
 * Author URL: http://pwdtechnology.com
 *
 * @param string $key Post Meta Key.
 *
 * @param string $type Post Type. Default is post. You can pass custom post type here.
 *
 * @param string $status Post Status like Publish, draft, future etc. default is publish
 *
 * @return array
 */
function get_unique_post_meta_values( $key = '', $type = 'post', $status = 'publish' ) 
{
    global $wpdb;
    if( empty( $key ) )
        return;
    $res = $wpdb->get_col( 
        $wpdb->prepare( 
            "SELECT DISTINCT pm.meta_value 
            FROM {$wpdb->postmeta} pm
            LEFT JOIN {$wpdb->posts} p 
            ON p.ID = pm.post_id
            WHERE pm.meta_key = '%s'
            AND p.post_status = '%s'
            AND p.post_type = '%s'", 
            $key, 
            $status, 
            $type 
        ) 
    );
    return $res;
}

Now, to get a specific array of meta values from a given meta_key from a specific post_type and post_status, you can try the following

// Get ids to exclude
$ids_to_exclude = get_unique_post_meta_values(
    'id', // This is our meta_key to get values from
    'MY_POST_TYPE', // This is the name of your custom post type
    'POST_STATUS' // Any other post status except publish as publish is default
);

/**
 * Generate a unique id
 * Thanks to Gautam3164 for the code
 * @see http://stackoverflow.com/a/17109530/1908141
 */
do {   
    // This is taken as is from your code in question
    $random   = substr( rand() * 900000 + 100000, 0, 6 );
} 
while( in_array( $random, $ids_to_exclude ) );
echo $random;

EDIT

You can put everything together in one fully functional function.

/**    
 * Description: Get a random unique 6 number id for any given meta_key
 *
 * @param string $key Post Meta Key.
 *
 * @param string $type Post Type. Default is post. You can pass custom post type here.
 *
 * @param string $status Post Status like Publish, draft, future etc. default is publish
 *
 * @return array
 */
function get_unique_random_value( 
    $key = '', 
    $type = 'post', 
    $status = 'publish' 
) {
    global $wpdb;

    // Check if we have a meta_key before continuing, if not, return false
    if( empty( $key ) )
        return false;

    $res = $wpdb->get_col( 
        $wpdb->prepare( 
            "SELECT DISTINCT pm.meta_value 
            FROM {$wpdb->postmeta} pm
            LEFT JOIN {$wpdb->posts} p 
            ON p.ID = pm.post_id
            WHERE pm.meta_key = '%s'
            AND p.post_status = '%s'
            AND p.post_type = '%s'", 
            $key, 
            $status, 
            $type 
        ) 
    );
    // Check if we actually have an array of values, if not, return false
    if ( !$res )
        return false;

    /**
     * Generate a unique id
     * Thanks to Gautam3164 for the code
     * @see http://stackoverflow.com/a/17109530/1908141
     */
    do {   
        // This is taken as is from your code in question
        $random   = substr( rand() * 900000 + 100000, 0, 6 );
    } 
    while( in_array( $random, $res ) );
    return $random;
}

Then you can use it as follow

$random_id = get_unique_random_value (
    'id', // This is our meta_key to get values from
    'MY_POST_TYPE', // This is the name of your custom post type
    'POST_STATUS' // Any other post status except publish as publish is default
);
echo $random_id;