Naucz się debugować hooki WordPress. Identyfikuj konflikty wtyczek, analizuj akcje i filtry oraz optymalizuj wydajność swojej strony.
PL

Jak debugować hooki WordPress? Kompletny przewodnik 2026

5.00 /5 - (27 głosów )
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.

Explore os nossos otimização de velocidade WordPress para levar o seu projeto mais longe.

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.