Meta-Abfrage mit mehreren Schlüsseln verwenden und Werte vergleichen

Ich vermute, dass ich damit den Mond am Stiel fragen kann, aber:

Ich habe einen Filter für meinen benutzerdefinierten Post-Typ. Der Filter verwendet Standardtaxonomien, die an shows angehängt shows , aber er erlaubt dem Benutzer auch, nach Venue zu filtern, was ein Metawert für jede Show oder nach Monat ist, da jeder Show ein Startdatum zugeordnet ist.

Das Problem, auf das ich gestoßen bin, ist, dass einige Shows mehrere Monate umfassen können; Starten Sie den Lauf im November 2014 und beenden Sie ihn im Dezember. Dafür speichere ich die Meta-Werte wie folgt:

 startdate => 20141225 enddate => 20141224 

Im Idealfall, wenn jemand Shows für Dezember 2014 filtert, möchte ich Shows anzeigen, die beide im Dezember beginnen oder vor Ende Dezember enden. Das Problem ist, dass ich, weil ich auch nach dem venue meta_value mit relation => 'AND' suche, keine Möglichkeit finde, nach [pseudocode] WHERE venue == 'royal-playhouse' AND ((startdate BETWEEN array(20141201, 20141231)) OR (enddate BETWEEN array(20141201, 20141231))) .

Ich verwende einen pre_get_posts Filter, um die übergebenen $query Argumente zu ändern, und es ist erwähnenswert, dass es noch ein paar meta_value-Felder gibt, die auch mit dem Filter verwendet werden (wie z. B. show type, accessibility usw.). Hier ist eine vereinfachte Version meines Codes (der momentan perfekt funktioniert, aber nur auf startdate prüft):

 function showDates_orderQuery($query) { if ($query->is_main_query() && !is_admin() && is_post_type_archive('showdates')) { $queryVenue = $query->query_vars['venue']; $queryMonth = $query->query_vars['month']; $metaQuery = array(); // Venue meta if ($queryVenue) { $metaQuery[] = array( 'key' => 'venue', 'value' => array($queryVenue), 'compare' => 'IN', ); } // Month meta if ($queryMonth) { $monthEpoch = strtotime($queryMonth); $formattedQueryMonth = date('Ymd', $monthEpoch); $formattedEndOfQueryMonth = date('Ymt', $monthEpoch); $metaQuery['relation'] = 'AND'; // Set because we want to check for shows from a venue AND by the given month $metaQuery[] = array( 'key' => 'startdate', 'value' => array($formattedQueryMonth, $formattedEndOfQueryMonth), 'compare' => 'BETWEEN', 'type' => 'DATE' ); } if ($metaQuery) { $query->set('meta_query', $metaQuery); } $query->set('meta_key', 'startdate'); $query->set('orderby', 'meta_value'); $query->set('order', 'ASC'); } } add_action('pre_get_posts', 'showDates_orderQuery'); 

Irgendwelche Ideen, wie ich das vielleicht erreichen könnte, wären dankbar aufgenommen.

Solutions Collecting From Web of "Meta-Abfrage mit mehreren Schlüsseln verwenden und Werte vergleichen"

Abhängig von deiner Zeitlinie oder davon, wie sehr du am Rande leben möchtest, gab es einige großartige Verbesserungen, die in 4.1 eingeführt werden sollen und die dir ermöglichen werden, genau das zu tun, was du tun willst. Wenn Sie ein bisschen am Rande leben möchten, könnten Sie mit der 4.1 Beta entwickeln und zum Zeitpunkt des Starts auf die Version wechseln (stellen Sie sicher, dass Sie Fehlerberichte einreichen, wenn Sie sie finden :))

Hier ist ein Link zum Make-Post, der etwas detaillierter geht: https://make.wordpress.org/core/2014/10/20/update-on-query-improvements-in-4-1/

Du kannst keinen Weg finden, das zu tun, weil es keinen solchen Weg gibt. Es ist nicht möglich, ANDs und ORs mit meta_query zu mischen. Das Abfragesystem ist großartig, aber nicht allumfassend. Sie müssen mehrere Abfragen verwenden oder das SQL selbst filtern.

Weil ich ein kompletter Idiot bin, habe ich völlig vergessen, dass ich vor über einem Jahr meine eigene Frage beantwortet habe .

Ich hatte Schwierigkeiten, den posts_join Filter zum Verhalten zu bringen (ich habe generell Probleme mit INNER JOIN s) und schaute stattdessen auf den posts_where Filter. Das Hauptproblem dabei ist, dass Sie keine anderen Argumente als die existierende $where Bedingung übergeben können. und in diesem Fall wollte ich, dass es nicht-globale Variablen verwendet.

Die Antwort bestand darin, eine inline anonyme Lambda-function für den posts_where Filter zu verwenden:

 if ($queryMonth) { $monthEpoch = strtotime($queryMonth); $formattedQueryMonth = date('Ymd', $monthEpoch); $formattedEndOfQueryMonth = date('Ymt', $monthEpoch); $monthOptions = array( 'monthstart' => $formattedQueryMonth, 'monthend' => $formattedEndOfQueryMonth, ); $monthFilter = function ($where = '') use ($monthOptions) { global $wpdb; $where .= " AND (($wpdb->postmeta.meta_key = 'startdate' AND $wpdb->postmeta.meta_value >= '" . $monthOptions['monthstart'] . "') AND ($wpdb->postmeta.meta_key = 'startdate' AND $wpdb->postmeta.meta_value < = '" . $monthOptions['monthend'] . "')) "; $where .= " OR (($wpdb->postmeta.meta_key = 'enddate' AND $wpdb->postmeta.meta_value >= '" . $monthOptions['monthstart'] . "') AND ($wpdb->postmeta.meta_key = 'enddate' AND $wpdb->postmeta.meta_value < = '" . $monthOptions['monthend'] . "')) "; return $where; }; add_filter('posts_where', $monthFilter); } 

Mit etwas Glück sollte diese Methode in den nächsten Wochen dank der bevorstehenden Veröffentlichung von 4.1 - dank @jmusal für den Heads-up - völlig überflüssig werden .