これを書いている間、私はXY問題を避けるために最善を尽くします。
私はauthor.php
テンプレートを作成しようとしています:
projects
(CPT)ユーザーがクレジットされている(CPTのACFフィールドを介して割り当てられる)author.php
テンプレート)私の最初の試み、そしてそれは大抵うまくいきました。このアプローチをやめさせたのは、ページネーションです。それについては後で詳しく説明します。 3つのクエリがありました。
3番目は、array_unique( array_merge($query1, $query2) )
を介してpost__in
を使用して、これら2つのクエリからの投稿を日付ごとにまとめて表示しました。
<?php
get_header();
global $wp_query;
if( !isset($whose_ID) ) {
$whose_ID = $wp_query->queried_object->data->ID;
}
/*
|==========================================================================
| First Query gets all posts by author
|==========================================================================
*/
$args = array(
'author' => $whose_ID,
'post_type' => 'post'
);
$query1 = new WP_Query( $args );
$first_set = array();
foreach($query1->posts as $post) {
$first_set[] = $post->ID;
}
wp_reset_postdata();
/*
|==========================================================================
| Second Query gets all Projects that are credited to author
|==========================================================================
*/
$args2 = array(
'post_type' => 'projects',
'meta_key' => 'project_credits_%_user',
'meta_value' => $whose_ID,
);
$query2 = new WP_Query( $args2 );
$second_set = array();
foreach($query2->posts as $post) {
$second_set[] = $post->ID;
}
wp_reset_postdata();
/*
|==========================================================================
| Then the two queries are merged to create a bag of posts to grab from
|==========================================================================
|
| What sucks about this is the $third_query_allowed. I had to figure out
| a way to make sure that the query didn't run on an empty array. Bah.
|
*/
$third_query_allowed = true;
if( !empty($first_set) && !empty($second_set) ) {
$merged_queries = array_unique( array_merge( $first_set, $second_set ) );
} elseif (!empty($first_set) && empty($second_set) ) {
$merged_queries = $first_set;
} elseif ( empty($first_set) && !empty($second_set) ) {
$merged_queries = $second_set;
} else {
$merged_queries = array();
$third_query_allowed = false;
}
/*
|==========================================================================
| So then this third query does the work of getting all the posts and
| displaying them on the author page.
|==========================================================================
*/
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args3 = array(
'post_type' => array( 'post', 'projects' ),
'post__in' => $merged_queries,
'orderby' => 'post__in',
'posts_per_page' => 2,
'paged' => $paged
);
$user_connected_to_post = new WP_Query( $args3 ); ?>
<div id="primary" class="">
<main id="main" class="site-main" role="main">
<?php
// ACF Helper
$search = 'user_'.$whose_ID;
// Header Info
// All of this Works!!
$name = get_the_author_meta( 'display_name', $whose_ID );
$job_title = get_field( 'job_title', $search );
$user_favorite_color = get_field( 'user_favorite_color', $search );
$user_featured_image = get_field( 'user_featured_image', $search );
$user_still_image = get_field( 'user_still_image', $search );
$user_gif = get_field( 'user_gif', $search );
$user_mp4 = get_field( 'user_mp4', $search );
if(!empty($user_featured_image) && !empty($user_favorite_color)) {
$header_styles = "style=\"background:url('".$user_featured_image['url']."') no-repeat scroll center center ".$user_favorite_color."; background-size: 100% auto;\"";
} elseif(!empty($user_featured_image) && empty($user_favorite_color)) {
$header_styles = "style=\"background:url('".$user_featured_image['url']."') no-repeat scroll center center #efefef; background-size: 100% auto;\"";
} elseif(empty($user_featured_image) && !empty($user_favorite_color)) {
$header_styles = "style=\"background-color:".$user_favorite_color."\"";
}
?>
<div class="container-fluid">
<div class="author-page-header row">
<div class="author-page-bg col-sm-12" <?php echo $header_styles; ?>></div>
<video class="img-circle the-vid author-page-img" width="250" height="250" loop="loop" muted="" autoplay="autoplay" poster="<?php echo $user_still_image['url']; ?>">>
<source type="video/mp4" data-source="<?php echo $user_mp4['url']; ?>">
</video>
<img class="img-circle the-img author-page-img" alt="" data-source="<?php echo $user_gif['url']; ?>">
</div>
</div>
<div class="container">
<div class="row">
<header class="author-page-name lower-divider text-center">
<h1><?php echo $name; ?></h1>
<h3><?php echo $job_title; ?></h3>
</header><!-- .author-name -->
</div>
<div class="row">
<div class="author-page-social">
<?php
// ACF Bug is keeping this from working at the moment.
echo three_sons_social_list( $search, array( 'bellyflop', 'dale-earnhardt' ) ); ?>
</div>
</div>
<div class="row upper-divider">
<div class="col-xs-10 col-xs-offset-1 col-sm-8 col-sm-offset-2 author-page-bio">
<p><?php echo get_the_author_meta( 'description', $whose_ID ); ?></p>
</div>
</div>
<?php
/*
|==========================================================================
| here's all the author's posts (this works)
|==========================================================================
*/
if( $third_query_allowed === true ){
if ( $user_connected_to_post->have_posts() ) : ?>
<div class="row masonry-grid">
<?php while ( $user_connected_to_post->have_posts() ) : $user_connected_to_post->the_post();
if($post->post_type === "projects") {
get_template_part( 'lib/partials/projects', 'masonry_item' );
} else {
// default post listing
get_template_part( 'lib/partials/content', 'masonry_item' );
}
endwhile; ?>
</div> <!-- .masonry-grid -->
<?php // THIS IS THE THING THAT DID NOT WORK ?>
<div class="nav-previous alignleft"><?php next_posts_link( 'Older posts', $user_connected_to_post->max_num_pages ); ?></div>
<div class="nav-next alignright"><?php previous_posts_link( 'Newer posts', $user_connected_to_post->max_num_pages ); ?></div>
<?php endif;
wp_reset_postdata();
wp_reset_query();
} ?>
</div><!-- .container -->
</main><!-- #main -->
</div><!-- #primary -->
<?php get_footer();
404なしではページネーションを機能させることができなかったため、アプローチを変更しました。
author.php
テンプレートがメインクエリを使用する方法に関するいくつかの提案を読んだ後、pre_get_posts
アクションでメインループを変更する関数に移行しました。すべてのクエリを独自の関数に移動し、著者のページに表示したい投稿の配列のみを返しました。 $query->set()
を使用して、クエリの1つが無限ループであるという問題に遭遇しました。私のコードにはforeach
ループもwhile
ループもなかったので、それはまだ謎です。私は無限ループとロシア人形の機能のためにこの試みを放棄しました。
最終的に私はこのコードに着きましたが、理論的には動作するはずですが(動作しません)。 3つの直接$wpdb
クエリが表示されます。不可解に無限のループで45分間Vagrantボックスを正常に無効にしたので、可能な限り無駄のないメモリ節約クエリを作成することにしました。これが実際に良いかどうかはわかりませんが、私がやったことです。それはポイントではありません。
merged_author_archive()
:
function merged_author_archive( &$query ) {
// Only do this weird shit for the author pages.
if ( $query->is_author ) {
// Start with a fresh query (Whether this line is here or not makes no difference)
wp_reset_query();
global $wpdb;
// holy shit this is so Gd complex it drives me crazy.
// since the only thing that gets passed to wordpress on author.php (apparently) to start is the author name, that's what we're going to query.
$author_Nice_name = $query->query['author_name'];
// Get the Author ID from the nicename.
$author_ID = $wpdb->get_results("SELECT id FROM $wpdb->users WHERE user_nicename LIKE '$author_Nice_name'");
$author_ID = $author_ID[0]->id;
// so we can get this on author pages.
set_query_var( 'three_sons_author_id', $author_ID );
// Get the IDs from posts authored and then save all the ids to $first_set
$authored_posts = $wpdb->get_results("SELECT id FROM $wpdb->posts WHERE post_author = '$author_ID' AND post_type = 'post'");
foreach ($authored_posts as $post) {
$first_set[] = $post->id;
}
// Get the IDS from the projects credited
$credited_projs = $wpdb->get_results("SELECT post_id FROM $wpdb->postmeta WHERE meta_key LIKE 'project_credits_%_user' AND meta_value = '$author_ID'");
foreach ($credited_projs as $proj) {
$second_set[] = $proj->post_id;
}
// First case: Both queries resulted in an array that wasn't empty.
if( !empty($first_set) && !empty($second_set) ) {
$just_these_posts = array_unique( array_merge( $first_set, $second_set ) );
}
// Second Case: Posts were not empty, but Projects were
elseif (!empty($first_set) && empty($second_set) ) {
$just_these_posts = $first_set;
}
// Third Case: Posts were empty, but Projects were not.
elseif ( empty($first_set) && !empty($second_set) ) {
$just_these_posts = $second_set;
}
// Here's the new $wp_query. We need to define the array of posts, and the post ids to send to the author page. Then we're done here.
$query->set( 'post_type', array('post', 'projects') );
$query->set( 'post__in', $just_these_posts );
}
// if it's not an author page, remove the action.
remove_action( 'pre_get_posts', 'three_sons_merged_author_archive' );
}
add_action( 'pre_get_posts', 'three_sons_merged_author_archive' );
...およびその後のauthor.php
:
get_header();
// getting the author ID from the query. was set in lib/inc/author-functions.php
$whose_ID = get_query_var('three_sons_author_id');
// Header Info
$name = get_the_author_meta( 'display_name', $whose_ID );
// ACF
$search = 'user_'.$whose_ID;
$job_title = get_field( 'job_title', $search );
$user_favorite_color = get_field( 'user_favorite_color', $search );
$user_featured_image = get_field( 'user_featured_image', $search );
$user_still_image = get_field( 'user_still_image', $search );
$user_gif = get_field( 'user_gif', $search );
$user_mp4 = get_field( 'user_mp4', $search );
if(!empty($user_featured_image) && !empty($user_favorite_color)) {
$header_styles = "style=\"background:url('".$user_featured_image['url']."') no-repeat scroll center center ".$user_favorite_color."; background-size: 100% auto;\"";
} elseif(!empty($user_featured_image) && empty($user_favorite_color)) {
$header_styles = "style=\"background:url('".$user_featured_image['url']."') no-repeat scroll center center #efefef; background-size: 100% auto;\"";
} elseif(empty($user_featured_image) && !empty($user_favorite_color)) {
$header_styles = "style=\"background-color:".$user_favorite_color."\"";
}
?>
<div id="primary" class="">
<main id="main" class="site-main" role="main">
<div class="container-fluid">
<div class="author-page-header row">
<div class="author-page-bg col-sm-12" <?php echo $header_styles; ?>></div>
<video class="img-circle the-vid author-page-img" width="250" height="250" loop="loop" muted="" autoplay="autoplay" <? /*poster="<?php echo $user_still_image['url']; ?>" */ ?>>
<source type="video/mp4" data-source="<?php echo $user_mp4['url']; ?>">
</video>
<img class="img-circle the-img author-page-img" alt="" data-source="<?php echo $user_gif['url']; ?>">
</div>
</div>
<div class="container">
<div class="row">
<header class="author-page-name lower-divider text-center">
<h1><?php echo $name; ?></h1>
<h3><?php echo $job_title; ?></h3>
</header><!-- .author-name -->
</div>
<div class="row">
<div class="author-page-social">
<!-- just for now... -->
<p class="text-center">Social Links will go here but they're currently broken for authors.</p>
<?php // echo three_sons_social_list( $search, array( 'bellyflop', 'dale-earnhardt' ) ); ?>
</div>
</div>
<div class="row upper-divider">
<div class="col-xs-10 col-xs-offset-1 col-sm-8 col-sm-offset-2 author-page-bio">
<p><?php echo get_the_author_meta( 'description', $whose_ID ); ?></p>
</div>
</div>
<?php
if ( have_posts() ) : ?>
<div class="row masonry-grid">
<?php while ( have_posts() ) : the_post();
if($post->post_type === "projects") {
get_template_part( 'lib/partials/projects', 'masonry_item' );
} else {
// default post listing
get_template_part( 'lib/partials/content', 'masonry_item' );
}
endwhile; ?>
</div> <!-- .masonry-grid -->
<div class="nav-previous alignleft"><?php next_posts_link( 'Older posts' ); ?></div>
<div class="nav-next alignright"><?php previous_posts_link( 'Newer posts' ); ?></div>
<?php endif; ?>
</div><!-- .container -->
</main><!-- #main -->
</div><!-- #primary -->
<?php wp_reset_query();
get_footer();
基本的に、私はこの最新のコードshouldが機能すると信じています。しかし、そうではありません。何かが翻訳されていません。 author.php
でvar_dump($wp_query); die;
を実行すると、次のように表示されます(無関係なビットまたは機密ビットを削除しました)。
object(WP_Query)#258 (51) {
["query"]=>
array(1) {
["author_name"]=>
string(15) "author-slug"
}
["query_vars"]=>
array(64) {
["author_name"]=>
string(15) "author-slug"
["post__in"]=>
array(9) {
[0]=>
string(1) "1"
[1]=>
string(3) "102"
[2]=>
string(3) "160"
[3]=>
string(3) "196"
[4]=>
string(3) "199"
[5]=>
string(3) "201"
[6]=>
string(3) "206"
[7]=>
string(3) "162"
[8]=>
string(3) "198"
}
["three_sons_author_id"]=>
string(1) "3"
["post_type"]=>
array(2) {
[0]=>
string(4) "post"
[1]=>
string(8) "projects"
}
["order"]=>
string(4) "DESC"
}
["date_query"]=>
bool(false)
["queried_object"]=>
object(WP_User)#152 (7) {
["data"]=>
object(stdClass)#151 (10) {
["ID"]=>
string(1) "3"
["user_login"]=>
string(6) "author"
["user_nicename"]=>
string(15) "author-slug"
["user_email"]=>
string(16) "[email protected]"
["user_url"]=>
string(17) "http://example.com"
["user_registered"]=>
string(19) "2016-05-09 19:12:24"
["user_status"]=>
string(1) "0"
["display_name"]=>
string(15) "Author Name"
}
["ID"]=>
int(3)
["caps"]=>
array(1) {
["administrator"]=>
bool(true)
}
["cap_key"]=>
string(25) "wp_capabilities"
["roles"]=>
array(1) {
[0]=>
string(13) "administrator"
}
}
["queried_object_id"]=>
int(3)
["request"]=>
string(489) "SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.ID IN (1,102,160,196,199,201,206,162,198) AND (wp_posts.post_author = 3) AND wp_posts.post_type IN ('post', 'projects') AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'acf-disabled' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 10"
["posts"]=>
&array(1) {
[0]=>
object(WP_Post)#144 (24) {
["ID"]=>
int(1)
["post_author"]=>
string(1) "3"
["post_date"]=>
string(19) "2016-05-03 20:12:01"
["post_date_gmt"]=>
string(19) "2016-05-04 00:12:01"
["post_content"]=>
string(85) "Welcome to WordPress. This is your first post. Edit or delete it, then start writing!"
["post_title"]=>
string(12) "Hello world!"
["post_excerpt"]=>
string(0) ""
["post_status"]=>
string(7) "publish"
["comment_status"]=>
string(6) "closed"
["ping_status"]=>
string(6) "closed"
["post_password"]=>
string(0) ""
["post_name"]=>
string(11) "hello-world"
["to_ping"]=>
string(0) ""
["pinged"]=>
string(0) ""
["post_modified"]=>
string(19) "2016-06-15 14:39:12"
["post_modified_gmt"]=>
string(19) "2016-06-15 18:39:12"
["post_content_filtered"]=>
string(0) ""
["post_parent"]=>
int(0)
["guid"]=>
string(19) "http://3sm.dev/?p=1"
["menu_order"]=>
int(0)
["post_type"]=>
string(4) "post"
["post_mime_type"]=>
string(0) ""
["comment_count"]=>
string(1) "1"
["filter"]=>
string(3) "raw"
}
}
["post_count"]=>
int(1)
["current_post"]=>
int(-1)
["in_the_loop"]=>
bool(false)
["post"]=>
object(WP_Post)#144 (24) {
["ID"]=>
int(1)
["post_author"]=>
string(1) "3"
["post_date"]=>
string(19) "2016-05-03 20:12:01"
["post_date_gmt"]=>
string(19) "2016-05-04 00:12:01"
["post_content"]=>
string(85) "Welcome to WordPress. This is your first post. Edit or delete it, then start writing!"
["post_title"]=>
string(12) "Hello world!"
["post_excerpt"]=>
string(0) ""
["post_status"]=>
string(7) "publish"
["comment_status"]=>
string(6) "closed"
["ping_status"]=>
string(6) "closed"
["post_password"]=>
string(0) ""
["post_name"]=>
string(11) "hello-world"
["to_ping"]=>
string(0) ""
["pinged"]=>
string(0) ""
["post_modified"]=>
string(19) "2016-06-15 14:39:12"
["post_modified_gmt"]=>
string(19) "2016-06-15 18:39:12"
["post_content_filtered"]=>
string(0) ""
["post_parent"]=>
int(0)
["guid"]=>
string(19) "http://3sm.dev/?p=1"
["menu_order"]=>
int(0)
["post_type"]=>
string(4) "post"
["post_mime_type"]=>
string(0) ""
["comment_count"]=>
string(1) "1"
["filter"]=>
string(3) "raw"
}
}
post__in
配列には正しい投稿が含まれていますが、何らかの理由でposts
には「Hello World」しか含まれていないことに注意してください。この著者にも少なくとも3つのプロジェクトが関連付けられている必要があります。それらはクエリ内にあり、次のように見えますが、返されません。 post
sを作成していないユーザーの場合、ループには何も表示されません。 User ID 1
、posts
およびprojects
が表示されます。
たぶんこれはrequest
と関係があるのでしょうか?
"SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.ID IN (1,102,160,196,199,201,206,162,198) AND (wp_posts.post_author = 3) AND wp_posts.post_type IN ('post', 'projects') AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'acf-disabled' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 10"
私はそれが複雑で、尋ねることが多いことを知っていますが、次のステップでの助け、またはコードのエラーは大歓迎です。ありがとう!
PHP <5.4(ugh-クライアントサーバー!)をサポートするために、彼のコードにいくつかの変更を加える必要がありました。唯一の大きな変更は、2番目のクエリにget_posts()
の代わりにWP_Query
を使用することです。なぜなら、get_posts()
はposts_where
にワイルドカードがあるために必要なmeta_key
アクションにフックしないためです高度なカスタムフィールドリピーターフィールドによる):
function posts_where_credited( $where ) {
$where = str_replace("meta_key = 'project_credits_%_user", "meta_key LIKE 'project_credits_%_user", $where);
return $where;
}
add_filter( 'posts_where' , 'posts_where_credited' );
したがって、ここにpre_get_posts
関数があります。
function author_pre_get_posts ( $q ) {
// Remove action
remove_action( 'pre_get_posts', __FUNCTION__ );
// Only target the main query, front end only on author archive pages
if ( !is_admin()
&& $q->is_main_query()
&& $q->is_author()
) {
wp_reset_query();
wp_reset_postdata();
// Now we can run our custom queries to get post ID's
$author_name = sanitize_title_for_query( $q->query['author_name'] );
// This section is also used by WP_Query to get user id
$author = get_user_by(
'slug',
$author_name
);
$author_id = absint( $author->ID );
// Get the posts
$args_1 = array(
'author' => $author_id, // Get from referenced query
'fields' => 'ids', // Only get the Post's IDs, faster, lighter, better, stronger
'posts_per_page' => -1, // Get all posts
'cache_results' => false, // Do not update post cache
'update_post_meta_cache' => false, // Do not update post meta cache
'update_post_term_cache' => false, // Do not cache post terms
);
$post_type_post_ids = get_posts( $args_1 );
// Get the projects
$args_2 = array(
'post_type' => 'projects',
'fields' => 'ids', // Only get the Post's IDs, faster, lighter, better, stronger
'posts_per_page' => -1, // Get all posts
'cache_results' => false, // Do not update post cache
'update_post_meta_cache' => false, // Do not update post meta cache
'update_post_term_cache' => false, // Do not cache post terms
'meta_query' => array(
array(
'key' => 'project_credits_%_user',
'value' => $author_id,
)
)
);
$post_type_projects_ids = new WP_Query( $args_2 );
// retrieve *JUST* the IDs
$post_type_projects_ids = $post_type_projects_ids->posts;
// It is now just a matter of merging the two arrays of ids
$combined = array_unique(
array_merge(
$post_type_post_ids,
$post_type_projects_ids
)
);
// We need to make 100% sure we have id's, otherwise post__in will return all posts
if ( !$combined ) {
return;
}
var_dump($combined);
// Lets build the query
$q->set( 'post_type', array('post', 'projects') );
$q->set( 'post__in', $combined );
}
}
add_action( 'pre_get_posts', 'author_pre_get_posts' );
var_dump($combined)
はpost
sおよびprojects
のIDを提供し、同様にこれらの投稿やプロジェクトを表示します...ただし、ユーザーID 1のみです。他の著者のauthor.php
ページの場合、表示されている唯一のオブジェクトは、post_type
がpost
の投稿です-projects
はすべての作成者/ユーザーに対して表示されませんを除くユーザーID 1のユーザー。
そのため、修正する必要があるのはこれだけです。修正方法はわかりません。
元の答えの問題は、投稿者IDをpost__in
パラメータに渡していますが、著者ページにあるにもかかわらず、メインクエリはその投稿者に属さない投稿をすべて削除することです。 author_name
フィルタを介して空の文字列をpre_get_posts
に渡すことができますが、それはクエリオブジェクトを継承して壊します。
これは新しいアプローチを要求します、そしてこれは私たちがすることです:
メインクエリを通常どおり実行します。つまり、現在表示されている作成者によって作成されたデフォルトの投稿タイプpost
からのすべての投稿を返します。これは自動的に問題2の面倒を見るでしょう。カスタムフィールドを表示することを伴う問題1は元のアプローチで処理されます。
オリジナルのメインクエリにカスタム投稿タイプを追加する必要がある場合は、ここでpre_get_posts
を使用できますが、私の理解していることからすると、通常の投稿のみが必要であるため、これは必要ありません。
表示されている著者が言及されている投稿タイプprojetcs
からの投稿のみが必要な2番目の問題をソートするには、pre_get_posts
経由で投稿を追加するよりも生成されるSQLクエリを変更します。
このために、posts_where
フィルタを利用します。作成者が言及されているすべての投稿のIDをprojects
から返すためにカスタムクエリを実行し、それらのIDを取得し、SQLクエリのWHERE
節を変更して投稿も取得するようにします。
meta_query
用に生成されたSQLも変更するために、カスタムクエリをトリガするためにまだカスタムトリガを使います。
そのため、コードについては、最初のアプローチで投稿したすべてのコードを削除し、それを新しいフィルタで置き換えることができます。 (繰り返しになりますが、PHP 5.4)
add_filter( 'posts_where', 'posts_where_credited', 10, 2 );
function posts_where_credited( $where, \WP_Query $q )
{
// Lets first check our trigger and change the SQL if needed
if ( true === $q->get( 'wpse_trigger' ) )
$where = str_replace(
"meta_key = 'project_credits_%_user",
"meta_key LIKE 'project_credits_%_user",
$where
);
// Make sure that we target the main query, front end on author pages
if ( !is_admin()
&& $q->is_main_query()
&& $q->is_author()
) {
// Get the current author
$author_name = sanitize_title_for_query( $q->get( 'author_name' ) );
// Just to make sure we actually have a valid uathor name, if not, bail
if ( !$author_name )
return $where;
$author = get_user_by(
'slug',
$author_name
);
$author_id = absint( $author->ID );
// Get the posts in which the author is mentioned from our post type
$args = [
'wpse_trigger' => true, // Our custom trigger
'post_type' => 'projects',
'posts_per_page' => -1,
'fields' => 'ids',
'suppress_filters' => false,
'cache_results' => false,
'update_post_term_cache' => false,
'update_post_meta_cache' => false,
'meta_query' => [
[
'key' => 'project_credits_%_user',
'value' => $author_id
]
]
];
$post_ids = get_posts( $args );
// Make sure we have id's, else bail
if ( !$post_ids )
return $where;
$post_ids = implode( ',', array_map( 'absint', $post_ids ) );
// We have id's, lets adjust the SQL WHERE clauses
global $wpdb;
$where .= " OR ( $wpdb->posts.ID IN ( $post_ids ) ) ";
}
return $where;
}
あなたはあなたのアプローチに非常に近く、ただあちらこちらにグリッチがあります。これらすべてを打破することができます
ユーザーのプロフィールページに高度なカスタムフィールドのデータを表示します。
これは簡単です。残念ながら私はACFを使ったことがないので、データがどのように保存されているのかわかりません。ただし、要するに、表示されている著者アーカイブページの現在のIDだけが必要です。そのIDはすでに利用可能です(照会されたオブジェクトを使用する場合は+1)。
あるいは、問い合わせされたオブジェクトを取得するためのはるかに信頼性の高い方法は、$GLOBALS['wp_the_query']
に格納されているメインの問い合わせオブジェクトを利用することです。 $GLOBALS['wp_the_query']
は$GLOBALS['wp_query']
のような不安定な関数によって変更される可能性があるのでquery_posts
よりはるかに信頼性があります。つまり、著者のアーカイブページでは、次のように使用できます。
if( !isset($whose_ID) ) {
$whose_ID = absint( $GLOBALS['wp_the_query']->queried_object_id );
}
その後、get_field()
関数で$whose_ID
を使用してACFデータを返すことができます。あなたのコードから、それはキーがuser
接頭辞を持っているように思われるので、
$search = 'user_' . $whose_ID;
するべきです。
ユーザーの投稿した投稿をすべて表示します
それはここにあなたのすべてのアプローチが小さいことか2つを欠いているか、またはいくらかの改良が必要なだけです。あなたの最初のアプローチと最後のアプローチは一つに統合されているはずです。ここで覚えておく必要があることの1つは、WP_Query
は後に続く種類のクエリをネイティブにサポートしていないため、ネイティブにこれを1つのクエリで行うことはできないため、複数のクエリが必要になることです。これはターンが私達が賢くなることを必要とします、これが高価になることができて、そしてさらに銀行を破ることができるからです。
このセクションを解決するためにここで行うことは次のとおりです。
get_posts
を使用して、著者が書いた投稿タイプpost
からすべての投稿IDを取得します。これはコストのかかるオーバーヘッドになる可能性があるため、ここでは非常に賢い必要があります。 get_posts
は法的にページングを壊すのでWP_Query
より速いですが、銀行を破る必要がないのでもっと速くする必要があります。
私たちがすることは、それを超高速にするために、'fields' => 'ids'
をget_posts
クエリ引数に渡すことです。これはクエリにpost idの配列だけを返すように伝えます。他のpostdataを返さないので、これはクエリを非常に速くします。また、ポストタームとメタデータをキャッシュしないようにクエリに指示することで、さらに高速にすることができます。これは私たちが必要としないすべての無関係なものです
それでは、このクエリを見てみましょう(注意:すべてのコードはテストされていないのでPHP 5.4+)
$author_name = sanitize_title_for_query( $q->query['author_name'] );
$args_1 = [
'author_name' => $author_name, // Get from referenced query
'posts_per_page' => -1, // Get all posts
'cache_results' => false, // Do not update post cache
'update_post_meta_cache' => false, // Do not update post meta cache
'update_post_term_cache' => false, // Do not cache post terms
];
$post_ids_1 = get_posts( $args_1 );
$post_ids_1
は現在、著者が現在閲覧している投稿からの投稿IDの配列をデフォルトの投稿タイプpost
から保持します。
このセクションでは、上記とまったく同じプロセスに従いますので、ここでは詳しく説明しません。コードを見てみましょう
// This section is also used by WP_Query to get user id
$author = get_user_by(
'slug',
$author_name
);
$author_id = absint( $author->ID );
$args_2 = [
'post_type' => 'projects',
'posts_per_page' => -1, // Get all posts
'cache_results' => false, // Do not update post cache
'update_post_meta_cache' => false, // Do not update post meta cache
'update_post_term_cache' => false, // Do not cache post terms
'meta_query' => [
[
'key' => 'project_credits_%_user',
'value' => $author_id
]
]
];
$post_ids_2 = get_posts( $args_2 );
投稿タイプprojects
から作者が言及されたすべての投稿IDを取得しました
すべての関連するIDが揃ったので、pre_get_posts
アクションにすべてをまとめます。
add_action( 'pre_get_posts', function ( $q )
{
// Remove action
remove_action( current_action(), __FUNCTION__ );
// Only target the main query, front end only on author archive pages
if ( !is_admin()
&& $q->is_main_query()
&& $q->is_author()
) {
// Now we can run our custom queries to get post ID's
$author_name = sanitize_title_for_query( $q->query['author_name'] );
$args_1 = [
'author_name' => $author_name, // Get from referenced query
'posts_per_page' => -1, // Get all posts
'cache_results' => false, // Do not update post cache
'update_post_meta_cache' => false, // Do not update post meta cache
'update_post_term_cache' => false, // Do not cache post terms
];
$post_ids_1 = get_posts( $args_1 );
// This section is also used by WP_Query to get user id
$author = get_user_by(
'slug',
$author_name
);
$author_id = absint( $author->ID );
$args_2 = [
'post_type' => 'projects',
'posts_per_page' => -1, // Get all posts
'cache_results' => false, // Do not update post cache
'update_post_meta_cache' => false, // Do not update post meta cache
'update_post_term_cache' => false, // Do not cache post terms
'meta_query' => [
[
'key' => 'project_credits_%_user',
'value' => $author_id
]
]
];
$post_ids_2 = get_posts( $args_2 );
// It is now just a matter of merging the two arrays of ids
$combined = array_unique(
array_merge(
$post_ids_1,
$post_ids_2
)
);
// We need to make 100% sure we have id's, otherwise post__in will return all posts
if ( !$combined )
return;
// Lets build the query
$q->set( 'post_type', ['post', 'projects'] );
$q->set( 'post__in', $combined );
}
});
デフォルトのループを使用して、投稿を通常の投稿者アーカイブページに表示できます。ちょっと注意してください、サイトの構文のハイライトによると、あなたのauthor.php
の中のコードに構文エラーがあるようです
私はあなたの編集を見ました、そして、いくつかの問題があります、しかし、それは必ずしもこれが問題を解決するという意味ではありません
wp_reset_postdata()
とwp_reset_query()
を呼び出す必要はありません。後者はquery_posts()
でのみ使われます。
get_posts()
はフィルタによる変更を受け入れますが、これはデフォルトの振る舞いではありません。 get_posts()
はデフォルトで'suppress_filters' => true
をWP_Query
に渡し、クエリを変更するフィルタを抑制します。 'suppress_filters' => false
をget_posts
引数に渡すだけでこれをオーバーライドできます。これはフィルタがクエリを変更することを可能にします
デフォルトでは、WP_Query
内のどのフィルタもWP_Query
(メインクエリを含む)のすべてのインスタンスを変更します。関連するクエリのみを対象とするようにフィルタをトリガするために、何らかのトリガを使用することをお勧めします。私は間違いなくあなたのposts_where
フィルタでこれをするでしょう。
できることは、トリガーをwpse_trigger
と呼ぶことです。フィルタでターゲットにしたいクエリのクエリ引数に'wpse_trigger' => true
を渡すことができます。ここでやらなければいけないことは、triggerが設定されているかどうか、そしてそれがtrueに設定されているかどうか、私たちのフィルタの中をチェックすることです。現在のクエリは、2番目のパラメータとしてフィルタへの参照によって渡されます。
コードを見てみましょう
function posts_where_credited( $where, \WP_Query $q )
{
// Lets remove the filter
remove_filter( current_filter(), __FUNCTION__ );
// Lets see if our trigger is set and if the value is true, if not, bail
if ( true !== $q->get( 'wpse_trigger' ) )
return $where
// Our trigger is set and true, lets alter this query
$where = str_replace(
"meta_key = 'project_credits_%_user",
"meta_key LIKE 'project_credits_%_user",
$where
);
return $where;
}
add_filter( 'posts_where' , 'posts_where_credited', 10, 2 );
メタクエリを作成する2番目のget_posts
インスタンスのクエリ引数は、次のようになります。
$args_2 = [
'wpse_trigger' => true,
'suppress_filter' => false,
// Rest of your query args
];
あなたのフィルタが実際にmeta_key LIKE
で正しく動作するかどうかはわかりませんが、 この記事 それが実際に失敗した2つ目のクエリである場合、/いくつかの代替案を見ることができます。
非常に奇妙なことは、すべてが作者1
に対して機能しますが、他のすべての作者に対しては機能しないことです。ここであなたがチェックできることがいくつかあります
WP_Query
アクションの中にある2番目のクエリ用のpre_get_posts
インスタンスを保持します。そして、そのクエリの後($post_type_projects_ids = new WP_Query();
の直後)、var_dump( $post_type_projects_ids->request );
を実行して著者ページをロードします。これにより、作成者ページの上にSQLクエリが印刷されます。結果のSQLクエリが他のすべての作者ページと作者1のものと一致するかどうかを確認します。それらが異なる場合は、プラグインまたはテーマのどこかに悪いフィルタ(posts_where
またはposts_clauses
)などの問題があります。 action(bad pre_get_posts
)またはカスタム投稿タイプの機能に関する問題。 WP_Query
ではうまくいきませんので、get_posts
に気をつけてください。
SQLクエリがチェックアウトする場合は、var_dump( $post_type_projects_ids->posts );
を実行し、クエリから返された投稿が実際にあるかどうかを確認します。投稿がある場合、これはIDを持つ配列になります。
上記のことを確認したら、あなたの作者ページに行き、そのページのどこかに、var_dump( $wp_query->request );
を追加してください。これにより、メインクエリによって生成されたSQLクエリが印刷されます。また、作者1が動作するので、そのSQLクエリを他の作者ページのSQLクエリと比較します。投稿者IDと作成者IDを除いて、クエリは一致する必要があります。そうでない場合は、デバッグのための箇条書きの1つを参照してください。