WordPress

ajax — Jak zaktualizować moją funkcję jquery/PHP, aby dodać/usunąć użytkownika jako ulubionego na liście użytkowników (WordPress)

  • 24 kwietnia, 2023
  • 8 min read
ajax — Jak zaktualizować moją funkcję jquery/PHP, aby dodać/usunąć użytkownika jako ulubionego na liście użytkowników (WordPress)


Mam witrynę WordPress, w której wymieniam wszystkich użytkowników (w oparciu o subskrypcję MemberPress), a użytkownicy mogą zapisywać innych użytkowników jako ulubionych. Funkcja działa dobrze podczas zapisywania użytkownika jako ulubionego, przechowuje i aktualizuje tak, jak powinna, i jest pobierana, gdy sprawdzam w innym miejscu/przeglądarce.

Ale usunięcie użytkownika jako ulubionego nie działa. Oto co się dzieje:

  • Ładowanie jednej strony, kiedy klikam „usuń z ulubionych”, działa tak, jakbym kliknął „zapisz w ulubionych”, tekst „usuń z ulubionych” nie zmienia się. Po drugim kliknięciu tego samego „usuń z ulubionych”, tekst się zmienia, a przycisk jest aktualizowany, wydaje się, że wszystko idzie dobrze zgodnie z dziennikiem, ale po przeładowaniu strony nic nie jest zapisywane i wraca do „usuń z ulubionych” ’.

  • Inna sytuacja, podczas ładowania strony klikam „zapisz w ulubionych” jednego użytkownika, a potem „zapisz w ulubionych” innego, wydaje się, że wszystko jest w porządku. Ale po przeładowaniu strony faktycznie zapisywany jest tylko drugi, pierwszy wraca do „zapisz w ulubionych”. To samo dotyczy kliknięcia 3 lub więcej opcji „zapisz w ulubionych” i ponownego załadowania strony, zapisywana jest tylko ostatnia.

To jest moja lista użytkowników w PHP

function display_users($args = array(), $show_all_users = true)
{
    $default_args = array(
        'orderby' => 'name',
        'order' => 'ASC',
        'role' => 'subscriber',
        'search' => '',
    );
    $args = wp_parse_args($args, $default_args);

    $wp_user_query = new WP_User_Query($args);

    if (!empty($wp_user_query->results)) {
        $output="<div class="user-grid">";
        foreach ($wp_user_query->results as $user) {
            $mepr_user = new MeprUser($user->ID);
            if (empty($mepr_user->active_product_subscriptions('ids'))) {
                continue;
            }
            // Check if only favorites should be displayed
            if (!$show_all_users) {
                $user_id = get_current_user_id();
                $favorites = get_user_meta($user_id, 'favorites', true);
                if (!in_array($user->ID, $favorites)) {
                    // If user is not in favorites list, skip to the next user
                    continue;
                }
            }
            $output .= '<div class="user">';
            $output .= '<a href="' . get_author_posts_url($user->ID) . '">';
            if (get_field('mepr_avatar_profile', 'user_' . $user->ID)) {
                $avatar = get_field('mepr_avatar_profile', 'user_' . $user->ID);
                $class="user-image-bw";
            } else {
                $avatar="/wp-content/uploads/2023/04/new-color-community-1.png";
                $class="default-image-avatar";
            }

            $output .= '<div class="user-image">';
            $output .= '<img class="' . $class . '" src="' . esc_url($avatar) . '" alt="Author Avatar" />';
            $output .= '</div>';

            if (get_field('mepr_open_to_connect', 'user_' . $user->ID) == 'always-feel-free-to-reach-out') {
                $output .= '<p class="user-connect">Let\'s connect</p>';
            }

            $output .= '<div class="user-name">' . get_field('first_name', 'user_' . $user->ID) . '</div>';
            $output .= '<div class="user-info">';
            $current_work = get_field('mepr_current_work', 'user_' . $user->ID)[0];
            $current_work = str_replace('-', ' ', $current_work);
            $output .= '<p class="user-current-work">' . $current_work . '</p>';
            $output .= '</div>';
            $output .= '</a>';
            // Add favorite button
            if (is_user_logged_in()) {
                $user_id = get_current_user_id();
                $favorites = get_user_meta($user_id, 'favorites', true);
                if (!is_array($favorites)) {
                  $favorites = array(); // set $favorites to an empty array if it is not already an array
                }
                $nonce = wp_create_nonce('save_user_favorites');
                $output .= '<button class="favorite-button" data-user-id="' . $user->ID . '" data-favorites="' . esc_attr(json_encode($favorites)) . '" data-is-favorite="' . (in_array($user->ID, $favorites) ? 'true' : 'false') . '" data-nonce="' . $nonce . '">' . (in_array($user->ID, $favorites) ? 'Remove from favorites' : 'Add to favorites') . '</button>';
              }      

            $output .= '</div>';
        }
        $output .= '</div>';
    } else {
        $output="<p>No users found.</p>";
    }

    return $output;
}

To jest moja funkcja dodawania PHP do ulubionych

// save favorites function
function save_user_favorites() {
    if (!isset($_POST['favorites'])) {
      wp_send_json_error('Favorites not provided');
    }
  
    // Verify nonce
    if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'save_user_favorites')) {
      wp_send_json_error('Invalid nonce');
    }
  
    // Check if user is logged in
    if (!is_user_logged_in()) {
      wp_send_json_error('User not logged in');
    }
  
    // Get user ID
    $user_id = get_current_user_id();
  
    // Get favorites
    $favorites = isset($_POST['favorites']) ? $_POST['favorites'] : array();
  
    // Update user meta
    update_user_meta($user_id, 'favorites', $favorites);
  
    wp_send_json_success();
  }
  
  add_action( 'wp_ajax_nopriv_save_user_favorites', 'save_user_favorites' );
  add_action( 'wp_ajax_save_user_favorites', 'save_user_favorites');

To jest moje jQuery

$('.favorite-button').click(function(e) {
  e.preventDefault();

  var button = $(this);
  var userId = button.data('userId');
  var nonce = button.data('nonce');
  // get existing favorites from the data attribute of the button
  var favorites = button.data('favorites') || [];

  // Add or remove user from favorites
  if (userId !== "") { 
    const indexToRemove = favorites.indexOf(userId);

    if (!favorites.includes(userId)) { 
      favorites.push(userId);
      console.log(`User ${userId} added to favorites.`);
    } else {
      favorites.splice(indexToRemove, 1);
      console.log(`User ${userId} removed from favorites.`);
    }

    // Save favorites to the user metadata via AJAX 
    $.post(ajaxurl, {
      'action': 'save_user_favorites',
      'favorites': favorites,
      'nonce': nonce,
      'user_id': userId // add user ID to request parameters,
    })  
    .done(function(response) {
      console.log('Favorites saved:', response);
      // update the favorites attribute of the button
      button.data('favorites', favorites);
    })
    .fail(function(xhr, status, error) {
      console.log('Failed to save favorites:', error);
      console.log('Server response:', xhr.responseText);
    });
  } else {
    console.log(`Cannot add/remove user with empty ID`);
  }

  // Toggle button text and data attribute
  button.text(favorites.includes(userId) ? 'Remove from favorites' : 'Add to favorites');
});

Próbując w inny sposób

Próbowałem również innego sposobu żądania ajax, najpierw przechowując go jako pamięć lokalną i aktualizując listę ulubionych podczas przeładowywania strony. To działało naprawdę dobrze i tak, jak powinno (dodawanie/usuwanie użytkowników), ale pojawia się błąd podczas ponownego ładowania strony, gdy próbuje zapisać ją w ulubionych (nie w pamięci lokalnej).

Warto przeczytać!  tworzenie wtyczek — Próbuję utworzyć tablicę atrybutów. Tablica nie jest zapełniana

To, co dzieje się po przeładowaniu, polega na tym, że nie jest ono faktycznie zapisywane po stronie serwera, tylko lokalnie, i otrzymuję takie wyjście na konsoli:

from the update user Array []
from the update user Array []
from the update user Array []
from the update user Array(4) [ 420, 442, 449, 447 ]
from the update user Array []

I to trwa, z tylko tablicą z wartościami tych, które zapisałem. Obok niego jest napisane, również wiele razy w Firefoksie:

Failed to save favorites: 
Server response: undefined
Failed to save favorites: 
Server response: undefined

w chromie:

Favorites saved: {success: false, data: 'Favorites not provided'} 
data: "Favorites not provided"
success: false
[[Prototype]]: Object

To jest mój drugi jQuery, którego można użyć zamiast powyższego, najpierw zapisując go lokalnie

// get existing favorites from localStorage, or initialize to empty array
var favorites = JSON.parse(localStorage.getItem('favorites') || '[]');

$('.favorite-button').click(function(e) {
  e.preventDefault();

  var button = $(this);
  var userId = button.data('userId');

  // Add or remove user from favorites if userId is not empty
  if (userId !== "") {
    var isFavorite = button.data('isFavorite');
    var nonce = button.data('nonce');

    const userIdToRemove = userId; // Replace with the actual user ID you want to remove
    const indexToRemove = favorites.indexOf(userIdToRemove);

  // Add or remove user from favorites
  if (!favorites.includes(userId)) {
    favorites.push(userId);
    console.log('user added to favorites')
  } else {
    favorites.splice(indexToRemove, 1);
    console.log('user deleted from favorites')
  }

  // Save favorites to localStorage
  localStorage.setItem('favorites', JSON.stringify(favorites));

  // Save favorites to user metadata
  $.post(ajaxurl, {
    'action': 'save_user_favorites',
    'favorites': favorites,
    'nonce': nonce,
    'user_id': userId // add user ID to request parameters
  })  
  .done(function(response) {
    console.log('Favorites saved:', response);
  })
  .fail(function(xhr, status, error) {
    console.log('Failed to save favorites:', error);
    console.log('Server response:', xhr.responseText);
  });

  update_local_storage(userId, favorites)

  console.log('favorites saved to local storage', favorites)

  // Toggle button text and data attribute
  button.text(favorites.includes(userId) ? 'Remove from favorites' : 'Add to favorites');
  }
});

// on page load, update button text based on stored favorites
$('.favorite-button').each(function() {
  var button = $(this);
  var userId = button.data('userId');
  var isFavorite = button.data('isFavorite');

  // check if user is in favorites
  var favorites = JSON.parse(localStorage.getItem('favorites') || '[]');
  var isUserFavorite = favorites.includes(userId);

  // set button text and data attribute based on result
  button.text(isUserFavorite ? 'Remove from favorites' : 'Add to favorites');
  button.data('isFavorite', isUserFavorite);
  button.data('favorites', favorites);
});

// function to store favorites in localStorage
function update_local_storage(user_id, favorites) {
  localStorage.setItem('favorites_' + user_id, JSON.stringify(favorites));
  // console.log('localstorage', favorites)
}

function update_user_favorites(user_id, favorites, nonce) {
  console.log('from the update user', favorites)

  $.post(ajaxurl, {
    'action': 'save_user_favorites',
    'favorites': favorites,
    'nonce': nonce,
    'user_id': user_id // Use the user_id parameter instead of userId
  })
  .done(function(response) {
    console.log('Favorites saved:', response);
  })
  .fail(function(xhr, status, error) {
    console.log('Failed to save favorites:', error);
    console.log('Server response:', xhr.responseText);
  });
}


// update user metadata when page is unloaded
$(window).on('beforeunload', function() {
  $('.favorite-button').each(function() {
    var user_id = $(this).data('userId');
    var nonce = $(this).data('nonce');
    var favorites = JSON.parse(localStorage.getItem('favorites_' + user_id) || '[]');
    // var favorites = [ 449, 487, 442, 474, 488, 457, 553, 559, 841]
    // console.log({favorites})
    update_user_favorites(user_id, favorites, nonce);
  });
});

Próbowałem rejestrować każdy krok i za każdym razem wygląda na to, że dane są przekazywane poprawnie i nie mogę dowiedzieć się, dlaczego to nie działa. Jakieś sugestie?

Warto przeczytać!  importowanie Gutenberga skopiowanego html do wtyczki Block


Źródło