Was Sie wollen, ist möglich, erfordert jedoch, dass Sie sich mit SQL befassen, was ich nach Möglichkeit vermeiden möchte (nicht, weil ich es nicht weiß, ich bin ein fortgeschrittener SQL-Entwickler, sondern weil Sie in WordPress die API verwenden möchten, wann immer dies möglich ist um zukünftige Kompatibilitätsprobleme im Zusammenhang mit zukünftigen möglichen Änderungen der Datenbankstruktur zu minimieren.)
SQL mit einem UNION
Operator ist eine Möglichkeit
So verwenden Sie SQL , was Sie brauchen ist ein UNION
Operator in Ihrer Abfrage, so etwas wie dies sind Ihre Kategorie Schnecken unter der Annahme "category-1"
, "category-1"
und "category-3"
:
SELECT * FROM wp_posts WHERE ID IN (
SELECT tr.object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='category-1'
LIMIT 5
UNION
SELECT tr.object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='category-2'
LIMIT 5
UNION
SELECT tr.object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='category-3'
LIMIT 5
)
Sie können SQL UNION mit einem posts_join
Filter verwenden
Mit den oben genannten Informationen können Sie entweder einfach direkt anrufen oder einen posts_join
Filter-Hook wie folgt verwenden. Hinweis: Ich verwende einen PHP-Heredoc. Stellen Sie daher sicher, dass der HeredocSQL;
bündig ist. Beachten Sie auch, dass ich eine globale Variable verwendet habe, damit Sie die Kategorien außerhalb des Hooks definieren können, indem Sie die Kategorie-Slugs in einem Array auflisten. Sie können diesen Code in ein Plugin oder in die functions.php
Datei Ihres Themas einfügen :
<?php
global $top_5_for_each_category_join;
$top_5_for_each_category_join = array('category-1','category-2','category-3');
add_filter('posts_join','top_5_for_each_category_join',10,2);
function top_5_for_each_category_join($join,$query) {
global $top_5_for_each_category_join;
$unioned_selects = array();
foreach($top_5_for_each_category_join as $category) {
$unioned_selects[] =<<<SQL
SELECT object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='{$category}'
LIMIT 5
SQL;
}
$unioned_selects = implode("\n\nUNION\n\n",$unioned_selects);
return $join . " INNER JOIN ($unioned_selects) categories ON wp_posts.ID=categories.object_id " ;
}
Aber es kann Nebenwirkungen geben
Natürlich führt die Verwendung der Abfrageänderungs-Hooks wie posts_join
immer zu Nebenwirkungen, da sie global auf Abfragen wirken. Daher müssen Sie Ihre Änderungen normalerweise in eine einbinden if
, die sie nur bei Bedarf verwendet und auf welche Kriterien getestet werden kann.
Stattdessen auf Optimierung setzen?
Ich gehe jedoch davon aus, dass es bei Ihrer Frage mehr um Optimierung geht als darum, eine Top-5-Zeit-3-Abfrage durchführen zu können, oder? Wenn dies der Fall ist, gibt es vielleicht andere Optionen, die die WordPress-API verwenden?
Besser die Transienten-API für das Caching verwenden?
Ich gehe davon aus, dass sich Ihre Beiträge nicht so oft ändern werden, richtig? Was ist, wenn Sie die drei (3) Abfragetreffer regelmäßig akzeptieren und die Ergebnisse dann mithilfe der Transienten-API zwischenspeichern ? Sie erhalten wartbaren Code und eine hervorragende Leistung. Ein gutes Stück besser als die UNION
obige Abfrage, da WordPress die Liste der Beiträge als serialisiertes Array in einem Datensatz der wp_options
Tabelle speichert .
Sie können das folgende Beispiel verwenden und im Stammverzeichnis Ihrer Website test.php
ablegen, um dies zu testen:
<?php
$timeout = 4; // 4 hours
$categories = array('category-1','category-2','category-3');
include "wp-load.php";
$category_posts = get_transient('top5_posts_per_category');
if (!is_array($category_posts) || count($category_posts)==0) {
echo "Hello Every {$timeout} hours!";
$category_posts = array();
foreach($categories as $category) {
$posts = get_posts("post_type=post&numberposts=5&taxonomy=category&term={$category}");
foreach($posts as $post) {
$category_posts[$post->ID] = $post;
}
}
set_transient('top5_posts_per_category',$category_posts,60*60*$timeout);
}
header('Content-Type:text/plain');
print_r($category_posts);
Zusammenfassung
Ja, Sie können zwar das tun, wonach Sie gefragt haben, indem Sie eine SQL- UNION
Abfrage und den posts_join
Filter-Hook verwenden, den Sie wahrscheinlich besser mit Caching mit der Transients-API anbieten .
Hoffe das hilft?