15%

Zaoszczędź 15% na wszystkich usługach hostingowych

Sprawdź swoje umiejętności i zdobądź Rabat na dowolny plan hostingowy

Użyj kodu:

Skills
Rozpocznij
21.10.2024

Co to jest zapytanie podatkowe w WordPress? Kompletny przewodnik dla programistów

A zapytanie taksonomiczne (tax query) w WordPress to ustrukturyzowany filtr przekazywany do WP_Query, który pobiera wpisy pasujące do określonych terminów taksonomii. Zamiast pobierać każdy wpis z bazy danych, tax query zawęża zestaw wyników wyłącznie do tych rekordów, których relacje terminów spełniają zdefiniowane warunki — niezależnie od tego, czy chodzi o pojedynczy slug kategorii, kombinację terminów niestandardowej taksonomii, czy złożony wzorzec wykluczenia wielu taksonomii.

W praktyce: jeśli chcesz wyświetlić tylko wpisy oznaczone tagiem „web-development”, które jednocześnie należą do niestandardowej taksonomii o nazwie „project-type” z terminem „client-work”, tax query jest właściwym i wydajnym narzędziem do tego zadania. Działa na poziomie SQL poprzez klasę WP_Tax_Query WordPressa, generując zoptymalizowane klauzule JOIN i WHERE dla tabel wp_term_relationships i wp_term_taxonomy.

Jak zbudowane są taksonomie i terminy w WordPress

Zanim napiszesz choćby jedną linię kodu zapytania, potrzebujesz jasnego modelu mentalnego leżącej u podstaw architektury danych.

Taksonomie to systemy klasyfikacji. WordPress jest dostarczany z dwiema globalnymi taksonomiami — category i post_tag — ale funkcja register_taxonomy() pozwala definiować nieograniczoną liczbę niestandardowych. Taksonomia jest zasadniczo nazwanym mechanizmem grupowania.

Terminy to indywidualne etykiety w ramach taksonomii. W taksonomii category terminami są „Technology”, „Lifestyle” i „Business”. Każdy termin ma trzy adresowalne identyfikatory:

  • term_id — całkowitoliczbowy klucz główny w wp_terms
  • slug — bezpieczny dla URL identyfikator tekstowy (np. web-development)
    name — czytelna dla człowieka etykieta wyświetlana
    
    Relacje terminów to rekordy pośrednie w wp_term_relationships, które łączą ID obiektu wpisu z ID taksonomii terminu. Każde tax query ostatecznie sprowadza się do wyszukiwania w tej tabeli.
    Zrozumienie tej trójwarstwowej struktury — taksonomia > termin > relacja terminu — jest niezbędne do pisania wydajnych zapytań i diagnozowania nieoczekiwanych zestawów wyników.
    Podstawowe argumenty parametru tax_query
    Klucz tax_query przyjmuje tablicę jednej lub więcej tablic klauzul zapytania oraz opcjonalny klucz relation na najwyższym poziomie. Każda klauzula obsługuje następujące argumenty:
    
    
    
    Argument
    Typ
    Opis
    Typowe wartości
    
    
    
    
    
    
    
    
    —
    —
    —
    —
    
    
    
    
    
    
    
    
    `taxonomy`
    string
    Taksonomia, względem której wykonywane jest zapytanie
    `category`, `post_tag`, niestandardowy slug
    
    
    
    
    
    
    
    
    `field`
    string
    Które pole terminu ma być dopasowane
    `slug`, `name`, `term_id`, `term_taxonomy_id`
    
    
    
    
    
    
    
    
    `terms`
    string / int / array
    Wartość/wartości terminu do dopasowania
    `'technology'`, `[4, 7]`, `'web-dev'`
    
    
    
    
    
    
    
    
    `operator`
    string
    Sposób zastosowania dopasowania terminu
    `IN`, `NOT IN`, `AND`, `EXISTS`, `NOT EXISTS`
    
    
    
    
    
    
    
    
    `include_children`
    bool
    Czy uwzględniać terminy podrzędne (tylko taksonomie hierarchiczne)
    `true` (domyślnie), `false`
    
    
    
    
    
    
    
    
    `relation`
    string
    Logiczny łącznik najwyższego poziomu między wieloma klauzulami
    `AND`, `OR`
    
    
    
    
    
    Argument operator w szczegółach
    To tutaj większość programistów popełnia błędy. Operatory działają następująco:
    
    IN (domyślny) — zwraca wpisy przypisane do *dowolnego* z podanych terminów. Jest to dopasowanie OR w ramach jednej klauzuli.
    NOT IN — wyklucza wpisy przypisane do dowolnego z podanych terminów.
    AND — zwraca wpisy przypisane do *wszystkich* podanych terminów jednocześnie. Używaj tego, gdy wpis musi posiadać wiele tagów naraz.
    EXISTS — zwraca wpisy posiadające *dowolny* termin w podanej taksonomii, niezależnie od tego, który to jest. Argument terms jest ignorowany.
    NOT EXISTS — zwraca wpisy bez przypisanego terminu w podanej taksonomii. Przydatne do znajdowania treści bez kategorii lub tagów.
    
    Ważna subtelność: operator => 'AND' w ramach jednej klauzuli sprawdza, czy jeden wpis jest przypisany do każdego terminu w tablicy terms. Różni się to od użycia relation => 'AND' na najwyższym poziomie, który łączy osobne klauzule. Mylenie tych dwóch podejść jest jednym z najczęstszych błędów tax query w produkcyjnym kodzie WordPress.
    Podstawowe Tax Query: filtr pojedynczej taksonomii
    Najprostszy przypadek użycia — pobierz wszystkie wpisy z kategorii „Technology”:
    $args = array(
        'post_type'  => 'post',
        'tax_query'  => array(
            array(
                'taxonomy' => 'category',
                'field'    => 'slug',
                'terms'    => 'technology',
            ),
        ),
    );
    
    $query = new WP_Query( $args );
    
    if ( $query->have_posts() ) {
        while ( $query->have_posts() ) {
            $query->the_post();
            // Render post content here
        }
        wp_reset_postdata();
    }
    Zawsze wywołuj wp_reset_postdata() po niestandardowej pętli WP_Query. Niezrobienie tego powoduje uszkodzenie globalnego obiektu $post, co psuje tagi szablonów takie jak the_title() i get_the_ID() dla wszystkich kolejnych zapytań na tej samej stronie.
    Łączenie wielu Tax Query za pomocą relation
    Klucz relation na najwyższym poziomie tablicy tax_query kontroluje sposób łączenia wielu klauzul:
    $args = array(
        'post_type'  => 'post',
        'tax_query'  => array(
            'relation' => 'AND',
            array(
                'taxonomy' => 'category',
                'field'    => 'slug',
                'terms'    => 'technology',
            ),
            array(
                'taxonomy' => 'post_tag',
                'field'    => 'slug',
                'terms'    => 'web-development',
            ),
        ),
    );
    Zwraca to tylko wpisy, które *jednocześnie* należą do kategorii „Technology” i są oznaczone tagiem „web-development”. Zmień relation na 'OR', a otrzymasz wpisy spełniające którykolwiek z warunków.
    Zagnieżdżone Tax Query (WordPress 4.1+)
    Do zaawansowanej logiki filtrowania WordPress obsługuje zagnieżdżone tablice tax_query, umożliwiając budowanie złożonych wyrażeń logicznych:
    $args = array(
        'post_type'  => 'product',
        'tax_query'  => array(
            'relation' => 'AND',
            array(
                'taxonomy' => 'product_cat',
                'field'    => 'slug',
                'terms'    => array( 'laptops', 'desktops' ),
                'operator' => 'IN',
            ),
            array(
                'relation' => 'OR',
                array(
                    'taxonomy' => 'product_tag',
                    'field'    => 'slug',
                    'terms'    => 'sale',
                ),
                array(
                    'taxonomy' => 'availability',
                    'field'    => 'slug',
                    'terms'    => 'in-stock',
                ),
            ),
        ),
    );
    Pobiera to produkty z kategorii „Laptops” lub „Desktops”, które *jednocześnie* są albo w promocji, albo dostępne w magazynie. Tego rodzaju zagnieżdżona logika jest niemożliwa do odtworzenia w czysty sposób za pomocą płaskiego klucza relation — zagnieżdżone tablice są jedynym właściwym podejściem.
    Niestandardowe typy wpisów i niestandardowe taksonomie
    Tax query stają się szczególnie potężne w połączeniu z niestandardowymi typami wpisów rejestrowanymi przez register_post_type() i niestandardowymi taksonomiami przez register_taxonomy(). Rozważmy stronę portfolio, gdzie rejestrujesz typ wpisu portfolio i taksonomię portfolio_type:
    // Register custom taxonomy (typically in functions.php or a plugin)
    register_taxonomy(
        'portfolio_type',
        'portfolio',
        array(
            'label'        => 'Portfolio Types',
            'hierarchical' => true,
        )
    );
    
    // Query portfolio items of type "branding"
    $args = array(
        'post_type'  => 'portfolio',
        'tax_query'  => array(
            array(
                'taxonomy' => 'portfolio_type',
                'field'    => 'slug',
                'terms'    => 'branding',
            ),
        ),
    );
    
    $query = new WP_Query( $args );
    Gdy hierarchical ma wartość true i include_children nie jest jawnie ustawione na false, zapytanie automatycznie uwzględnia wszystkie terminy podrzędne „branding”. Jest to właściwe zachowanie dla hierarchii w stylu kategorii, ale może dawać nieoczekiwane wyniki, jeśli masz głęboko zagnieżdżone drzewa terminów. Ustaw 'include_children' => false, gdy potrzebujesz dopasowania wyłącznie do dokładnego terminu.
    Używanie term_id vs. slug vs. name jako wartości field
    
    
    
    Wartość pola
    Kiedy używać
    Ostrzeżenie
    
    
    
    
    
    
    
    
    —
    —
    —
    
    
    
    
    
    
    
    
    `slug`
    Zapytania zakodowane na stałe w kodzie motywu/wtyczki
    Slugi mogą być zmieniane przez redaktorów w panelu administracyjnym
    
    
    
    
    
    
    
    
    `term_id`
    Zapytania krytyczne wydajnościowo lub programowe
    ID różnią się między środowiskami (dev vs. produkcja)
    
    
    
    
    
    
    
    
    `name`
    Logika czytelna dla człowieka, na poziomie warstwy wyświetlania
    Rozróżnia wielkość liter; podatna na błędy przy edycji nazw
    
    
    
    
    
    
    
    
    `term_taxonomy_id`
    Ujednoznacznianie wielu taksonomii
    Rzadko potrzebne; używaj tylko gdy ID terminów kolidują między taksonomiami
    
    
    
    
    
    W kodzie produkcyjnym slug jest generalnie najbezpieczniejszym wyborem ze względu na czytelność. Jednak jeśli migrujesz bazy danych między środowiskiem staging a produkcyjnym, pamiętaj, że wartości term_id będą się różnić. Zawsze używaj slug dla przenośnego kodu.
    Kwestie wydajności i typowe pułapki
    Wpływ na bazę danych
    Każde tax query generuje co najmniej jedno dodatkowe JOIN względem wp_term_relationships. Przy wielu klauzulach efekt ten się kumuluje. Na stronach z dziesiątkami tysięcy wpisów, źle skonstruowane tax query są główną przyczyną wolnego ładowania stron i przekroczeń czasu bazy danych.
    Kluczowe optymalizacje:
    
    Używaj fields => 'ids', gdy potrzebujesz tylko ID wpisów, a nie pełnych obiektów wpisów. Pozwala to uniknąć ładowania metadanych wpisów i zserializowanych danych.
    Buforuj wyniki za pomocą Transients API. Tax query na stronach archiwów, które rzadko się zmieniają, powinny być buforowane za pomocą set_transient() i get_transient().
    Unikaj operator => 'AND' z dużymi tablicami terminów. Każdy dodatkowy termin w klauzuli AND dodaje podzapytanie. Przed wdrożeniem wykonaj testy porównawcze za pomocą EXPLAIN w MySQL.
    Ustaw no_found_rows => true, gdy nie potrzebujesz paginacji. Pomija to narzut SQL_CALC_FOUND_ROWS.
    
    $args = array(
        'post_type'      => 'post',
        'fields'         => 'ids',
        'no_found_rows'  => true,
        'tax_query'      => array(
            array(
                'taxonomy' => 'category',
                'field'    => 'slug',
                'terms'    => 'technology',
            ),
        ),
    );
    Pułapka wp_reset_postdata()
    Jeśli uruchomisz wtórne WP_Query wewnątrz głównej pętli bez resetowania danych wpisu, globalna zmienna $post będzie wskazywać na niewłaściwy wpis przez resztę renderowania strony. Powoduje to subtelne błędy: błędne tytuły wpisów w okruszkach nawigacyjnych, nieprawidłowe kanoniczne URL-e i uszkodzone tagi Open Graph. Zawsze resetuj.
    Zapytania o terminy, które nie istnieją
    Jeśli przekażesz wartość terms, która nie istnieje w bazie danych, WP_Query zwróci zero wyników bez żadnego komunikatu. Nie ma żadnego błędu ani ostrzeżenia. Zawsze weryfikuj istnienie terminu za pomocą term_exists() przed konstruowaniem dynamicznych tax query opartych na danych wejściowych użytkownika lub danych zewnętrznych.
    $term = term_exists( 'technology', 'category' );
    if ( $term !== 0 && $term !== null ) {
        // Safe to build the tax query
    }
    Przypadki użycia z życia wzięte
    Niestandardowe strony archiwów
    Nadpisz archive.php lub użyj pre_get_posts, aby wstrzyknąć tax query do głównego zapytania, filtrując archiwum tak, aby pokazywało tylko określone terminy bez tworzenia osobnego obiektu zapytania:
    add_action( 'pre_get_posts', function( $query ) {
        if ( ! is_admin() && $query->is_main_query() && is_post_type_archive( 'portfolio' ) ) {
            $query->set( 'tax_query', array(
                array(
                    'taxonomy' => 'portfolio_type',
                    'field'    => 'slug',
                    'terms'    => array( 'branding', 'web-design' ),
                    'operator' => 'IN',
                ),
            ) );
        }
    } );
    Używanie pre_get_posts jest bardziej wydajne niż tworzenie wtórnego WP_Query, ponieważ modyfikuje główne zapytanie zanim trafi do bazy danych.
    Filtrowanie produktów w e-commerce
    WooCommerce rejestruje product_cat i product_tag jako standardowe taksonomie WordPress, a także taksonomie atrybutów takie jak pa_color i pa_size. Tax query napędzają warstwowy pasek boczny filtrów nawigacji. Niestandardowy filtr dla „czerwonych laptopów określonej marki” łączyłby trzy osobne klauzule taksonomii z relation => 'AND'.
    Redakcyjne wykluczanie treści
    Używaj operator => 'NOT IN', aby ukryć treści sponsorowane lub promocyjne z kanałów redakcyjnych:
    $args = array(
        'post_type'  => 'post',
        'tax_query'  => array(
            array(
                'taxonomy' => 'post_tag',
                'field'    => 'slug',
                'terms'    => array( 'sponsored', 'promoted' ),
                'operator' => 'NOT IN',
            ),
        ),
    );
    Znajdowanie niesklasyfikowanych treści
    Używaj operator => 'NOT EXISTS', aby przeprowadzić audyt biblioteki treści pod kątem wpisów pozbawionych wymaganych przypisań taksonomii:
    $args = array(
        'post_type'  => 'post',
        'tax_query'  => array(
            array(
                'taxonomy' => 'category',
                'operator' => 'NOT EXISTS',
            ),
        ),
    );
    Jest to nieocenione przy audytach treści na dużych serwisach redakcyjnych, gdzie wpisy mogły zostać zaimportowane bez właściwego przypisania taksonomii.
    Tax Query vs. Meta Query: wybór właściwego narzędzia
    Częstą decyzją architektoniczną w tworzeniu stron WordPress jest to, czy przechowywać dane filtrowania jako termin taksonomii, czy jako metadane wpisu. Wybór ten ma istotne implikacje dla wydajności.
    
    
    
    Kryterium
    Tax Query (`tax_query`)
    Meta Query (`meta_query`)
    
    
    
    
    
    
    
    
    —
    —
    —
    
    
    
    
    
    
    
    
    Tabela bazy danych
    `wp_term_relationships` (indeksowana)
    `wp_postmeta` (mniej zoptymalizowana do filtrowania)
    
    
    
    
    
    
    
    
    Wydajność zapytań
    Szybka — zaprojektowana do wyszukiwań opartych na zbiorach
    Wolniejsza przy skali — struktura EAV
    
    
    
    
    
    
    
    
    Filtrowanie fasetowe
    Natywne, wydajne
    Wymaga obejść
    
    
    
    
    
    
    
    
    Typ danych
    Kontrolowane słownictwo (terminy)
    Dowolne pary klucz-wartość
    
    
    
    
    
    
    
    
    Przypadek użycia
    Kategoryzacja, klasyfikacja
    Atrybuty, pomiary, flagi
    
    
    
    
    
    
    
    
    Indeksowanie
    Automatyczne poprzez ID taksonomii terminów
    Wymaga ręcznego dostrajania indeksów
    
    
    
    
    
    Zasada kciuka: jeśli dane są używane do filtrowania lub nawigacji (kolor, kategoria, typ, status), używaj taksonomii. Jeśli jest to unikalny atrybut dla każdego wpisu (cena, waga, znacznik czasu publikacji), używaj metadanych wpisu. Mylenie tych podejść jest jedną z najczęstszych przyczyn wolnych stron WordPress przy dużej skali.
    Kwestie hostingowe dla stron WordPress używających złożonych zapytań
    Tax query z wieloma klauzulami, zagnieżdżoną logiką lub dużymi zestawami terminów generują złożony SQL. Wydajność tych zapytań w dużym stopniu zależy od środowiska serwerowego.
    Na planie Hosting VPS masz bezpośrednią kontrolę nad konfiguracją MySQL — możesz dostroić innodb_buffer_pool_size, włączyć pamięć podręczną zapytań (MySQL 5.7 i wcześniejsze) oraz dodać niestandardowe indeksy do wp_term_relationships w razie potrzeby. Środowiska współdzielone zazwyczaj nie pozwalają na tego rodzaju dostrajanie bazy danych.
    Jeśli prowadzisz sklep WooCommerce o dużym ruchu z warstwową nawigacją opartą na tax query, Serwer Dedykowany zapewnia izolowane I/O bazy danych, co eliminuje problem „hałaśliwego sąsiada” degradującego czasy odpowiedzi zapytań na infrastrukturze współdzielonej.
    Dla programistów, którzy chcą wygody panelu sterowania przy jednoczesnym zachowaniu dostępu na poziomie serwera do optymalizacji bazy danych, VPS z cPanel zapewnia praktyczny kompromis — pełny dostęp do MySQL przez phpMyAdmin obok znajomego interfejsu zarządzania.
    Strony, które w dużym stopniu polegają na endpointach WordPress REST API opartych na tax query, powinny również rozważyć buforowanie obiektów (Redis lub Memcached) na poziomie serwera, które można skonfigurować na Panelach Sterowania VPS obsługujących niestandardowe warstwy buforowania PHP i po stronie serwera.
    Macierz decyzyjna i lista kontrolna techniczna
    Przed wdrożeniem tax query na produkcji zweryfikuj następujące kwestie:
    
    Zweryfikowano istnienie terminu — używaj term_exists() dla wszelkich dynamicznie konstruowanych wartości terminów
    Wywołano wp_reset_postdata() — po każdej niestandardowej pętli WP_Query, bez wyjątku
    Jawnie ustawiono include_children — nie polegaj na wartości domyślnej dla taksonomii hierarchicznych, chyba że uwzględnienie terminów podrzędnych jest zamierzone
    Używano fields => 'ids' — wszędzie tam, gdzie pełne obiekty wpisów nie są wymagane
    Ustawiono no_found_rows => true — dla każdego zapytania, które nie wymaga paginacji
    Wyniki buforowane — używaj Transients API dla zapytań na stronach archiwów lub stronach docelowych o dużym ruchu
    Preferowane pre_get_posts — zamiast wtórnych instancji WP_Query do modyfikacji głównego zapytania
    Potwierdzono wybór operator — rozróżnij między IN (dowolny termin), AND (wszystkie terminy) i NOT IN (wykluczenie) przed napisaniem klauzuli
    Jasne rozróżnienie relation vs. operator — relation łączy klauzule; operator kontroluje dopasowanie w ramach klauzuli
    Zagnieżdżone tablice używane dla złożonej logiki — nie próbuj wyrażać kombinacji AND/OR wyłącznie za pomocą płaskiego klucza relation
  • Zapytanie do bazy danych zalogowane i przejrzane — użyj wtyczki Query Monitor lub SAVEQUERIES, aby sprawdzić wygenerowany SQL przed uruchomieniem

FAQ

Jaka jest różnica między relation => 'AND' a operator => 'AND' w tax query?

relation to klucz najwyższego poziomu, który łączy ze sobą wiele klauzul tax query — określa, czy wpis musi spełniać wszystkie klauzule (AND), czy przynajmniej jedną (OR). operator to klucz na poziomie klauzuli, który określa sposób dopasowania tablicy terms w ramach jednej klauzuli — AND wymaga, aby wpis miał jednocześnie przypisany każdy wymieniony termin.

Dlaczego moje tax query nie zwraca żadnych wyników, mimo że wpisy i terminy istnieją?

Najczęstsze przyczyny to: przekazanie wartości terms niezgodnej z podanym typem field (np. przekazanie nazwy, gdy field jest ustawione na slug), zapytanie o taksonomię niezarejestrowaną dla danego typu wpisu lub użycie operator => 'AND' z terminami, których żaden pojedynczy wpis nie posiada jednocześnie. Włącz SAVEQUERIES i sprawdź surowy SQL, aby zdiagnozować problem.

Czy mogę używać tax query wewnątrz WordPress REST API?

Tak. WP_REST_Posts_Controller REST API akceptuje tax_query pośrednio poprzez zarejestrowane parametry zapytania. W przypadku niestandardowych taksonomii musisz ustawić 'show_in_rest' => true podczas rejestrowania taksonomii. W przypadku złożonych zapytań wieloklauzulowych użyj niestandardowego endpointu REST, który konstruuje argumenty WP_Query po stronie serwera.

Czy include_children => true wpływa na wydajność?

Tak. Gdy include_children jest włączone (domyślnie dla taksonomii hierarchicznych), WordPress wykonuje dodatkowe zapytanie w celu pobrania wszystkich ID terminów potomnych przed zbudowaniem głównego zapytania. W przypadku taksonomii z głębokimi hierarchiami i wieloma terminami, to wstępne zapytanie dodaje mierzalne obciążenie. Ustaw 'include_children' => false, gdy potrzebujesz dokładnego dopasowania terminu i nie wymagasz dziedziczenia terminów podrzędnych.

Czy istnieje limit liczby klauzul w tax query?

W rdzeniu WordPress nie ma zakodowanego na stałe limitu, ale praktyczne ograniczenia narzuca maksymalna głębokość złączeń MySQL i progi złożoności zapytań. Więcej niż cztery lub pięć klauzul w jednym tax query jest sygnałem, że model danych może wymagać ponownego przemyślenia — poprzez denormalizację, dedykowany indeks wyszukiwania (Elasticsearch, Typesense) lub restrukturyzację hierarchii taksonomii w celu zmniejszenia liczby klauzul.

15%

Zaoszczędź 15% na wszystkich usługach hostingowych

Sprawdź swoje umiejętności i zdobądź Rabat na dowolny plan hostingowy

Użyj kodu:

Skills
Rozpocznij