私はmeta_keyの値で並べられた一連の投稿を持っています。必要に応じて、それらはメニュー順で並べることもできます。
Next/prev postリンク(next_post_link
、previous_post_link
、posts_nav_link
はすべて年代順に移動します。このデフォルトの動作は理解できますが、変更方法がわかりません。link-templateの隣接リンクにマッピングされていることがわかりました。 php、しかしそれはかなりハードコードされているように見え始めますそれを置き換えるために最初からこれを書き直すことをお勧めしますか、それともより良い解決策があります。
隣接する(次の/前の)投稿の「ソート」順序は、実際にはソートの「順序」ではありません。これはリクエスト/ページごとの個別のクエリです。 しかし post_date
- または現在表示されているオブジェクトとして階層型の投稿がある場合は投稿の親でクエリをソートします。
next_post_link()
の内部を見ると、それは基本的に adjacent_post_link()
のAPIラッパーであることがわかります。後者の関数は、$previous
引数/ flagをget_adjacent_post()
に設定して内部的に bool(true|false)
を呼び出し、次または前の投稿リンクを取得します。
もっと深く掘り下げると、 get_adjacent_post()
ということがわかります。 ソースリンク は、その出力用にいくつかのNiceフィルタを持っています(別名クエリ結果):(フィルタ名/引数)
"get_{$adjacent}_post_join"
$join
// Only if `$in_same_cat`
// or: ! empty( $excluded_categories`
// and then:
// " INNER JOIN $wpdb->term_relationships AS tr
// ON p.ID = tr.object_id
// INNER JOIN $wpdb->term_taxonomy tt
// ON tr.term_taxonomy_id = tt.term_taxonomy_id";
// and if $in_same_cat then it APPENDS:
// " AND tt.taxonomy = 'category'
// AND tt.term_id IN (" . implode(',', $cat_array) . ")";
$in_same_cat
$excluded_categories
"get_{$adjacent}_post_where"
$wpdb->prepare(
// $op = $previous ? '<' : '>'; | $current_post_date
"WHERE p.post_date $op %s "
// $post->post_type
."AND p.post_type = %s "
// $posts_in_ex_cats_sql = " AND tt.taxonomy = 'category'
// AND tt.term_id NOT IN (" . implode($excluded_categories, ',') . ')';
// OR empty string if $in_same_cat || ! empty( $excluded_categories
."AND p.post_status = 'publish' $posts_in_ex_cats_sql "
",
$current_post_date,
$post->post_type
)
$in_same_cat
$excluded_categories
"get_{$adjacent}_post_sort"
"ORDER BY p.post_date $order LIMIT 1"`
それであなたはそれでalotをすることができます。それはWHERE
節、ならびにJOIN
edテーブルおよびORDER BY
ステートメントのフィルタリングから始まります。
結果は現在のリクエストのためにメモリにキャッシュされるので、単一のページでこの関数を複数回呼び出しても追加のクエリは追加されません。
コメントで @StephenHarris が指摘したように、SQLクエリを構築するときに役に立つかもしれないコア関数があります: get_meta_sql()
- 例 Codex 内。基本的にこの関数はWP_Query
で使われるメタSQLステートメントを構築するためだけに使われますが、この場合(あるいは他の人)にも使うことができます。あなたがそれに投入する引数は配列であり、それはWP_Query
に追加するものと全く同じです。
$meta_sql = get_meta_sql(
$meta_query,
'post',
$wpdb->posts,
'ID'
);
戻り値は配列です。
$sql => (array) 'join' => array(),
(array) 'where' => array()
そのため、コールバックで$sql['join']
と$sql['where']
を使用できます。
あなたの場合、最も簡単なことは小さな(mu)プラグインかthemes functions.phpファイルでそれを傍受して$adjacent = $previous ? 'previous' : 'next';
変数と$order = $previous ? 'DESC' : 'ASC';
変数に応じて変更することです。
そのため、フィルタ名は次のとおりです。
get_previous_post_join
、get_next_post_join
get_previous_post_where
、get_next_post_where
get_previous_post_sort
、get_next_post_sort
...そしてフィルタコールバックは(たとえば)次のようになります。
<?php
/** Plugin Name: (#73190) Alter adjacent post link sort order */
function wpse73190_adjacent_post_sort( $orderby )
{
return "ORDER BY p.menu_order DESC LIMIT 1";
}
add_filter( 'get_previous_post_sort', 'wpse73190_adjacent_post_sort' );
add_filter( 'get_next_post_sort', 'wpse73190_adjacent_post_sort' );
カイザーの答え は素晴らしく徹底的ですが、あなたのmenu_order
があなたの年代順に一致しない限り、ORDER BY句を変更するだけでは不十分です。
私はこれを信用することはできませんが、 this Gist に次のコードを見つけました。
<?php
/**
* Customize Adjacent Post Link Order
*/
function wpse73190_Gist_adjacent_post_where($sql) {
if ( !is_main_query() || !is_singular() )
return $sql;
$the_post = get_post( get_the_ID() );
$patterns = array();
$patterns[] = '/post_date/';
$patterns[] = '/\'[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\'/';
$replacements = array();
$replacements[] = 'menu_order';
$replacements[] = $the_post->menu_order;
return preg_replace( $patterns, $replacements, $sql );
}
add_filter( 'get_next_post_where', 'wpse73190_Gist_adjacent_post_where' );
add_filter( 'get_previous_post_where', 'wpse73190_Gist_adjacent_post_where' );
function wpse73190_Gist_adjacent_post_sort($sql) {
if ( !is_main_query() || !is_singular() )
return $sql;
$pattern = '/post_date/';
$replacement = 'menu_order';
return preg_replace( $pattern, $replacement, $sql );
}
add_filter( 'get_next_post_sort', 'wpse73190_Gist_adjacent_post_sort' );
add_filter( 'get_previous_post_sort', 'wpse73190_Gist_adjacent_post_sort' );
WP.SEの関数名を変更しました。
ORDER BY句のみを変更した場合でも、クエリは現在の投稿日よりも大きいまたは小さい投稿を検索します。投稿が年代順になっていないと、正しい投稿が得られません。
これは、orderby句を修正することに加えて、where句を変更して、menu_orderが現在の投稿のmenu_orderよりも大きいか小さい投稿を探すようにします。
また、orderby節はDESCを使用するようにハードコーディングしてはいけません。次の投稿リンクと前の投稿リンクのどちらを使用しているかに基づいて切り替える必要があるためです。
function wpse73190_Gist_adjacent_post_sort( $sql ) {
$pattern = '/post_date/';
$replacement = 'menu_order';
return preg_replace( $pattern, $replacement, $sql );
}
add_filter( 'get_next_post_sort', 'wpse73190_Gist_adjacent_post_sort' );
add_filter( 'get_previous_post_sort', 'wpse73190_Gist_adjacent_post_sort' );
成功せずにフックしようとしました。私の設定の問題にすぎないかもしれませんが、フックを機能させることができない人のために、これが最も簡単な解決策です:
<?php
$all_posts = new WP_Query(array(
'orderby' => 'menu_order',
'order' => 'ASC',
'posts_per_page' => -1
));
foreach($all_posts->posts as $key => $value) {
if($value->ID == $post->ID){
$nextID = $all_posts->posts[$key + 1]->ID;
$prevID = $all_posts->posts[$key - 1]->ID;
break;
}
}
?>
<?php if($prevID): ?>
<span class="prev">
<a href="<?= get_the_permalink($prevID) ?>" rel="prev"><?= get_the_title($prevID) ?></a>
</span>
<?php endif; ?>
<?php if($nextID): ?>
<span class="next">
<a href="<?= get_the_permalink($nextID) ?>" rel="next"><?= get_the_title($nextID) ?></a>
</span>
<?php endif; ?>
@SzabolcsPállの answer に基づいて、このユーティリティクラスをヘルパーメソッドで作成して、メニューの順番でタイプの投稿を取得し、メニューの順番で前後の投稿も取得できるようにしました。現在の投稿が最初の投稿であるか最後の投稿であるかを確認するための条件をそれぞれ最後または最初の投稿に追加しました。
例えば:
// $currentPost is first by menu order
getPreviousPostByMenuOrder($postType, $$currentPost->ID)
// returns => last post by menu order
// $currentPost is last by menu order
getPreviousPostByMenuOrder($postType, $$currentPost->ID)
// returns => first post by menu order
フルクラス:
class PostMenuOrderUtils {
public static function getPostsByMenuOrder($postType){
$args =[
'post_type' => $postType,
'orderby' => 'menu_order',
'order' => 'ASC',
'posts_per_page' => -1
];
$posts = get_posts($args);
return $posts;
}
public static function getNextPostByMenuOrder($postType, $postID){
$posts = self::getPostsByMenuOrder($postType);
$nextPost = null;
foreach($posts as $key => $value) {
if($value->ID == $postID){
$nextPost = $posts[$key] !== end($posts) ? $posts[$key + 1] : $posts[0];
break;
}
}
return $nextPost;
}
public static function getPreviousPostByMenuOrder($postType, $postID){
$posts = self::getPostsByMenuOrder($postType);
$prevPost = null;
foreach($posts as $key => $value) {
if($value->ID == $postID){
$prevPost = $key !== 0 ? $posts[$key - 1] : end($posts);
break;
}
}
return $prevPost;
}
}
私はこの小さなプラグインが本当に便利だと思います: http://wordpress.org/plugins/wp-query-powered-adjacent-post-link/
WP_Query Powered Adjacent Post Linkは開発者向けのプラグインです。これはWordPressに
wpqpapl();
という関数を追加したもので、前と次の投稿に関する情報を現在のものに戻すことができます。WP_Query
クラスで使用するための引数を受け入れます。
これは私のために働いた:
add_filter( 'get_previous_post_where', 'so16495117_mod_adjacent_bis' );
add_filter( 'get_next_post_where', 'so16495117_mod_adjacent_bis' );
function so16495117_mod_adjacent_bis( $where ) {
global $wpdb;
return $where . " AND p.ID NOT IN ( SELECT post_id FROM $wpdb->postmeta WHERE ($wpdb->postmeta.post_id = p.ID ) AND $wpdb->postmeta.meta_key = 'archive' AND $wpdb->postmeta.meta_value = 1 )";
}