0

I'm trying to create a multiple custom user profile fields to allow our users adding more software skills in their profile page.

The problem I'm facing is it always saving only one meta for "skills" and one meta for "skills_percent" even if I added more inputs!

What should I do to save all of them when I adding more fields?

And how to display all of them as well in the front end!

enter image description here

here what I have done.

<table class="skills-table">
    <tr>
        <th><label for="skills"><?php _e("Skills"); ?></label></th>
        <td>
            <div class="multi-field-wrapper">
              <button type="button" class="add-field">+</button>        
              <div class="multi-fields">
                <div class="multi-field">
                  <input type="text" name="skills" id="skills" value="<?php echo esc_attr( get_the_author_meta( 'skills', $current_user->ID ) ); ?>" class="textbox" />
                  <input type="text" name="skills_percent" id="skills_percent" value="<?php echo esc_attr( get_the_author_meta( 'skills_percent', $current_user->ID ) ); ?>" class="textbox" /><br />
                  <button type="button" class="remove-field">-</button>
                </div>
              </div>
          </div>
            <span class="description"><?php _e("Please enter your programs or software in the first box and how many percent in the second box ."); ?></span>
        </td>
    </tr>
</table>

script for adding/removing fields dynamically.

<script type="text/javascript">
jQuery(document).ready(function($) {
$('.multi-field-wrapper').each(function() {
    var $wrapper = $('.multi-fields', this);
    $(".add-field", $(this)).click(function(e) {
        $('.multi-field:first-child', $wrapper).clone(true).appendTo($wrapper).find('input').val('').focus();
    });
    $('.multi-field .remove-field', $wrapper).click(function() {
        if ($('.multi-field', $wrapper).length > 1)
            $(this).parent('.multi-field').remove();
    });
});
});
</script>

updating the user meta

if ( !empty( $_POST['skills'] ) )
    update_user_meta( $current_user->ID, 'skills', esc_attr( $_POST['skills'] ) );

if ( !empty( $_POST['skills_percent'] ) )
    update_user_meta( $current_user->ID, 'skills_percent', esc_attr( $_POST['skills_percent'] ) );

displaying the author meta in the front end

<dt class="j-s-m">Skills</dt><dd class="text-intro"><?php echo get_the_author_meta('skills', $curauth->ID); ?> <?php echo get_the_author_meta('skills_percent', $curauth->ID); ?></dd>

Update 1 as mrben522 answer

if ( !empty( $_POST['skills'] ) )
    $skillArray = [];
if (is_array($_POST['skills'])) {
    foreach ($_POST['skills'] as $skill) {
        $skillArray[] = esc_attr($skill);
    }
} else {
    $skillArray[] = esc_attr($_POST['skills']);
}

    update_user_meta( $current_user->ID, 'skills', $skillArray );


if ( !empty( $_POST['skills_percent'] ) )
    $skills_percentArray = [];
if (is_array($_POST['skills_percent'])) {
    foreach ($_POST['skills_percent'] as $skill_percent) {
        $skills_percentArray[] = esc_attr($skill_percent);
    }
} else {
    $skills_percentArray[] = esc_attr($_POST['skills_percent']);
}

    update_user_meta( $current_user->ID, 'skills_percent', $skills_percentArray );

but it return Array Array for skills and skills percent, also not saving the second div of "multi-field"

enter image description here

1 Answer 1

0

Add square brackets to input names to get PHP to interpret them as an array of data instead of overriding the value with each new input.

so your input will look like this:

          <input type="text" name="skills[]" id="skills" value="<?php echo esc_attr( get_the_author_meta( 'skills', $current_user->ID ) ); ?>" class="textbox" />
          <input type="text" name="skills_percent[]" id="skills_percent" value="<?php echo esc_attr( get_the_author_meta( 'skills_percent', $current_user->ID ) ); ?>" class="textbox" /><br />

And your sanitization will look like this (repeat the structure for skills_percent):

if ( !empty( $_POST['skills'] ) )
    $skillArray = [];
if (is_array($_POST['skills'])) {
    foreach ($_POST['skills'] as $skill) {
        if (!empty($skill)) {
            $skillArray[] = esc_attr($skill);
        }
    }
} else {
    $skillArray[] = esc_attr($_POST['skills']);
}

    update_user_meta( $current_user->ID, 'skills', $skillArray );

EDIT: You could also use array_map instead of a foreach loop.

$skillArray = array_map('esc_attr', $_POST['skills']);

EDIT 2: Here's basic structure for looping over your data for showing the inputs. I don't love this layout as it relies on the indices for the two arrays staying the same, but it should work.

<?php
$skills = get_the_author_meta( 'skills', $current_user->ID );
$skillPercents = get_the_author_meta( 'skills_percent', $current_user->ID );
if (is_array($skills) && is_array($skillPercents)) {
    foreach ($skills as $index => $skill) {
        ?>
        <div class="multi-field">
            <input type="text" name="skills[]" id="skills_<?php echo $index; ?>" value="<?php echo esc_attr( $skill ); ?>" class="textbox" />
            <input type="text" name="skills_percent[]" id="skills_percent_<?php echo $index; ?>" value="<?php echo esc_attr( $skillPercents[$index] ); ?>" class="textbox" /><br />
            <button type="button" class="remove-field">-</button>
        </div>
        <?php
    }
} else { ?>
    <div class="multi-field">
        <input type="text" name="skills[]" id="skills_0" value="<?php echo esc_attr( $skills ); ?>" class="textbox" />
        <input type="text" name="skills_percent[]" id="skills_percent_0" value="<?php echo esc_attr( $skillPercents ); ?>" class="textbox" /><br />
        <button type="button" class="remove-field">-</button>
    </div>
<?php   }
?>

You can rework this so each skill and percent was saved as it's own array in a 2d array to make it a bit more sturdy if you want.

14
  • Thanks for your answer @mrben522, kindly check the updated question. Mar 8, 2019 at 14:23
  • 1
    You'll need to change your output as well. var_dump(get_the_author_meta( 'skills', $current_user->ID )); and see what you get. most likely it's going to be an array of data. you'll need to create your input fields using a foreach loop iterating over that.
    – mrben522
    Mar 8, 2019 at 14:32
  • I'm sorry @mrben522, I still newbie, can you please give me a real answer so I can understand it as well, Thanks. Mar 8, 2019 at 14:40
  • 1
    Try now, added fallbacks for if you don't have data in those meta fields yet
    – mrben522
    Mar 8, 2019 at 17:10
  • 1
    the meta should be an array, so you need to loop over it as such. something like foreach (get_the_author_meta('skills', $curauth->ID) as $skill) { echo $skill}; although I would implement !empty and is_array checks before in case the data hasn't been set on an author
    – mrben522
    Mar 8, 2019 at 17:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.