W ekosystemie WordPressa to WP_Query zgarnia całą chwałę, ale to WP_User_Query rządzi światem serwisów społecznościowych, intranetów i platform członkowskich.
Niezależnie od tego, czy budujesz prostą stronę “Nasz Zespół” (Team Page), czy skomplikowaną wyszukiwarkę “Znajdź Lekarza” z tysiącami specjalistów, poleganie na wtyczkach typu Ultimate Member do warstwy prezentacji jest często przesadą – i wąskim gardłem wydajnościowym.
W tym poradniku pominiemy interfejsy graficzne i zbudujemy wydajne, bezpieczne zapytania o użytkowników bezpośrednio w PHP. Omówimy granularne filtrowanie, cache’owanie wydajnościowe i krytyczne środki bezpieczeństwa, aby zapobiec wyciekom danych.
1. Development() vs. Wp_User_Query
Tak jak get_posts() jest nakładką na WP_Query, tak development() jest skonfigurowaną nakładką na WP_User_Query.
- Używaj
development()do prostych list (np. “Pokaż mi 5 administratorów”). Zwraca tablicę obiektówWP_User. - Używaj
WP_User_Query, gdy potrzebujesz zaawansowanych manipulacji SQL, szczegółowej logiki sortowania (‘orderby’) lub inspekcji nagłówków zapytania/wyników bezpośrednio.
W 95% przypadków będziemy używać tablicy argumentów, która ma zastosowanie do obu funkcji.
2. Podstawy: Budowa strony zespołu
Załóżmy, że chcemy wyświetlić siatkę pracowników (Redaktorów i Autorów) posortowaną według ich wyświetlanej nazwy.
$args = [
'role__in' => ['editor', 'author'],
'orderby' => 'display_name',
'order' => 'ASC',
'number' => 12, // Limit paginacji
'paged' => 1,
];
$user_query = new WP_User_Query($args);
$results = $user_query->get_results();
if (!empty($results)) {
echo '<div class="team-grid">';
foreach ($results as $user) {
$avatar = get_avatar($user->ID, 128);
$name = esc_html($user->display_name);
$bio = esc_html(get_user_meta($user->ID, 'description', true));
echo "<article class='team-member'>
<figure>{$avatar}</figure>
<h3>{$name}</h3>
<p>{$bio}</p>
</article>";
}
echo '</div>';
}
3. Zaawansowane filtrowanie (meta queries)
Tutaj WP_User_Query błyszczy. Wyobraź sobie, że masz katalog programistów i chcesz znaleźć tych, którzy:
- Są z “Warszawy”.
- Mają profil oznaczony jako “Publiczny”.
- Mają “PHP” na liście umiejętności.
$args = [
'role' => 'subscriber',
'meta_query' => [
'relation' => 'AND',
[
'key' => 'city',
'value' => 'Warszawa',
'compare' => '='
],
[
'key' => 'is_public_profile',
'value' => '1',
'compare' => '='
],
[
'key' => 'skills',
'value' => 'PHP',
'compare' => 'LIKE' // Wolne, ale skuteczne dla zserializowanych tablic
]
]
];
[!WARNING] Alert Wydajnościowy: Odpytywanie
wp_usermetajest kosztowne. W przeciwieństwie dowp_posts, tabele użytkowników rzadko są optymalnie indeksowane pod kątem złożonego filtrowania. Dla katalogów >10,000 użytkowników, rozważ przeniesienie indeksu wyszukiwania do Elasticsearch (przez ElasticPress) lub użycie własnej tabeli SQL.
4. Optymalizacja wydajności
Odpytując użytkowników na stronie o dużym ruchu, musisz oszczędnie gospodarować zasobami bazy danych.
A. Ogranicz zwracane pola (fields)
Domyślnie WordPress pobiera każdą możliwą daną o użytkowniku (wszystkie metadane). Jeśli potrzebujesz tylko imion i e-maili, powiedz WordPressowi, by był lekki.
$args = [
'role' => 'subscriber',
'number' => 100,
'fields' => ['ID', 'display_name', 'user_email'], // Zwraca obiekty stdClass, nie WP_User
];
Wynik: Zużycie pamięci RAM spada drastycznie.
B. Policz użytkowników bez ich Ładowania
Jeśli chcesz tylko pokazać “Mamy 500 członków!”, nie ładuj obiektów członków.
$args = [
'role' => 'subscriber',
'fields' => 'ID', // Pobierz tylko ID
];
$query = new WP_User_Query($args);
$count = $query->get_total(); // Używa logiki SQL_CALC_FOUND_ROWS
Lub dla ekstremalnej szybkości (ignorując złożone filtry), użyj count_users():
$count = count_users();
echo "Mamy " . $count['total_users'] . " użytkowników.";
5. Bezpieczeństwo: Zagrożenie “user enumeration”
Domyślnie WordPress jest dość “dziurawy”, jeśli chodzi o dane użytkowników.
- Nie ujawniaj Loginów: Nigdy nie wykonuj
echo $user->user_login. To połowa klucza potrzebnego do zhakowania konta administratora. Zawsze używajdisplay_namelubuser_nicename. - Ukrywaj E-maile: O ile to nie jest wewnętrzny intranet, nigdy nie wypisuj
user_emailw kodzie HTML, aby uniknąć botów spamujących.
Blokowanie archiwów autora
Hakerzy często skanują /?author=1, /?author=2, aby odkryć nazwy użytkowników. Jeśli budujesz stronę firmową, gdzie użytkownicy nie potrzebują publicznych archiwów, wyłącz tę trasę.
// Dodaj do functions.php
add_action('template_redirect', function() {
if (is_author()) {
wp_redirect(home_url(), 301);
exit;
}
});
6. Podsumowanie
Budowanie własnego katalogu użytkowników daje pełną kontrolę nad wydajnością i bezpieczeństwem.
- Używaj parametru
fields, aby zmniejszyć ślad pamięci. - Cache’uj wyniki używając Transients API, jeśli katalog nie zmienia się co godzinę.
- Sanityzuj dane wyjściowe bezlitośnie (zawsze
esc_html). - Chroń prywatność, ukrywając loginy i e-maile.
Użytkownicy w WordPressie to encje tak samo jak posty – zacznij ich odpytywać z tą samą precyzją.
7. Paginacja użytkowników
Przy dużych katalogach użytkowników, paginacja jest kluczowa dla wydajności i UX.
Paginacja numeryczna
function wppoland_paginated_users_list( $role = 'subscriber', $per_page = 20 ) {
$paged = isset( $_GET['paged'] ) ? max( 1, intval( $_GET['paged'] ) ) : 1;
$args = [
'role' => $role,
'number' => $per_page,
'paged' => $paged,
'fields' => ['ID', 'display_name', 'user_email', 'user_login'],
];
$user_query = new WP_User_Query( $args );
$users = $user_query->get_results();
$total_users = $user_query->get_total();
$total_pages = ceil( $total_users / $per_page );
// Wyświetl użytkowników
if ( ! empty( $users ) ) {
echo '<ul class="users-list">';
foreach ( $users as $user ) {
$profile_url = get_author_posts_url( $user->ID );
echo '<li>';
echo '<a href="' . esc_url( $profile_url ) . '">';
echo get_avatar( $user->ID, 48 );
echo '<span>' . esc_html( $user->display_name ) . '</span>';
echo '</a>';
echo '</li>';
}
echo '</ul>';
}
// Wyświetl paginację
if ( $total_pages > 1 ) {
echo '<nav class="pagination">';
echo paginate_links([
'base' => add_query_arg( 'paged', '%#%' ),
'format' => '?paged=%#%',
'current' => $paged,
'total' => $total_pages,
'prev_text' => '« Poprzednia',
'next_text' => 'Następna »',
]);
echo '</nav>';
}
echo '<p class="total-users">Łącznie: ' . $total_users . ' użytkowników</p>';
}
Nieskończone przewijanie (Infinite Scroll)
// AJAX handler dla infinite scroll
add_action( 'wp_ajax_wppoland_load_more_users', 'wppoland_load_more_users' );
add_action( 'wp_ajax_nopriv_wppoland_load_more_users', 'wppoland_load_more_users' );
function wppoland_load_more_users() {
$page = isset( $_POST['page'] ) ? intval( $_POST['page'] ) : 1;
$role = isset( $_POST['role'] ) ? sanitize_text_field( $_POST['role'] ) : 'subscriber';
$args = [
'role' => $role,
'number' => 12,
'paged' => $page,
'fields' => ['ID', 'display_name', 'user_email'],
];
$query = new WP_User_Query( $args );
if ( $query->get_results() ) {
foreach ( $query->get_results() as $user ) {
echo '<div class="user-card">';
echo get_avatar( $user->ID, 100 );
echo '<h3>' . esc_html( $user->display_name ) . '</h3>';
echo '<p>' . esc_html( $user->user_email ) . '</p>';
echo '</div>';
}
}
wp_die();
}
8. Filtrowanie według niestandardówych ról
WordPress pozwala na tworzenie własnych ról. Oto jak filtrować użytkowników według ról niestandardówych:
// Rejestracja roli niestandardowej
function wppoland_register_custom_roles() {
add_role(
'premium_member',
'Członek Premium',
[
'read' => true,
'edit_posts' => false,
'delete_posts' => false,
]
);
add_role(
'instructor',
'Instruktor',
[
'read' => true,
'edit_posts' => true,
'delete_posts' => true,
'upload_files' => true,
]
);
}
add_action( 'init', 'wppoland_register_custom_roles' );
// Wyświetl wszystkich instruktorów
function wppoland_list_instructors() {
$args = [
'role' => 'instructor',
'orderby'=> 'display_name',
'order' => 'ASC',
];
$query = new WP_User_Query( $args );
if ( $query->get_results() ) {
echo '<div class="instructors-grid">';
foreach ( $query->get_results() as $user ) {
$specialty = get_user_meta( $user->ID, 'specialty', true );
echo '<div class="instructor-card">';
echo get_avatar( $user->ID, 150 );
echo '<h3>' . esc_html( $user->display_name ) . '</h3>';
echo '<p class="specialty">Specjalizacja: ' . esc_html( $specialty ) . '</p>';
echo '<a href="' . esc_url( get_author_posts_url( $user->ID ) ) . '" class="button">Zobacz profil</a>';
echo '</div>';
}
echo '</div>';
}
}
9. Integracja z WooCommerce (lista klientów)
function wppoland_list_woocommerce_customers() {
$customers = [];
// Pobierz użytkowników, którzy złożyli zamówienia
$args = [
'role__in' => ['customer', 'subscriber', 'administrator'],
'number' => 50,
'paged' => isset( $_GET['paged'] ) ? intval( $_GET['paged'] ) : 1,
];
$query = new WP_User_Query( $args );
if ( $query->get_results() ) {
echo '<table class="customers-table">';
echo '<thead><tr><th>Klient</th><th>Email</th><th>Liczba zamówień</th><th>Suma wydana</th></tr></thead>';
echo '<tbody>';
foreach ( $query->get_results() as $user ) {
// Pobierz dane WooCommerce
$orders = wc_get_orders([
'customer' => $user->ID,
'status' => ['completed', 'processing'],
'limit' => -1,
]);
$order_count = count( $orders );
$total_spent = 0;
foreach ( $orders as $order ) {
$total_spent += $order->get_total();
}
echo '<tr>';
echo '<td>' . esc_html( $user->display_name ) . '</td>';
echo '<td><a href="mailto:' . esc_attr( $user->user_email ) . '">' . esc_html( $user->user_email ) . '</a></td>';
echo '<td>' . intval( $order_count ) . '</td>';
echo '<td>' . wc_price( $total_spent ) . '</td>';
echo '</tr>';
}
echo '</tbody></table>';
}
}
10. Wyszukiwanie użytkowników
function wppoland_user_search_form() {
?>
<form method="get" action="">
<input type="text" name="user_search" placeholder="Szukaj użytkownika..." value="<?php echo isset( $_GET['user_search'] ) ? esc_attr( $_GET['user_search'] ) : ''; ?>">
<button type="submit">Szukaj</button>
</form>
<?php
}
function wppoland_search_users( $search_term ) {
$args = [
'search' => '*' . sanitize_text_field( $search_term ) . '*',
'search_columns' => ['user_login', 'user_email', 'display_name'],
'number' => 20,
];
$query = new WP_User_Query( $args );
if ( $query->get_results() ) {
echo '<ul class="search-results">';
foreach ( $query->get_results() as $user ) {
echo '<li>';
echo get_avatar( $user->ID, 32 );
echo '<a href="' . esc_url( get_author_posts_url( $user->ID ) ) . '">';
echo esc_html( $user->display_name );
echo '</a>';
echo ' <small>(' . esc_html( $user->user_email ) . ')</small>';
echo '</li>';
}
echo '</ul>';
} else {
echo '<p>Nie znaleziono użytkowników.</p>';
}
}
11. Tworzenie katalogu z filtrami
function wppoland_advanced_user_directory() {
$role_filter = isset( $_GET['role'] ) ? sanitize_text_field( $_GET['role'] ) : '';
$city_filter = isset( $_GET['city'] ) ? sanitize_text_field( $_GET['city'] ) : '';
$search = isset( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : '';
$args = [
'number' => 12,
];
if ( $role_filter ) {
$args['role'] = $role_filter;
}
if ( $search ) {
$args['search'] = '*' . $search . '*';
$args['search_columns'] = ['display_name', 'user_email'];
}
if ( $city_filter ) {
$args['meta_query'] = [
[
'key' => 'city',
'value' => $city_filter,
'compare'=> 'LIKE',
]
];
}
$query = new WP_User_Query( $args );
// Wyświetl filtry
echo '<form method="get" class="user-filters">';
echo '<select name="role"><option value="">Wszystkie role</option>';
wp_dropdown_roles( $role_filter );
echo '</select>';
echo '<input type="text" name="city" placeholder="Miasto" value="' . esc_attr( $city_filter ) . '">';
echo '<input type="text" name="s" placeholder="Szukaj..." value="' . esc_attr( $search ) . '">';
echo '<button type="submit">Filtruj</button>';
echo '</form>';
// Wyświetl wyniki
if ( $query->get_results() ) {
echo '<div class="users-grid">';
foreach ( $query->get_results() as $user ) {
$city = get_user_meta( $user->ID, 'city', true );
echo '<div class="user-card">';
echo get_avatar( $user->ID, 100 );
echo '<h3>' . esc_html( $user->display_name ) . '</h3>';
echo '<p class="role">' . implode( ', ', $user->roles ) . '</p>';
if ( $city ) {
echo '<p class="city">📍 ' . esc_html( $city ) . '</p>';
}
echo '</div>';
}
echo '</div>';
} else {
echo '<p>Brak wyników.</p>';
}
}
12. Cache’owanie wyników
function wppoland_get_cached_users( $role = 'subscriber', $cache_time = HOUR_IN_SECONDS ) {
$cache_key = 'wppoland_users_' . md5( $role );
$users = get_transient( $cache_key );
if ( false === $users ) {
$args = [
'role' => $role,
'number' => -1,
'fields' => ['ID', 'display_name', 'user_email'],
];
$query = new WP_User_Query( $args );
$users = $query->get_results();
set_transient( $cache_key, $users, $cache_time );
}
return $users;
}
// Unieważnij cache przy nowej rejestracji
add_action( 'user_register', 'wppoland_invalidate_users_cache' );
function wppoland_invalidate_users_cache() {
global $wpdb;
$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '_transient_wppoland_users_%'" );
$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '_transient_timeout_wppoland_users_%'" );
}
13. REST API dla użytkowników
// Rejestracja endpoint REST API
add_action( 'rest_api_init', function() {
register_rest_route( 'wppoland/v1', '/users', [
'methods' => 'GET',
'callback' => 'wppoland_get_users_api',
'args' => [
'role' => [
'default' => 'subscriber',
'sanitize_callback' => 'sanitize_text_field',
],
'limit' => [
'default' => 10,
'sanitize_callback' => 'absint',
],
'offset' => [
'default' => 0,
'sanitize_callback' => 'absint',
],
],
]);
});
function wppoland_get_users_api( $request ) {
$args = [
'role' => $request->get_param( 'role' ),
'number' => $request->get_param( 'limit' ),
'offset' => $request->get_param( 'offset' ),
'fields' => ['ID', 'display_name', 'user_email', 'user_login'],
];
$query = new WP_User_Query( $args );
$users = [];
foreach ( $query->get_results() as $user ) {
$users[] = [
'id' => $user->ID,
'name' => $user->display_name,
'email' => $user->user_email,
'username' => $user->user_login,
'avatar_url' => get_avatar_url( $user->ID ),
'profile_url' => get_author_posts_url( $user->ID ),
];
}
return rest_ensure_response([
'total' => $query->get_total(),
'users' => $users,
]);
}
14. Shortcode do wyświetlania użytkowników
add_shortcode( 'lista_użytkownikow', 'wppoland_users_shortcode' );
function wppoland_users_shortcode( $atts ) {
$atts = shortcode_atts([
'role' => 'subscriber',
'limit' => 10,
'columns' => 3,
'avatar' => 'yes',
'bio' => 'no',
], $atts );
$args = [
'role' => $atts['role'],
'number' => intval( $atts['limit'] ),
'fields' => ['ID', 'display_name', 'user_email', 'user_login'],
];
$query = new WP_User_Query( $args );
if ( ! $query->get_results() ) {
return '<p>Brak użytkowników.</p>';
}
$output = '<div class="wppoland-users-shortcode" style="display: grid; grid-template-columns: repeat(' . intval( $atts['columns'] ) . ', 1fr); gap: 20px;">';
foreach ( $query->get_results() as $user ) {
$output .= '<div class="user-item" style="text-align: center; padding: 20px; border: 1px solid #eee; border-radius: 8px;">';
if ( 'yes' === $atts['avatar'] ) {
$output .= '<div class="user-avatar" style="margin-bottom: 10px;">' . get_avatar( $user->ID, 80 ) . '</div>';
}
$output .= '<h4 class="user-name" style="margin: 0 0 5px;">' . esc_html( $user->display_name ) . '</h4>';
$output .= '<p class="user-role" style="font-size: 0.8em; color: #666;">' . implode( ', ', $user->roles ) . '</p>';
if ( 'yes' === $atts['bio'] ) {
$bio = get_user_meta( $user->ID, 'description', true );
if ( $bio ) {
$output .= '<p class="user-bio" style="font-size: 0.9em;">' . esc_html( $bio ) . '</p>';
}
}
$output .= '</div>';
}
$output .= '</div>';
return $output;
}
15. Widget użytkowników
class WPPoland_Users_Widget extends WP_Widget {
public function __construct() {
parent: ':__construct('
'wppoland_users_widget',
'WPPoland: Lista Użytkowników',
['description' => 'Wyświetla listę użytkowników z wybraną rolą']
);
}
public function widget( $args, $instance ) {
echo $args['before_widget'];
$title = ! empty( $instance['title'] ) ? $instance['title'] : 'Użytkownicy';
$role = ! empty( $instance['role'] ) ? $instance['role'] : 'subscriber';
$limit = ! empty( $instance['limit'] ) ? intval( $instance['limit'] ) : 5;
echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
$query = new WP_User_Query([
'role' => $role,
'number' => $limit,
'orderby'=> 'registered',
'order' => 'DESC',
]);
if ( $query->get_results() ) {
echo '<ul class="users-widget-list">';
foreach ( $query->get_results() as $user ) {
echo '<li>';
echo '<a href="' . esc_url( get_author_posts_url( $user->ID ) ) . '">';
echo get_avatar( $user->ID, 40 );
echo '<span>' . esc_html( $user->display_name ) . '</span>';
echo '</a>';
echo '</li>';
}
echo '</ul>';
}
echo $args['after_widget'];
}
public function form( $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : '';
$role = ! empty( $instance['role'] ) ? $instance['role'] : 'subscriber';
$limit = ! empty( $instance['limit'] ) ? intval( $instance['limit'] ) : 5;
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">Tytuł:</label>
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
type="text" value="<?php echo esc_attr( $title ); ?>">
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'role' ) ); ?>">Rola:</label>
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'role' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'role' ) ); ?>">
<?php
global $wp_roles;
foreach ( $wp_roles->roles as $role_name => $role_info ) {
echo '<option value="' . esc_attr( $role_name ) . '"' . selected( $role, $role_name, false ) . '>';
echo esc_html( $role_info['name'] );
echo '</option>';
}
?>
</select>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'limit' ) ); ?>">Liczba użytkowników:</label>
<input class="tiny-text" id="<?php echo esc_attr( $this->get_field_id( 'limit' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'limit' ) ); ?>"
type="number" min="1" max="50" value="<?php echo esc_attr( $limit ); ?>">
</p>
<?php
}
public function update( $new_instance, $old_instance ) {
$instance = [];
$instance['title'] = sanitize_text_field( $new_instance['title'] );
$instance['role'] = sanitize_text_field( $new_instance['role'] );
$instance['limit'] = absint( $new_instance['limit'] );
return $instance;
}
}
function wppoland_register_users_widget() {
register_widget( 'WPPoland_Users_Widget' );
}
add_action( 'widgets_init', 'wppoland_register_users_widget' );
16. FAQ - Najczęściej zadawane pytania
Jak wyświetlić tylko użytkowników z konkretną rolą?
$args = [
'role' => 'administrator', // lub inna rola
];
$users = get_users( $args );
Jak ukryć użytkowników bez avatarów?
$args = [
'role' => 'subscriber',
'number' => 20,
];
$query = new WP_User_Query( $args );
foreach ( $query->get_results() as $user ) {
if ( get_avatar_url( $user->ID ) ) {
// Wyświetl użytkownika
}
}
Jak sortować użytkowników według daty rejestracji?
$args = [
'role' => 'subscriber',
'orderby'=> 'registered',
'order' => 'DESC', // najnowsi pierwszy
];
Jak wykluczyć użytkowników z listy?
$args = [
'role__not_in' => ['administrator', 'editor'],
'exclude' => [1, 2, 3], // ID do wykluczenia
];
Jak pobrać tylko liczbę użytkowników?
$args = [
'role' => 'subscriber',
'fields' => 'ID',
];
$query = new WP_User_Query( $args );
$count = $query->get_total();
Jak wyświetlić użytkowników online?
function wppoland_get_online_users() {
$transient_key = 'wppoland_online_users';
$online_users = get_transient( $transient_key );
if ( false === $online_users ) {
$ten_minutes_ago = time() - 600;
$users = get_users([
'fields' => ['ID', 'display_name'],
]);
$online = [];
foreach ( $users as $user ) {
$last_active = get_user_meta( $user->ID, 'last_activity', true );
if ( $last_active && $last_active > $ten_minutes_ago ) {
$online[] = $user;
}
}
$online_users = $online;
set_transient( $transient_key, $online_users, 300 );
}
return $online_users;
}
// Aktualizuj last_activity przy każdej wizycie
add_action( 'wp_footer', function() {
if ( is_user_logged_in() ) {
update_user_meta( get_current_user_id(), 'last_activity', time() );
}
});
Jak dodać własne pola do profilu użytkownika?
// Dodaj pola do formularza profilu
add_action( 'show_user_profile', 'wppoland_extra_profile_fields' );
add_action( 'edit_user_profile', 'wppoland_extra_profile_fields' );
function wppoland_extra_profile_fields( $user ) {
?>
<h3>Dodatkowe informacje</h3>
<table class="form-table">
<tr>
<th><label for="city">Miasto</label></th>
<td>
<input type="text" name="city" id="city" value="<?php echo esc_attr( get_user_meta( $user->ID, 'city', true ) ); ?>" class="regular-text">
</td>
</tr>
<tr>
<th><label for="phone">Telefon</label></th>
<td>
<input type="text" name="phone" id="phone" value="<?php echo esc_attr( get_user_meta( $user->ID, 'phone', true ) ); ?>" class="regular-text">
</td>
</tr>
</table>
<?php
}
// Zapisz pola
add_action( 'personal_options_update', 'wppoland_save_extra_profile_fields' );
add_action( 'edit_user_profile_update', 'wppoland_save_extra_profile_fields' );
function wppoland_save_extra_profile_fields( $user_id ) {
if ( ! current_user_can( 'edit_user', $user_id ) ) {
return false;
}
update_user_meta( $user_id, 'city', sanitize_text_field( $_POST['city'] ) );
update_user_meta( $user_id, 'phone', sanitize_text_field( $_POST['phone'] ) );
}
Podsumowanie
| Zadanie | Funkcja/Metoda | Przykład |
|---|---|---|
| Podstawowa lista | get_users() | get_users(['role' => 'author']) |
| Zaawansowane filtry | WP_User_Query | new WP_User_Query(['meta_query' => [...]]) |
| Paginacja | paginate_links() | Z WP_User_Query->get_total() |
| Wyszukiwanie | Parametr search | ['search' => '*tekst*'] |
| Cache | set_transient() | Cache’owanie wyników |
| REST API | register_rest_route() | Endpoint /wp-json/wppoland/v1/users |
| Shortcode | add_shortcode() | [lista_użytkowników role="editor"] |
| Widget | WP_Widget | Rejestracja własnego widgetu |
Kluczowe zasady:
- Używaj
fieldsdla oszczędności pamięci - Cache’uj wyniki dla dużych katalogów
- Chroń prywatność - nie ujawniaj loginów i emaili publicznie
- Paginate wyniki dla lepszej wydajności
- Sanityzuj wszystkie dane wyjściowe (
esc_html,esc_url)
Słowa kluczowe: WP_User_Query, get_users, lista użytkowników WordPress, katalog użytkowników, role użytkowników, filtrowanie użytkowników, paginacja użytkowników, shortcode użytkowników, widget użytkowników, cache użytkowników, REST API użytkownicy, bezpieczeństwo użytkowników, user enumeration, WooCommerce klienci, niestandardowe role.
Sprawdź nasze profesjonalne usługi WordPress aby rozwinąć swój projekt.

