Problema al almacenar arrays con update_user_meta en WordPress
Estoy escribiendo una función que añade un número de ID a un array y guarda el array en el usermeta. $_GET['auction']
es el post_id
.
A continuación la función:
$reminders = get_user_meta( $current_user->ID, "reminders" );
print_r( $reminders );
if( in_array( $_GET['auction'], $reminders ) ) {
echo "Error: Subasta ya existe en la lista";
} else {
array_push( $reminders, intval( $_GET['auction'] ) );
if ( update_user_meta( $current_user->ID, "reminders", $reminders ) ) {
echo "Éxito";
} else {
echo "Error: No se pudo actualizar el usermeta";
}
}
print_r( $reminders );
Salida después de añadir una subasta:
Array ( )
Éxito
Array ( [0] => 7 )
Salida después de añadir dos subastas:
Array ( [0] => Array ( [0] => 7 ) )
Éxito
Array ( [0] => Array ( [0] => 7 ) [1] => 73 )
Salida después de añadir tres subastas:
Array ( [0] => Array ( [0] => Array ( [0] => 7 ) [1] => 73 ) )
Éxito
Array ( [0] => Array ( [0] => Array ( [0] => 7 ) [1] => 73 ) [1] => 0 )
Observa que añadir un nuevo elemento al array usando array_push
funciona bien. Pero cuando el array se almacena en el usermeta y luego se recupera, el último elemento del array se convierte en un array, creando un array infinitamente dimensional. Prefiero mantener este array unidimensional.
¿Hay alguna forma de usar update_user_meta
y get_user_meta
sin que cambie la estructura de mi array?

Tuve el mismo problema y lo resolví con este pequeño fragmento, que coloca todos los nuevos valores en un solo array guardado como metadatos del usuario:
//Donde $access_key es el siguiente valor (añadido)
$get_access_keys_from_wp = get_user_meta($user_id,'wsm_capability');
$current_access_keys = $get_access_keys_from_wp[0];
$new_access_keys = array();
$new_access_keys[]=$access_key;
foreach($current_access_keys as $key => $value){
$new_access_keys[]=$value;
}
delete_user_meta( $user_id, 'wsm_capability');//Limpiar los metadatos...
update_user_meta( $user_id, 'wsm_capability', $new_access_keys);
Array antes de guardar/actualizar para la meta key (de get_user_meta):
Array
(
[0] => access_9
)
Array resultante (después de actualizar meta) añadiendo el valor 'access_5':
Array
(
[0] => access_5
[1] => access_9
)
Si necesitas que el nuevo valor se añada al final del array, haz esto en su lugar:
//Donde $access_key es el siguiente valor (añadido)
$get_access_keys_from_wp = get_user_meta($user_id,'wsm_capability');
$current_access_keys = $get_access_keys_from_wp[0];
$new_access_keys = array();
foreach($current_access_keys as $key => $value){
$new_access_keys[]=$value;
}
$new_access_keys[]=$access_key;
Luego actualiza los metadatos...
Bryan

No he usado la función desde hace bastante tiempo, pero supongo que tu problema es que estás insertando un array dentro de otro array. Así que verifica si intval($_GET['auction'])
es un array:
echo '<pre>';
print_r(intval($_GET['auction']));
echo '</pre>';
Edición #1: Quizás necesites obtener el valor de ese array y luego hacerle array_push. Así que algo como array_push( $reminders, $_GET['auction'][0]) );
- si solo estás añadiendo un único valor. También podrías hacer algo como $reminders[] = $_GET['auction'][0];
para añadirlo al final de tu array.
Edición #2: Echando un vistazo al archivo core: sí. update_user_meta()
es simplemente un alias de update_metadata()
que toma el ID + el valor y lo guarda en la base de datos como un array.
// Desde /wp-includes/meta.php ~ línea 135
$where = array( $column => $object_id, 'meta_key' => $meta_key );
if ( !empty( $prev_value ) ) {
$prev_value = maybe_serialize($prev_value);
$where['meta_value'] = $prev_value;
}

Parecía que el problema estaba con la serialización/deserialización del array, así que simplemente reescribí la función para que use una cadena separada por comas:
$reminders = get_user_meta($current_user->ID,"reminders",TRUE);
if(is_int(strpos($reminders,$_GET['auction']))) {
echo "Error: La subasta ya está en la lista";
} else {
$reminders .= ",".intval($_GET['auction']);
if(substr($reminders,0,1) == ",") { // Eliminar coma inicial si existe
$reminders = substr($reminders,1,strlen($reminders)-1);
}
if(update_user_meta($current_user->ID,"reminders",$reminders)) {
echo "Éxito";
} else {
echo "Error: No se pudo actualizar los metadatos del usuario";
}
}

Hola @Jarred, ¿al final esto funcionó para ti? Tengo una necesidad similar para mi sitio web. Tengo opciones de checkbox en el meta de usuario (un array) que necesito actualizar para cada usuario (más de 1500 usuarios). Y necesito una forma de actualizar cada usuario, dándoles diferentes selecciones, pero a gran escala. Nuestra solución parece que podría funcionar, pero no estoy seguro de cómo implementar la elección de diferentes opciones para cada usuario individual. Me gustaría trabajar con tu ejemplo, pero necesito ayuda para personalizarlo según mi necesidad, que sería hacer selecciones únicas para cada usuario y luego actualizar.

La respuesta de Shaun era correcta pero siento que necesita más clarificación. Puedes colocar un array en una entrada de meta de usuario, pero cuando lo recuperas todavía necesitas recuperarlo con el argumento single establecido en true, de lo contrario obtendrás un array de un array. Aquí está mi código:
$past_orders = get_user_meta($order_userID, 'qr-replacement-orders',true);
//verificar si esta nueva orden ya ha sido procesada
if(in_array($_GET["oid"],$past_orders))
{
echo '<p>Esta orden ya ha sido procesada.</p>';
//depuración
//var_dump($past_orders);
}
else
{
//añadir el número de orden al array de órdenes pasadas y almacenarlo
//si la lista está vacía, inicializarla como array vacío
if($past_orders == '')
{
$past_orders = array();
}
//añadir la nueva orden a la lista
array_push($past_orders, $_GET["oid"]);
//añadir la nueva lista a la base de datos
update_user_meta($order_userID, 'qr-replacement-orders',$past_orders);
echo '<p>Tu tarjeta ha sido comprada y será enviada por correo. ¡Gracias!</p>';
//depuración: confirmar que funcionó
//$past_orders = get_user_meta($order_userID, 'qr-replacement-orders',true);
//var_dump($past_orders);
}
