Zurück in die Zukunft: Wie WP_Date_Query funktioniert

datequery

Mit WordPress 3.7 wurde die lang ersehnte Erweiterung »Datumssuche« eingespielt. In diesem Beitrag möchte ich euch eine kleine Einführung in das neue Feature geben.

Neue Klasse WP_Date_Query

Die neue Klasse heißt WP_Date_Query. Mit ihrer Methode get_sql() können wir WHERE-Klauseln mit Datumssuchen generieren. Folgende Parameter sind für die Generierung von Suchqueries möglich:

Parameter Typ Erklärung
year integer 4-stelliges Jahr (z.B. 2011)
month|monthnum integer Monat (von 1 bis 12)
week|w integer Wochennummer (von 0 bis 53)
day integer Tag (von 1 bis 31)
hour integer Stunde (von 0 bis 23)
minute integer Minuten (von 0 bis 59)
second integer Sekunden (von 0 bis 59)
after string|array Suche »später als Datum X«
before string|array Suche »früher als Datum X«
dayofweek string|array Tag der Woche. (1 = Sonntag, 2 = Montag, …, 7 = Samstag)
dayofyear string|array Tag des Jahres. (1 bis 366)
compare string =, !=, >, >=, <, <=, IN, NOT IN, BETWEEN, NOT BETWEEN (Default: =)
inclusive bool Sollen after/ before inklusive oder exklusive sein
column string post_date, post_date_gmt, post_modified, post_modified_gmt,
comment_date, comment_date_gmt (Default: post_date)

Ärgerlich sind die doppelten Parameter für Woche ( week/ w) und Monat ( month/ monthnum). Hier hat man jeweils zwei zur Auswahl, aber wenn man beide setzt, werden auch beide innerhalb der WHERE-Klausel genommen. Ich habe dies schon als Bug gemeldet, spätestens mit WordPress 3.8 sollte das behoben worden sein.

Ein weiteres Problem ist die mangelnde Kontrolle: Wenn man beispielsweise den 370. Tag anfordert oder die 73. Minute, wird fehlerhaftes oder zumindest wirkungsloses SQL generiert. Auch das sollte bald behoben sein; siehe Bug #25834.

Zusätzlicher »geheimer« Parameter

Bei Betrachtung der Klasse ist mir noch ein weiterer Parameter dayofyear aufgefallen, der in der Dokumentation noch nicht erwähnt wird. Dieser erlaubt es, einen spezifischen Tag des Jahres zu suchen.

Inklusive-Parameter

Eine Besonderheit ist der inklusive-Parameter. Dieser bewirkt bei der Suche mit after und before eine exakte Suche (aus kleiner wird kleinergleich, aus größer wird größergleich), wenn er gesetzt ist. Leider stimmt die Angabe boolean nicht ganz, denn die Überprüfung des Parameters wird mit der PHP-Funktion empty durchgeführt. Würde ich als Wert also egal setzen, wäre das gleichzusetzen mit true.

before und after

Für die Werte der Parameter before und after gibt es zwei unterschiedliche Schreibweisen.

Variante 1: Array

In der ausführlichen Variante kann ein Array mit folgenden Werten gesetzt werden:

Parameter Typ Erklärung
year integer 4-stelliges Jahr (z.B. 2011)
month integer Monat (von 1 bis 12)
w integer Wochennummer (von 0 bis 53)
day integer Tag (von 1 bis 31)
hour integer Stunde (von 0 bis 23)
minute integer Minuten (von 0 bis 59)
second integer Sekunden (von 0 bis 59)

Hier haben wir wieder eine kleine Inkonsistenz: monthnum, week, dayofmonth und dayofyear fehlen.

Variante 2: Datum in Textform

Für die zweite Variante kann ein Datum in englischer Textform angegeben werden. Hier können beispielsweise solche Werte eingesetzt werden:

  • 10 September 2013
  • -1 day
  • -1 week

Dies ist sehr nützlich, wenn man nicht unnötig rechnen möchte, sondern einfach nur Zeiträume wie »letztes Jahr«, »letzte Woche« oder »vor 2 Tagen« angeben möchte. Eine Liste der erlaubten Textformen findet ihr in der offiziellen PHP-Dokumentation.

Beispiel

Erstelle eine WHERE-Klausel für alle Beiträge, die vor dem 01. Juli 2013 und zwischen dem 2. und 6. Wochentag geändert worden sind.

Erweiterung von WP_Query / get_posts

Die Klasse WP_Query wurde um neue Parameter zum internen Aufrufen der WP_Date_Query-Klasse erweitert. Folgende zwei Möglichkeiten haben wir, um unsere Datenbank-Anfrage um eine Datumssuche zu verfeinern:

Einfache Suche

Die einfache Suche läuft ähnlich wie bei der post_meta-Suche ab. Hier können folgende Parameter im Konstruktor der WP_Query-Klasse übergeben werden um nach einem Datum zu filtern:

Parameter Typ Erklärung
year integer 4-stelliges Jahr (z.B. 2011)
monthnum integer Monat (von 1 bis 12)
m integer Jahr-Monat-Kombination (z.B.: 201307)
w integer Wochennummer (von 0 bis 53)
day integer Tag (von 1 bis 31)
hour integer Stunde (von 0 bis 23)
minute integer Minuten (von 0 bis 59)
second integer Sekunden (von 0 bis 59)

Hier haben wir einige Lücken: So können wir nicht den Paramter month wie in der erweiterten Suche (siehe unten) verwenden, sondern monthnum. Das Gleiche gilt auch für die Woche, hier müssen wir w anstelle von week verwenden. Auch fehlt die Angabe der search_column (Default: post_date), sowie der compare-Parameter (Default: =).

Erweiterte Suche

Die erweiterte Suche ist ein mehrdimensionales Array (vergleichbar mit meta_query) um komplizierte Suchen mit mehreren Abhängigkeiten und Vergleichen zu erstellen. Folgende Parameter können hier verwendet werden:

  • date_query ( array)
    • relation ( string) – OR oder AND (Default: AND)
    • compare ( boolean) – =, !=, >, >=, <, <=, IN, NOT IN, BETWEEN, NOT BETWEEN (Default: =)
    • column ( string) – Spalte: post_date, post_date_gmt, post_modified, post_modified_gmt, comment_date, comment_date_gmt (Default: post_date)

Für die Parameterliste können alle oben aufgelisteten verwendet werden. Um die Parameter zu verknüpfen, können die Relationen AND oder OR verwendet werden. Der Parameter column kann in den Sub-Queries überschrieben werden.

Beispiele

In den unten gezeigten Beispielen kann auch anstelle von der Funktion get_posts() die WP_Query-Klasse verwendet werden. Die Argumente werden bei get_posts() 1:1 an WP_Query durchgereicht und zusätzlich gleich die Ergebnisse zurückgeliefert.

Lade alle Beiträge vom 30. Oktober 2012

Lade alle Beiträge von der aktuellen Woche

Lade alle Beiträge für den 47. und 215. Tag im Jahr 2012

Kleiner Hinweis: Der 47. Tag 2012 ist der 16. Februar und der 215. Tag ist ein 02. August. Wofür das gut ist, weiß ich aber auch (noch) nicht. 🙂

Lade alle Beiträge die älter als 1 Jahr, aber vor 1 Monat das letzte mal geändert worden sind

Lade alle Beiträge zwischen dem 01. September 12:00 Uhr und vor dem 10. September

Erweiterung der Klasse WP_Comment_Query/ get_comments()

Leider beschränkt sich die Erweiterung der Kommentar-API nur auf die »Erweiterte Suche«. Dennoch können wir nun anstelle umständlicher Filtern auf recht einfach Art und Weise unsere Kommentare laden. Hierzu ein kleines Vorher-Nachher-Beispiel.

Beispiel

Lade alle Kommentare die letzte Woche gepostet worden sind.

Vorher

Nachher

Fazit

Mit der neuen Erweiterung lassen sich einfach und schnell neue SQL-Queries erzeugen. Ebenso muss keine Rücksicht mehr auf die Datumsformatierung genommen werden. Leider fehlt die komplette Implementierung bei der User-API. Hier gibt es ja auch ein Registrierungsdatum user_registered, mit dem man hantieren könnte. Um sinnvoll damit zu arbeiten, müssten wir uns in die WP_User_Query-Klasse mit pre_user_query und zusätzlich noch in die WP_Date_Query-Klasse in date_query_valid_columns einhängen und die user_registered-Spalte hinzuzufügen. Auch die Implementierung in der WP_Comment_Query-Klasse ist nicht vollständig und die doppelten Parameter sollten unbedingt noch abgefangen werden. Ich hoffe, dass in zukünftigen Releases noch einmal Hand angelegt wird.

Beitrag teilen

Author Avatar

Hi! Mein Name ist Chris und ich arbeite als leidenschaftlicher Webentwickler im X-Team der Inpsyde GmbH. Meine Spezialgebiete sind die Backend- und Frontendentwicklung. Wenn ich nicht gerade über Barrierefreiheit und Usability diskutiere, bin ich auf Google+ unterwegs. In meiner Freizeit absolviere ich ein Informatikfernstudium, treibe gern und viel Sport, verschlinge ein Buch nach dem Anderen und blogge auf www.chrico.info.

Auch interessant:

woonews19

WooCommerce Wochenrückblick #19: Google Analytics, kostenlose Themes und neue Kennzeichnungspflicht

von Michael Firnkes

Die Shop-Analyse ist wichtig, muss aber rechtlich abgesichert werden. Für WooCommerce gibt es neue Theme-Inspirationen und ein neues German Market. Dies u ...

Weiterlesen
slack-blog

Neues Plugin: Slack Connector - Verbinde WordPress, WooCommerce und Slack

von Michael Firnkes

Anfangs wollten wir lediglich unsere eigenen Slack-Prozesse optimieren. Mit automatisierten Benachrichtigungen aus dem MarketPress-Shop, dem Blog und unser ...

Weiterlesen
woo26

WooCommerce 2.6: Deutlich mehr Versandoptionen, bessere Bestellübersicht

von Michael Firnkes

WooCommerce 2.6 "Zipping Zebra" steht kurz vor der Veröffentlichung, das Release ist für kommenden Dienstag geplant. Wir zeigen dir, was sich für dich ...

Weiterlesen
wp-geburtstag

13 Jahre WordPress - 13 Mal ein WooCommerce- oder Blog-Theme gewinnen

von Michael Firnkes

WordPress wird 13. Und wiederholt seine Erfolgsgeschichte: Mit WooCommerce. Feiere mit und gewinne eines unserer Top-Themes. WordPress hat einen rasante ...

Weiterlesen

Kommentare

4 Kommentare

  1. #3

    Funktioniert die date_query eigentlich auch mit eigens erstellten Datumsfeldern. Ich habe nämlich ein zusätzliches Datums-Feld mit ACF erstellt und kämpfe gerade mit der Abfrage.

    • #4

      Hallöchen Steve,

      natürlich geht die WP_Date_Query nicht standardmäßig auf Custom Fields, sondern nur auf 'post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt', 'comment_date', 'comment_date_gmt', 'user_registered'. Wenn du eigene Custom fields hinzufügen möchtest, kannst du den Hook date_query_valid_columns verwenden:

      Anschließend kannst du dein Custom Field entsprechend dem Konstruktor als zweiten Parameter mit übergeben:

      Viele Grüße,
      Chris

2 Pingbacks

  1. Endlich! Date Queries! Funktion "Zeige Posts von Datum A bis Datum B" bald im Core! | WP-Entwickler.at
  2. WordPress-Newsletter Nr. 130 | perun.net

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

Du kannst folgende HTML Tags verwenden: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">