Debugowanie hooków WordPress: akcje, filtry i kolejność wykonania
PL

Debugowanie hooków WordPress: akcje, filtry i kolejność wykonania

Ostatnio zweryfikowano: 1 maja 2026
12min czytania
Przewodnik
Full-stack developer

WordPress działa na hookach (akcje i filtry). Czasami zdarzają się nieoczekiwane rzeczy – treść znika, tytuły się zmieniają, style się psują, strona działa wolno. Podejrzewasz, że jakaś wtyczka ingeruje, ale która? W tym kompletnym przewodniku nauczysz się profesjonalnie debugować hooki WordPress, identyfikować konflikty i optymalizować wydajność swojej strony.

#Czym są hooki WordPress i dlaczego warto je debugować?

System hooków WordPressa to fundament jego rozszerzalności. Hooki pozwalają wtyczkom i motywom modyfikować zachowanie WordPressa bez edytowania plików core. Każda ważna funkcja w WordPressie uruchamia hooki, tworząc punkty zaczepieńia dla deweloperów.

#Dwa typy hooków

Akcje (Actions) – Wykonują się w określonym momencie cyklu życia WordPressa. Nie zwracają wartości, ale mogą wywoływać funkcje, wysyłać maile, modyfikować bazę danych.

Najpopularniejsze akcje:

  • wp_head – Wykonuje się w sekcji <head> strony
  • wp_footer – Wykonuje się przed zamknięciem tagu </body>
  • init – Wykonuje się podczas inicjalizacji WordPressa
  • template_redirect – Wykonuje się przed wczytaniem szablonu
  • save_post – Wykonuje się przy zapisywaniu wpisu

Filtry (Filters) – Modyfikują dane przed ich użyciem. Przyjmują wartość, modyfikują ją i zwracają zmienioną wersję.

Najpopularniejsze filtry:

  • the_content – Modyfikuje treść wpisu przed wyświetleniem
  • the_title – Modyfikuje tytuł wpisu
  • wp_enqueue_scripts – Pozwala dodawać skrypty i style
  • excerpt_length – Kontroluje długość wyciągu
  • upload_mimes – Modyfikuje dozwolone typy plików

#Kiedy debugowanie hooków jest niezbędne?

Debugowanie hooków staje się konieczne w wielu scenariuszach:

  1. Konflikty wtyczek – Dwie wtyczki modyfikują tę samą treść, powodując błędy
  2. Problemy z wydajnością – Strona ładuje się wolno z powodu zbyt wielu callbacków
  3. Nieoczekiwane zmiany – Treść lub wygląd zmieniają się bez wyraźnego powodu
  4. Błędy w motywach – Motyw nadpisuje funkcjonalność wtyczki
  5. Debugowanie produkcji – Musisz znaleźć źródło problemu na działającej stronie

#Jak działa system hooków WordPress?

Zanim przejdziemy do debugowania, zrozummy mechanizm działania hooków. WordPress przechowuje wszystkie zarejestrowane hooki w globalnej zmiennej $wp_filter, która jest instancją klasy WP_Hook.

#Struktura $wp_filter

// Przykładowa struktura $wp_filter
global $wp_filter;

$wp_filter['the_content'] = WP_Hook Object
(
    [callbacks] => Array
        (
            [10] => Array  // Priorytet 10 (domyślny)
                (
                    [0] => Array
                        (
                            [function] => 'wppoland_modify_content'
                            [accepted_args] => 1
                        )
                    [1] => Array
                        (
                            [function] => Array
                                (
                                    [0] => SomeClass Object
                                    [1] => 'method_name'
                                )
                            [accepted_args] => 1
                        )
                )
            [5] => Array   // Priorytet 5 (wykonuje się wcześniej)
                (
                    // Funkcje z priorytetem 5
                )
        )
)

#Priorytety hooków

Priorytety określają kolejność wykonywania callbacków:

  • Niższy numer = wcześniejsze wykonanie
  • Wyższy numer = późniejsze wykonanie
  • Ten sam numer = kolejność rejestracji
// Ten callback wykona się pierwszy (priorytet 5)
add_filter('the_content', 'first_function', 5);

// Ten callback wykona się drugi (priorytet 10 - domyślny)
add_filter('the_content', 'second_function', 10);

// Ten callback wykona się trzeci (priorytet 99)
add_filter('the_content', 'third_function', 99);

#Typy funkcji callback

WordPress obsługuje różne typy callbacków:

Funkcje nazwane:

add_filter('the_content', 'my_custom_function');

Metody statyczne klas:

add_filter('the_content', array('MyClass', 'static_method'));
// lub nowsza składnia:
add_filter('the_content', ['MyClass', 'static_method']);

Metody obiektów:

$obj = new MyClass();
add_filter('the_content', array($obj, 'method'));

Closures (funkcje anonimowe):

add_filter('the_content', function($content) {
    return $content . '<p>Dodatkowa treść</p>';
});

Problemy z closures: Funkcje anonimowe są trudniejsze do debugowania, ponieważ nie mają nazwy. Wymagają specjalnego podejścia przy użyciu Reflection API.

#Kompletny snippet do debugowania hooków

Oto zaawansowany snippet, który pozwala szczegółowo analizować hooki:

#Podstawowa wersja debugowania

/**
 * Podstawowa inspekcja hooków WordPress
 *
 * @param string $hook_name Nazwa hooka do sprawdzenia
 * @return void
 */
function wppoland_inspect_hook_basic( $hook_name ) {
    global $wp_filter;

    if ( ! isset( $wp_filter[ $hook_name ] ) ) {
        echo '<div style="background:#fff3cd; border:2px solid #ffc107; padding:15px; margin:20px 0; border-radius:4px;">';
        echo "<strong>ℹ️ Hook '$hook_name' nie ma podpiętych funkcji.</strong>";
        echo '</div>';
        return;
    }

    $hooks = $wp_filter[ $hook_name ];

    echo '<div style="background:#f8f9fa; border:2px solid #dee2e6; padding:20px; margin:20px 0; font-family:monospace; border-radius:4px;">';
    echo "<h3 style='margin-top:0; color:#333;'>🔍 Hook: <code style='background:#e9ecef; padding:2px 6px; border-radius:3px;'>$hook_name</code></h3>";
    echo "<p style='color:#666; font-size:14px;'>Liczba callbacków: " . count( $hooks->callbacks ) . "</p>";

    foreach ( $hooks->callbacks as $priority => $callbacks ) {
        echo "<h4 style='color:#495057; margin-top:20px; border-bottom:1px solid #dee2e6; padding-bottom:5px;'>Priorytet: $priority</h4>";
        echo '<ul style="list-style:none; padding-left:0;">';

        foreach ( $callbacks as $callback_id => $callback ) {
            $function_name = wppoland_get_callback_name( $callback['function'] );
            echo "<li style='margin:8px 0; padding:8px; background:#fff; border-left:3px solid #007bff;'>";
            echo "<code style='color:#d63384;'>$function_name</code>";
            echo "<span style='color:#6c757d; font-size:12px; margin-left:10px;'>(args: {$callback['accepted_args']})</span>";
            echo "</li>";
        }

        echo '</ul>';
    }
    echo '</div>';
}

/**
 * Pobiera czytelną nazwę callbacku
 *
 * @param mixed $callback Funkcja callback
 * @return string Nazwa funkcji
 */
function wppoland_get_callback_name( $callback ) {
    if ( is_string( $callback ) ) {
        return $callback;
    } elseif ( is_array( $callback ) ) {
        if ( is_object( $callback[0] ) ) {
            return get_class( $callback[0] ) . '->' . $callback[1];
        } else {
            return $callback[0] . '::' . $callback[1];
        }
    } elseif ( $callback instanceof Closure ) {
        $reflection = new ReflectionFunction( $callback );
        return 'Closure @ ' . $reflection->getFileName() . ':' . $reflection->getStartLine();
    }
    return 'Unknown';
}

#Zaawansowana wersja z Reflection API

/**
 * Zaawansowana inspekcja hooków z informacjami o źródle
 *
 * @param string $hook_name Nazwa hooka
 * @param bool $show_source Pokaż informacje o pliku źródłowym
 * @return void
 */
function wppoland_inspect_hook_advanced( $hook_name, $show_source = true ) {
    // Tylko dla administratorów
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }

    global $wp_filter;

    if ( ! isset( $wp_filter[ $hook_name ] ) ) {
        echo "<p style='color:#856404; background:#fff3cd; padding:10px; border-radius:4px;'>";
        echo "⚠️ Hook '$hook_name' nie ma podpiętych funkcji.";
        echo "</p>";
        return;
    }

    $hooks = $wp_filter[ $hook_name ];
    $total_callbacks = 0;

    // Policz wszystkie callbacki
    foreach ( $hooks->callbacks as $callbacks ) {
        $total_callbacks += count( $callbacks );
    }

    echo '<div style="background:#fff; border:1px solid #ddd; padding:20px; margin:20px 0; font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif; border-radius:8px; box-shadow:0 2px 4px rgba(0,0,0,0.1);">';
    echo "<h3 style='margin-top:0; color:#23282d; border-bottom:2px solid #0073aa; padding-bottom:10px;'>";
    echo "🔍 Analiza hooka: <code style='background:#f0f0f1; padding:4px 8px; border-radius:4px; color:#0073aa;'>$hook_name</code>";
    echo "</h3>";
    echo "<p style='color:#555;'><strong>Całkowita liczba callbacków:</strong> $total_callbacks</p>";

    foreach ( $hooks->callbacks as $priority => $callbacks ) {
        echo "<div style='margin-top:20px; background:#f6f7f7; padding:15px; border-radius:6px;'>";
        echo "<h4 style='margin-top:0; color:#23282d;'>Priorytet: <span style='color:#0073aa;'>$priority</span></h4>";

        foreach ( $callbacks as $callback_id => $callback ) {
            echo "<div style='background:#fff; padding:12px; margin:10px 0; border-left:4px solid #0073aa; border-radius:4px; box-shadow:0 1px 2px rgba(0,0,0,0.05);'>";

            // Nazwa funkcji
            $function_info = wppoland_get_callback_info( $callback['function'] );
            echo "<div style='font-weight:600; color:#23282d; margin-bottom:8px;'>";
            echo "<code style='background:#f0f0f1; padding:2px 6px; border-radius:3px;'>{$function_info['name']}</code>";
            echo "</div>";

            // Informacje dodatkowe
            echo "<div style='font-size:13px; color:#666; margin-left:10px;'>";
            echo "<strong>Argumenty:</strong> {$callback['accepted_args']}<br>";

            if ( $show_source && isset( $function_info['file'] ) ) {
                echo "<strong>Plik:</strong> {$function_info['file']}<br>";
                echo "<strong>Linia:</strong> {$function_info['line']}<br>";
            }

            if ( isset( $function_info['class'] ) ) {
                echo "<strong>Klasa:</strong> {$function_info['class']}<br>";
            }

            echo "</div>";
            echo "</div>";
        }

        echo "</div>";
    }

    echo '</div>';
}

/**
 * Pobiera szczegółowe informacje o callbacku
 *
 * @param mixed $callback Funkcja callback
 * @return array Informacje o funkcji
 */
function wppoland_get_callback_info( $callback ) {
    $info = array(
        'name' => 'Unknown',
        'type' => 'unknown'
    );

    try {
        if ( is_string( $callback ) ) {
            $info['name'] = $callback;
            $info['type'] = 'function';

            if ( function_exists( $callback ) ) {
                $reflection = new ReflectionFunction( $callback );
                $info['file'] = str_replace( ABSPATH, '', $reflection->getFileName() );
                $info['line'] = $reflection->getStartLine();
            }

        } elseif ( is_array( $callback ) ) {
            if ( is_object( $callback[0] ) ) {
                $class_name = get_class( $callback[0] );
                $info['name'] = $class_name . '->' . $callback[1];
                $info['type'] = 'method';
                $info['class'] = $class_name;

                $reflection = new ReflectionMethod( $callback[0], $callback[1] );
                $info['file'] = str_replace( ABSPATH, '', $reflection->getFileName() );
                $info['line'] = $reflection->getStartLine();

            } else {
                $info['name'] = $callback[0] . '::' . $callback[1];
                $info['type'] = 'static';
                $info['class'] = $callback[0];

                $reflection = new ReflectionMethod( $callback[0], $callback[1] );
                $info['file'] = str_replace( ABSPATH, '', $reflection->getFileName() );
                $info['line'] = $reflection->getStartLine();
            }

        } elseif ( $callback instanceof Closure ) {
            $reflection = new ReflectionFunction( $callback );
            $info['name'] = 'Closure';
            $info['type'] = 'closure';
            $info['file'] = str_replace( ABSPATH, '', $reflection->getFileName() );
            $info['line'] = $reflection->getStartLine();
        }

    } catch ( Exception $e ) {
        $info['error'] = $e->getMessage();
    }

    return $info;
}

#Praktyczne przykłady użycia

#Przykład 1: Debugowanie konfliktu wtyczek

Załóżmy, że masz problem z formatowaniem treści wpisu. Dwie wtyczki modyfikują the_content i powodują błędy.

// Dodaj do functions.php tymczasowo
add_action('wp_footer', function() {
    if ( current_user_can('manage_options') ) {
        wppoland_inspect_hook_advanced('the_content');
    }
});

Wynik pokaże wszystkie funkcje podpięte pod the_content wraz z ich priorytetami i źródłami. Możesz zidentyfikować, która wtyczka powoduje problem i zmienić jej priorytet lub wyłączyć.

#Przykład 2: Optymalizacja wydajności

Jeśli strona ładuje się wolno, sprawdź hooki wp_head i wp_footer:

// Zlicz callbacki dla każdego hooka
function wppoland_count_callbacks() {
    global $wp_filter;

    $hooks_to_check = array('wp_head', 'wp_footer', 'wp_enqueue_scripts', 'template_redirect');

    foreach ( $hooks_to_check as $hook ) {
        if ( isset( $wp_filter[ $hook ] ) ) {
            $count = 0;
            foreach ( $wp_filter[ $hook ]->callbacks as $callbacks ) {
                $count += count( $callbacks );
            }
            error_log( "Hook $hook ma $count callbacków" );
        }
    }
}
add_action('wp', 'wppoland_count_callbacks');

#Przykład 3: Znajdowanie źródła niechcianego kodu

Jeśli na stronie pojawia się nieznany kod JavaScript:

// Sprawdź wszystkie funkcje podpięte pod wp_footer
add_action('wp_footer', function() {
    if ( current_user_can('manage_options') ) {
        echo "<h4>Debug: Funkcje w wp_footer</h4>";
        wppoland_inspect_hook_advanced('wp_footer');
    }
}, 999);

#Narzędzia do debugowania hooków

#Query Monitor

Query Monitor to najlepsza wtyczka do debugowania WordPress. Pokazuje:

  • Wszystkie hooki i ich callbacki
  • Czas wykonania każdego zapytania
  • Błędy PHP i ostrzeżenia
  • Żądania HTTP

Instalacja:

  1. Przejdź do Wtyczki → Dodaj nową
  2. Wyszukaj “Query Monitor”
  3. Zainstaluj i aktywuj

Użycie: Po aktywacji pojawi się nowy panel w pasku admina. Przejdź do zakładki “Hooks & Actions” aby zobaczyć wszystkie hooki.

#Debug Bar

Debug Bar to klasyczne narzędzie do debugowania:

// Włącz debugowanie w wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

#Własne narzędzie do logowania

/**
 * Loguje wszystkie wywołania określonego hooka
 */
function wppoland_log_hook_calls( $hook_name ) {
    add_action( $hook_name, function() use ( $hook_name ) {
        $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 10 );
        $caller = isset( $backtrace[2] ) ? $backtrace[2] : array();

        $log_message = sprintf(
            '[%s] Hook %s wywołany przez: %s%s w %s:%d',
            current_time('mysql'),
            $hook_name,
            isset( $caller['class'] ) ? $caller['class'] . '->' : '',
            isset( $caller['function'] ) ? $caller['function'] : 'unknown',
            isset( $caller['file'] ) ? basename( $caller['file'] ) : 'unknown',
            isset( $caller['line'] ) ? $caller['line'] : 0
        );

        error_log( $log_message );
    }, 0 );
}

// Użycie:
wppoland_log_hook_calls( 'the_content' );
wppoland_log_hook_calls( 'wp_head' );

#Typowe problemy i rozwiązania

#Problem 1: Za dużo callbacków na jednym hooku

Objawy: Wolne ładowanie strony, timeouty

Rozwiązanie:

// Usuń niepotrzebne callbacki
function wppoland_remove_unnecessary_callbacks() {
    // Usuń emoji scripts
    remove_action('wp_head', 'print_emoji_detection_script', 7);
    remove_action('wp_print_styles', 'print_emoji_styles');

    // Usuń embed scripts jeśli nie używasz
    remove_action('wp_head', 'wp_oembed_add_discovery_links');
    remove_action('wp_head', 'wp_oembed_add_host_js');
}
add_action('init', 'wppoland_remove_unnecessary_callbacks', 999);

#Problem 2: Konflikt priorytetów

Objawy: Funkcje wykonują się w złej kolejności

Rozwiązanie:

// Zmień priorytet istniejącego callbacka
function wppoland_reorder_callbacks() {
    // Usuń i dodaj ponownie z innym priorytetem
    remove_filter('the_content', 'problematic_function', 10);
    add_filter('the_content', 'problematic_function', 5); // Wyższy priorytet
}
add_action('after_setup_theme', 'wppoland_reorder_callbacks');

#Problem 3: Nieznane źródło modyfikacji

Objawy: Treść zmienia się, ale nie wiesz skąd

Rozwiązanie:

// Dodaj tymczasowy filtr do śledzenia zmian
add_filter('the_content', function($content) {
    if ( current_user_can('manage_options') ) {
        $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
        error_log('the_content modified by: ' . print_r($backtrace[2], true));
    }
    return $content;
}, 999);

#Zaawansowane techniki debugowania

#Profilowanie wydajności hooków

/**
 * Mierzy czas wykonania callbacków dla danego hooka
 */
class WPPoland_Hook_Profiler {
    private $timings = array();

    public function start_profiling( $hook_name ) {
        add_action( $hook_name, array( $this, 'profile_start' ), PHP_INT_MIN );
        add_action( $hook_name, array( $this, 'profile_end' ), PHP_INT_MAX );
    }

    public function profile_start() {
        $this->timings['start'] = microtime( true );
    }

    public function profile_end() {
        $this->timings['end'] = microtime( true );
        $duration = ( $this->timings['end'] - $this->timings['start'] ) * 1000;
        error_log( sprintf( 'Hook execution time: %.2f ms', $duration ) );
    }
}

// Użycie:
$profiler = new WPPoland_Hook_Profiler();
$profiler->start_profiling( 'wp_head' );

#Śledzenie zmian w filtrach

/**
 * Śledzi wszystkie modyfikacje wartości przez filtry
 */
function wppoland_trace_filter_changes( $tag, $value ) {
    $original_value = $value;

    add_filter( $tag, function( $value ) use ( $tag, $original_value ) {
        static $call_count = 0;
        $call_count++;

        if ( $value !== $original_value ) {
            $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 4 );
            $caller = isset( $backtrace[3] ) ? $backtrace[3] : array();

            error_log( sprintf(
                'Filter %s modified value (call #%d) by %s%s',
                $tag,
                $call_count,
                isset( $caller['class'] ) ? $caller['class'] . '->' : '',
                isset( $caller['function'] ) ? $caller['function'] : 'unknown'
            ) );
        }

        return $value;
    }, PHP_INT_MAX );
}

// Użycie:
wppoland_trace_filter_changes( 'the_content', '' );

#Najlepsze praktyki i bezpieczeństwo

#Zasady bezpiecznego debugowania

  1. Nigdy nie pokazuj informacji debugowania gościom – Zawsze używaj current_user_can('manage_options')

  2. Używaj logów zamiast wyświetlania – W produkcji loguj do pliku zamiast wyświetlać na stronie:

if ( ! defined('WP_DEBUG') || ! WP_DEBUG ) {
    error_log( $debug_info ); // Loguj zamiast wyświetlać
}
  1. Usuwaj kod debugowania przed wdrożeniem – Upewnij się, że nie zostawiasz kodu debugowania na produkcji

  2. Używaj wtyczek do debugowania – Query Monitor jest bezpieczniejszy niż własny kod

#Checklist przed wdrożeniem

  • Usunięto wszystkie wywołania var_dump() i print_r()
  • Kod debugowania jest owinięty w sprawdzanie uprawnień
  • Logi debugowania są wyłączone w produkcji
  • Przetestowano na kopii stagingowej
  • Sprawdzono wpływ na wydajność

#Podsumowanie

Debugowanie hooków WordPress to kluczowa umiejętność dla każdego dewelopera. Dzięki zrozumieniu systemu hooków, użyciu odpowiednich narzędzi i stosowaniu najlepszych praktyk, możesz szybko identyfikować i rozwiązywać problemy na swoich stronach WordPress.

Kluczowe wnioski:

  • Używaj globalnej zmiennej $wp_filter do inspekcji hooków
  • Reflection API pozwala znaleźć dokładne źródło funkcji
  • Query Monitor to najlepsze narzędzie do wizualnego debugowania
  • Zawsze zabezpieczaj kod debugowania sprawdzaniem uprawnień
  • Testuj zmiany na kopii stagingowej przed wdrożeniem na produkcję

Mając te narzędzia i wiedzę, jesteś gotowy profesjonalnie debugować każdy problem związany z hookami WordPress.

Zobacz nasze usługi optymalizacji szybkości WordPress, jeśli chcesz poprawić Core Web Vitals i realną szybkość strony.

Następny krok

Przekuj artykuł w realne wdrożenie

Pod tym wpisem dokładam linki, które domykają intencję użytkownika i prowadzą dalej w strukturze serwisu.

FAQ do artykułu

Często zadawane pytania

Najważniejsze odpowiedzi, które pomagają wdrożyć temat w praktyce.

SEO-ready GEO-ready AEO-ready 3 Q&A
Czym jest Jak debugować hooki WordPress? Kompletny przewodnik 2026? #
Jak debugować hooki WordPress? Kompletny przewodnik 2026 to kluczowy element zarządzania witryną WordPress, który pomaga poprawić jej wydajność, bezpieczeństwo i doświadczenie użytkownika.
Jak wdrożyć Jak debugować hooki WordPress? Kompletny przewodnik 2026? #
Jak debugować hooki WordPress? Kompletny przewodnik 2026 polega na konfiguracji różnych ustawień i wdrażaniu najlepszych praktyk w celu optymalizacji Twojej strony WordPress.
Dlaczego Jak debugować hooki WordPress? Kompletny przewodnik 2026 jest ważne? #
Jak debugować hooki WordPress? Kompletny przewodnik 2026 jest to kluczowa sprawa, ponieważ ma bezpośredni wpływ na rankingi strony w wyszukiwarkach, prędkość ładowania i ogólny sukces witryny.

Potrzebujesz FAQ dopasowanego do branży i rynku? Przygotujemy wersję pod Twoje cele biznesowe.

Porozmawiajmy

Polecane artykuły

Słynny skrypt TimThumb to relikt przeszłości i dziura bezpieczeństwa. Zobacz, jak poprawnie skalować obrazy używając add_image_size() i nowoczesnych funkcji WP.
development

TimThumb idź do domu! Jak obsługiwać obrazki w WordPress w 2026?

Słynny skrypt TimThumb to relikt przeszłości i dziura bezpieczeństwa. Zobacz, jak poprawnie skalować obrazy używając add_image_size() i nowoczesnych funkcji WP.

Przestań pisać bałaganiarskie if-y. Poznaj różnicę między in_category a has_term, naucz się obsługiwać rekurencyjne kategorie potomne i optymalizować tagi warunkówe.
development

Logika warunkówa WordPress, kategorie, tagi i taksonomie

Przestań pisać bałaganiarskie if-y. Poznaj różnicę między in_category a has_term, naucz się obsługiwać rekurencyjne kategorie potomne i optymalizować tagi warunkówe.

Opanuj Pętlę WordPressa. Naucz się pisać wydajne zapytania WP_Query, unikać pułapek SQL (jak meta_query) i poprawnie stronicować własne pętle.
development

Kompleksowy przewodnik po wp_Query i pętli WordPress (edycja 2026)

Opanuj Pętlę WordPressa. Naucz się pisać wydajne zapytania WP_Query, unikać pułapek SQL (jak meta_query) i poprawnie stronicować własne pętle.