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();
}
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();
}
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 )
update_user_met
was succesful or not and simply exit with no error code or response? The code should check for the return values ofget_user_meta
andupdate_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