update_user_meta as multiple value but with same meta key

Your HTML select tags for each level all have the same name and ID, and will overwrite each other. They must be unique. You will need separate names, IDs, and meta for each user level input.

Likewise, the user meta keys need to be unique. The code also needs to use get_user_meta instead ( get_the_author_meta is only to be used inside a post loop ).

I suggest using something similar to this:

    foreach ($user_levels as $user_level) {
        update_user_meta( $user_id, 'time-selector-' . $user_level, $_POST[ 'time-selector' . $user_level ] );
    }

Then changing your input names and IDs accordingly. e.g. <select name="time-selector-" . $user_level . 'You will also need to adjust your get_user_meta call to use the new keys

There is another mistake in your code however. selected does not return a string, it outputs it, so the selected="selected" HTML will be output in the wrong place. You need to pass a 3rd parameter false to make it return, otherwise your HTML markup will be incorrect, and the selected attribute will be displayed before the input markup is displayed.

Here is an example:

Saving the meta:

$rua_user = rua_get_user( $user->ID );
$user_levels = $rua_user->get_level_ids();

// save existing values if they exist
foreach ( $user_levels as $level ) {
    $metakey = 'time-selector-' . $level;
    if ( isset( $_POST[ $metakey ] ) ) {
        update_user_meta( $user_id, $metakey, $_POST[ $metakey ] );
    }
}

Displaying the input:

$choices = [
    'two'  => 'Two Weeks',
    'nine' => '9 months',
];

$rua_user = rua_get_user( $user->ID );
$user_levels = $rua_user->get_level_ids();

foreach ( $user_levels as $level ) {
    $metakey = 'time-selector-' . $level;
    $time    = get_user_meta( $user->ID, $metakey, true );
    ob_start();
    echo esc_html( get_the_title( $level ) ) . ' -> ';
    ?>
    <select
        name="time-selector-<?php echo esc_attr( $level ); ?>"
        id='time-selector-<?php echo esc_attr( $level ); ?>'
        style="width:180px;"
    >
        <option value="default">Select time</option>
        <?php
        foreach ( $choices as $value => $label ) {
            ?>
            <option
                value="<?php echo esc_attr( $value ); ?>"
                <?php selected( $value, $time ); ?>
            >
                <?php echo esc_html( $label ); ?>
            </option>
            <?php
        }
        ?>
    </select>
    <br>
    <br>
    <?php
    $html = ob_get_clean();
    $elements[] = $html;
}
// ... etc

Note several important things:

  • All levels have unique and independent HTML markup, and post meta
  • Nothing is shared between each field, if things were shared they would not be separate
  • I used an output buffer to make the HTML easier to read and generate
  • I added escaping, an important security feature
  • The list of times is no longer hardcoded, and was moved to a separate array to simplify the code and reduce repetition. This also means they can be filtered, added to, etc
  • The save code is in a separate snippet, handling post/user save should not happen on the same hook as displaying the data.
    • By putting the save code inside the display code in your original question, you may have introduced a bug
  • Because the user meta keys have changed, all prior data will need to be re-saved. This should not be an issue as the prior data is broken due to the way your original code worked. Any data loss that could occurred already happened before you wrote the question.
  • If you try to use this snippet, you will not see the full list of times. I deliberately limited the array to 2 entries to prevent people using this as a copy paste solution. Anybody with beginner level PHP skills can update the array to add the other choices