0

I want to save/update a custom user meta field from the frontend, via ajax. This field should hold a list of post ID´s. No double ID´s should allowed.

My problem is that my field value get saved as an multidimension array, every time I update it.

For example the saved data looks like this:

Array ( [0] => Array ( [0] => Array ( [0] => [1] => 70 [2] => 79 ) [1] => 79 ) [1] => 93 )

I just need/want a single array.

I tried different things regarding the $single parameter of get_user_meta(), as it seems that this is the problem. But I was not able to find a solution.

I think the problem is the format of the value I get with get_user_meta().

In my enqueue function, I use wp_localize_script to add values to my custom JS file. Here I would like to check if a value was already saved, and send this value to the JS file.

(I added comments in the code)

function my_custom_enqueue() {
    if ( is_user_logged_in() ) {

        wp_enqueue_script( 'ajax-script', plugins_url('ajax.js', __FILE__), array('jquery') );

        $current_user = wp_get_current_user();
        $saved_ids = get_user_meta($current_user->ID, 'postlist', false); 
        // if changed to true, jquery is not working anymore, but if true it can also be an array

        // do something if $saved_ids is empty ?! check if it is an array?!

        wp_localize_script( 'ajax-script', 'my_ajax_object', array( 
            'ajax_url' => admin_url( 'admin-ajax.php' ),
            'saved_ids' => $saved_ids,
        ) );
    }
}
add_action( 'wp_enqueue_scripts', 'my_custom_enqueue' );

In my ajax.js file:

jQuery(document).ready(function($){

    //get the $saved_ids value
    var postIdsToCompare = my_ajax_object.saved_ids;

    $(document).on('click', '.add-to-list', function(e) {
        e.preventDefault();  

        // get post id from data-id of element
        var idToAdd = $(this).attr('data-id');          

        // see if post id already exists in postIdsToCompare
        // this is not working anymore because of the multidimension arrays
        var found = $.inArray(idToAdd, postIdsToCompare);

        if (found >= 0) {
            // Element was found, remove it from array
            postIdsToCompare.splice(found, 1);
        } else {
            // Element was not found, add it to array
            postIdsToCompare.push(idToAdd);
        }

        var data = {
            'action': 'make_post_list', // name of php function "wp_ajax_make_post_list"
            'ids_to_compare': postIdsToCompare, // to use $_POST['ids_to_compare']
        };

        $.post(my_ajax_object.ajax_url, data, function(response) {
            alert('Added');
        });
    });
});

My ajax callback function to save/update the field.

add_action( 'wp_ajax_make_post_list', 'make_post_list_callback' );
function make_post_list_callback() {

    global $wpdb; // this is how you get access to the database

    // Ensure we have the data we need to continue
    if( ! isset( $_POST ) || empty( $_POST ) || ! is_user_logged_in() ) {
        exit;
    }

    $user_id = get_current_user_id();

    $saved_ids = get_user_meta($user_id, 'postlist', true);

    $ids_to_compare = $_POST['ids_to_compare'];

    //save user meta here
    update_user_meta(
        $user_id, // user id
        'postlist', // meta key
        $ids_to_compare, // meta value
        $saved_ids // prev value, tried without it also
    );

    wp_die();
}
1
  • 2
    I see you added an authenticated AJAX endpoint, but I also see that you never indicate if update_user_met was succesful or not and simply exit with no error code or response? The code should check for the return values of get_user_meta and update_user_meta as well as output a failure response with a message, or a success response so the application knows if it worked or not. As an aside have you considered using the easier REST API endpoints?
    – Tom J Nowell
    Commented Mar 3, 2018 at 17:29

1 Answer 1

0

I wanted to update this older question.

I got this working or at least I got the saving worked out.

Thanks Tom J Nowell for your input. I considerd using the REST API yes, I looked at some introductions, but this went over my head. The REST API but also AJAX is kinda new to me, and I havent really worked with these things. I will especially look into using the REST API.

With that in mind, I think the code could be a lot better and cleaner, but I was just playing around and thought I should post my answer anyway. Its also kinda bare-bones...

The Enqueue code looks like this:

function my_custom_enqueue() {
    if ( is_user_logged_in() ) {

        wp_enqueue_script( 'ajax-script', plugins_url('ajax.js', __FILE__), array('jquery') );

        wp_localize_script( 'ajax-script', 'my_ajax_object', array( 
            'ajax_url' => admin_url( 'admin-ajax.php' ),
        ) );

    }
}
add_action( 'wp_enqueue_scripts', 'my_custom_enqueue' );

The ajax.js file looks like:

jQuery(document).ready(function($){

    $(document).on('click', '.add-to-list', function(e) {
        e.preventDefault();  

        // get post id from data-id of element
        var idToAdd = $(this).attr('data-id');   

        var data = {
            'action': 'make_post_list', // name of php function "wp_ajax_make_post_list"
            'id_to_add': idToAdd, // to use $_POST['ids_to_add']
        };

        $.post(my_ajax_object.ajax_url, data, function(response) {
            console.log (response); // show response in console
            alert(response); // show response as alert
        });

    });

});

And finally the callback function:

function make_post_list_callback() {

    global $wpdb; // this is how you get access to the database

    // Ensure we have the data we need to continue
    if( ! isset( $_POST ) || empty( $_POST ) || !is_user_logged_in() ) {
        echo 'Oops! Try again.';
        exit;
    }

    $user_id = get_current_user_id();

    // get array of already saved ID´s
    $saved_ids = get_user_meta($user_id, 'postlist', true);

    // new ID to add to array
    $id_to_add = $_POST['id_to_add'];

    // check if ID already exist in array,
    // only if it doesnt, we add it
    if( in_array( $id_to_add, $saved_ids ) ) {

        echo 'Failed: Post already in list.';

    } else {

         //if list is empty, initialize it as an empty array
         if($saved_ids == ''){
            $saved_ids = array();
         }

        // push the new ID inside the array
        array_push( $saved_ids, $id_to_add );

        if ( update_user_meta( $user_id, 'postlist', $saved_ids ) ) {
            echo 'Success!';
        } else {
            echo 'Failed: Could not update user meta.';
        }
    }

    wp_die(); // this is required to terminate immediately and return a proper response

}
add_action( 'wp_ajax_make_post_list', 'make_post_list_callback' );

With this a logged in user is able to click a button on a post, the post ID is than saved in the meta of the user, the saved meta data looks like:

Array ( [0] => 70 [1] => 76 [2] => 343 [3] => 375 [4] => 40 ) 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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