update_user_meta as multiple value but with same meta key

I have this code. When I save it, the user levels adding and gives time select input next to it. But when I give different time to levels, for example: Level 1: 2 weeks, Level 2: 9 Months

If saves only the last element, then all inputs display that value. How can I save different times? Where do I wrong?

//USER EDIT IN ADMIN DASHBOARD
add_action( 'show_user_profile', 'crf_show_extra_profile_fields' );
add_action( 'edit_user_profile', 'crf_show_extra_profile_fields' );

function crf_show_extra_profile_fields( $user ) {
    $user_levels = rua_get_user($user->ID)->get_level_ids();
    $elements = array();
    foreach ($user_levels as $user_level) {
        $present_date = date("Y-m-d");
        $end_time = get_the_author_meta( $user_level, $user->ID);
        $effectiveDate = strtotime($end_time, strtotime(date("Y-m-d")));
        $time = date("d/m/y", $effectiveDate);
        $elements[] = get_the_title($user_level) . 
        ' ->  <select name="' .$user_level. '" id="time-selector" style="width:180px;">
              <option value="default">Süre Seçiniz</option>
              <option value="+14 day" '.selected( $end_time, "+14 day"). '>2 Hafta</option>
              <option value="+9 months" '.selected( $end_time, "+9 months"). '>9 Ay</option>
              <option value="+12 months" ' .selected( $end_time, "+12 months"). '>12 Ay</option>
              <option value="+7 day" ' .selected( $end_time, "+7 day"). '>Uzat</option>
              </select>'  . $present_date . '   ' . $time .  '<br><br>';
    }
}


//SAVING DATE OF EACH LEVEL    
add_action( 'personal_options_update', 'crf_update_profile_fields' );
add_action( 'edit_user_profile_update', 'crf_update_profile_fields' );

function crf_update_profile_fields( $user_id ) {
    $user_levels = rua_get_user($user_id)->get_level_ids();
    foreach ($user_levels as $user_level) {
        update_user_meta( $user_id, $user_level, $_POST[ $user_level ] );
    }
}

//DELETING LEVEL
function my_demo_cronjob_action () {
    $present_date = date("Y-m-d");
    $user = get_user_by('id',26);
    $user_levels = rua_get_user($user)->get_level_ids(false, false, true);

    foreach ($user_levels as $level) {
      $end_time = get_the_author_meta( $level, $user->ID);
      $effectiveDate = strtotime($end_time, strtotime(date("Y-m-d")));
      $time = date("d/m/y", $effectiveDate);
      if ($present_date > $time) {
        rua_get_user($user)->remove_level($level);
      }
    }
}
add_action('my_demo_cronjob_action', 'my_demo_cronjob_action');

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x