phpmysqlwordpressmeta-key

Combine meta values into a new key (PHP/WordPress)


Here's what I need to do, in laymen's terms:

For each wordpress user, find every meta key that starts with "FOO_" then combine all the meta values into a new key named "FOO_COMBINED"

My question refers to WordPress, but I think applies generally enough to PHP or SQL, that I hope this is the proper forum.

I generally understand, from related answers I found, that I need to do something like this:

function combine_keys() {

    $array = // the array of (all?) user meta

    foreach ($array as $key => $value) {
        if (substr($key, 0, 4) == "FOO_") {
            // grab the $value and append it to another key??
        }
    }

}

But I don't know how to translate this into WordPress functions. I know get_users() will get all users. And get_user_meta($user_id) will get all user meta for a specific user ID. But I don't know how to implement them into the above function. We have a lot of users, so it needs to be done efficiently.

My other question is when to call the function. The purpose of this is for exporting a CSV. I'm using a user export plugin, but I need to merge all FOO_ keys, with values separated by a line break, into a single key so we don't have to export a million FOO_ columns.

** UPDATE **

Here is my updated code trying to use implement the answer below. I put this into functions.php.

function combine_keys( $user_id ) {

    $array    = array();
    $all_meta = get_user_meta( $user_id );

    foreach( $all_meta as $key => $meta ) {
        if( preg_match('/^WORKSHOP_/', $key) )
            $array[$key] = $meta[0];
    }

    return $array;
}

add_action('personal_options_update', function( $user_id ){
    if ( current_user_can('edit_user', $user_id) )
        update_user_meta( $user_id, 'WORKSHOP_COMBINED', combine_keys( $user_id ) );

});

This works to create a new key (called WORKSHOP_COMBINED) and it sucessfully combines the values into an array like this:

a:2:{s:10:"WORKSHOP_5";s:43:"Test, May 15, 2015, Score: 80, Hours: 30 ";s:11:"WORKSHOP_30";s:68:"Middle School Civics & Economics, Jun 04, 2015, Score: 12, Hours: 43";}

But there are two problems:

  1. Everytime I update the profile, it ADDS another combined value to the WORKSHOP_COMBINED key, rather than replacing the value. Even though it says update_meta and not add_meta. Do you know why this is happening?

  2. I'd like to turn the array into a string. So instead of "return $array", I tried to implode it like this:

    $comma_separated = implode(",", $array); return $comma_separated;

But that returns nothing, and the value is empty. What have I done wrong? Thank you!


Solution

  • Here it is:

    function combine_keys( $user_id ) {
    
        $array    = array();
        $all_meta = get_user_meta( $user_id );
    
        foreach( $all_meta as $key => $meta ) {
            if( preg_match('/^FOO_/', $key) )
                $array[$key] = $meta[0];
        }
    
        return $array;
    }
    

    You can create the combined key like this:

    foreach (get_users() as $user) {
        $combined_meta = combine_keys( $user->ID );
        update_user_meta( $user->ID, 'FOO_COMBINED', $combined_meta );
    }
    

    As for when to call it, you could do it right before exporting the CSV (maybe using a hook provided by the plugin), or you could schedule it when you want.

    Or you could let the single user to save his personal combined key when he updates his profile:

    add_action('personal_options_update', function( $user_id ){
        if ( current_user_can('edit_user', $user_id) )
            update_user_meta( $user_id, 'FOO_COMBINED', combine_keys( $user_id ) );
    });
    

    UPDATE

    Answering the new questions:

    1. That happens because even FOO_COMBINED starts with FOO_, so it's added to the array (sorry, my fault :). Replacing the search pattern with /^FOO_(?!COMBINED)/ will exclude that key.
    2. It should be working, I don't see why it doesn't.

    I've updated the code to meet your new requirements and tested it:

    function combine_keys( $user_id ) {
    
        $array    = array();
        $all_meta = get_user_meta( $user_id );
    
        foreach( $all_meta as $key => $meta ) {
            if( preg_match('/^FOO_(?!COMBINED)/', $key) )
                $array[$key] = $meta[0];
        }
    
        return implode(',', $array);
    }
    
    add_action('personal_options_update', function( $user_id ){
        if ( current_user_can('edit_user', $user_id) )
            update_user_meta( $user_id, 'FOO_COMBINED', combine_keys( $user_id ) );
    
    });