Uwaga! Wpis ten dotyczy ciągle rozwijanej funkcjonalności WordPressa 3.7 – jej działanie może ulec zmianie w toku prac nad nowym wydaniem WordPressa.
Wygląda na to, że WordPress 3.7 przyniesie nową, bardzo ciekawą funkcjonalność związaną z tworzeniem zapytań zwracających wpisy – możliwość określenia ram czasowych dla pobieranych danych. Otwiera to wiele ciekawych możliwości np. wyświetlanie wpisów z konkretnego miesiąca, prezentacja wpisów opublikowanych tylko po godzinie 18 itd.
Sama obsługa tego typu zapytań wygląda przyjaźnie i warto o tej zmianie pamiętać oraz ją uwzględnić w swoich planach – może to pozwolić na uniknięcie tworzenia własnych, wyszukanych zapytań z pominięciem warstwy abstrakcji jaką oferuje nam natywna klasa obsługi bazy danych.
W klasie WP_Query dochodzi nam nowy argument – date_query, który posiada następujące parametry:
'date_query' => array( // Wszystkie parametry są opcjonalne 'column' => 'post_date', // określa kolumnę wykorzystywaną do porównań 'compare' => '=', // operator porównania, możliwe wartości: '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' 'relation' => 'AND', // określa jak będą łączone argumenty z podtablic - możliwe warotści: 'OR', 'AND' array( 'column' => 'post_date', // j.w. można łączyć porównania różnych kolumn 'compare' => '=', // j.w. można zmieniać operator dla każdej z podtablic 'after' => '', // ciąg znaków lub tablica, pozwala określić zakres dat 'before' => '', // ciąg znaków lub tablica, pozwala określić zakres dat 'inclusive' => false, // wartość logiczna określa czy daty z after i before będą włączane w zakres badanego przedziału 'year' => '', // liczba 4-cyfrowa lub tablica, określa lata 'month' => ''. // liczba z zakresu 1-12 lub tablica, określa miesiące 'week' => '', // liczba z zakresu 0-53 lub tablica, określa tygodnie 'day' => '', // liczba z zakresu 1-31 lub tablica, określa dni 'hour' => '', // liczba z zakresu 0-23 lub tablica, określa godziny 'minute' => '', // liczba z zakresu 0-59 lub tablica, okresla minuty 'second' => '', // liczba z zakresu 0-59 lub tablica, określa sekundy 'dayofweek' => '', // liczba z zakresu 1-7 lub tablica, określa dni tygodnia 'dayofyear' => '' // liczba z zakresu 1-366 lub tablica, określa dni roku ), array( ... ), .. )
Garść przykładów
Zacznijmy od prostego przypadku – pobranie wpisów utworzonych po godzinie 12:
'date_query' => array( array( 'hour' => 12, 'compare' => '>' ) )
Jak widać musimy jedynie okreslić godzinę oraz operator porównania. Dodajmy to tego teraz warunek, że wpisy będą utworzone po godzinie 12 ale NIE później niż o godzinie 18:
'date_query' => array( array( 'hour' => 12, 'compare' => '>' ), array( 'hour' => 18, 'compare' => '<=' ) )
Dodaliśmy kolejny warunek, który korzysta z faktu, że parametr relation ma domyślnie wartość AND – dla odmiany zmieńmy zakres: niech zapytanie pobierze tylko te wpisy, które powstały przed godziną 12 LUB po godzinie 18:
'date_query' => array( 'relation' => 'OR', array( 'hour' => 12, 'compare' => '<' ), array( 'hour' => 18, 'compare' => '>' ) )
Jak widać musieliśmy nie tylko zmienić operatory porówania, ale też i sposób łączenia argumentów z koniunkcji na alternatywę. Rozbudujmy nasz przykład jeszcze bardziej – do poprzedniego ograniczenia dodajmy jeszcze ograniczenie roku (chcemy wpisy tylko z roku 2013) oraz dni tygodnia (chcemy tylko wpisów z dni poniedziałek-piątek):
'date_query' => array( 'relation' => 'OR', array( 'hour' => 12, 'compare' => '<' ), array( 'hour' => 18, 'compare' => '>' ), array( 'year' => 2013 ), array( 'dayofweek' => array(1,5), 'compare' => 'BETWEEN' ) )
I tutaj pojawia się mały problem – nie możemy w trakcie definiowania data query zmienić operatora – w powyższym wypadku pokazany byłby każdy wpis, który spełniałby wspomniane warunki, podczas gdy my chcielibyśmy aby warunek wyglądał tak:
(godzina < 12 LUB godzina > 18) I rok = 2013 I dzień tygodnia z zakresu 1-5
Na szczęście możemy się uratować poniższym zapisem:
'date_query' => array( array( 'hour' => array(12, 18), 'compare' => 'NOT BETWEEN' ), array( 'year' => 2013 ), array( 'dayofweek' => array(1,5), 'compare' => 'BETWEEN' ) ),
Wykorzystaliśmu tutaj fakt iż parametry typu godzina, minuta itd. przyjmują też jako argument tablice, które możemy porównywać z użyciem operatora podanego w compare, dodatkowo przywróciliśmy domyślny operator porównania AND usuwając wartość arugmentu relation.
Na koniec przykład użycia argumentów before i after.
Jak już zostało opisane w kodzie na początku – oba argumenty przyjmują tablicę lub ciąg znaków jako wartość. Przykładowo określmy ramy czasowe na dni pomiędzy 28 a 29 września z użyciem ciągów znaków:
'date_query' => array( array( 'before' => '2013-9-29', 'after' => '2013-9-28' ) ),
Warto zauważyć, że zastosowaliśmy skrócone daty, zatem zostaną one rozwinięte odpowiednio do postaci:
2013-09-29 00:00:00 2013-09-28 00:00:00
Pamiętajmy, że jeżeli nie musimy stosować parametrów inclusive lub compare o różnych wartościach to nie musimy rozdzielać naszych warunków na oddzielne tablice.
Pora na dłuższą składnię, wykrzystującą tablice:
array( 'before' => array( 'year' => 2013, 'month' => 9, 'day' => 29 ), 'after' => array( 'year' => 2013, 'month' => 9, 'day' => 28 ) )
Ktoś może zapytać czy jest w ogóle sens stosować drugi dłuższy zapis? Otóż istnieje pewna subtelna różnica pomiędzy podaniem jako argumentu ciągu znaków a podaniem tablicy – w drugim wypadku wartość określona w argumencie after jest rozwijana do postaci:
2013-09-28 23:59:59
Wynika to z faktu iż kod parsujący argumenty na tą chwilę nie sprawdza w wypadku ciągu znaków czy określono godzinę i nie korzysta z drugiego argumentu metody build_mysql_datetime, który określa czy ma być ustawiona minimalna czy maksymalna wartość poszczególnych elementów daty.
Podsumowanie
Warto pamiętać, że opisywana funkcjonalność może w mniejszym lub większym stopniu ulec jeszcze zmianom przed wydaniem WordPressa 3.7, myślę jednak, że warto o niej wiedzieć i znać jej możliwości by móc już teraz uwzględnić jej potencjał w przyszłych wersjach swoich rozszerzeń dla WordPressa.