register_post_status
では、私のカスタムステータスshow_in_admin_all_list
に対してshow_in_admin_status_list
とmy_hidden_status
を無効にしました
しかし、クエリログからpost_status my_hidden_status
はまだ除外されていません(edit.phpをロードするとき)
例えば.
SELECT post_status、COUNT(*)AS num_posts from st_posts WHERE post_type = 'my_cpt' GROUP BY post_status;
私が実際にフィルタリングしたいpost_statusは私のCPTの90%以上なので、クエリが以下のように書き直されるなら
SELECT post_status, COUNT( * ) AS num_posts FROM st_posts WHERE
post_type = 'my_cpt' AND post_status != 'my_hidden_status' GROUP BY
post_status;
それはパフォーマンスを大幅に向上させることができます。
それはバグですか?
TL; DR:これはバグではなく(一般に理解されているように)、むしろ機能でした- 完全に実装されていない WordPress。
register_post_status()
のステータスregister_post_status()
関数がWordPressに完全に実装されることはありませんでした。 WordPress register_post_status()関数のCodexエントリ をチェックすると、通知で明確に言及されていることがわかります。
注意:
この関数は、登録済みの投稿ステータスを管理パネルに追加しません。この機能は保留中の将来の開発です。 Trac Ticket#12706 を参照してください。このパラメーターを追加するには、アクションフック post_submitbox_misc_actions を検討してください。
また、 関連チケット にアクセスすると、それを完全に実装するための議論が8年以上にわたって行われていることがわかります(2010年3月から)。ただし、WordPressはオープンソースコミュニティ主導のソフトウェアであり、この機能に取り組むボランティアはあまりいないため、適切な実装はまだ保留されています。
Trac Ticket#12706 は、説明で次のことを示しています。
開発者はregister_post_status()を使用してカスタム投稿ステータスを登録できる必要があります。管理UI(投稿送信ボックスとクイック編集を含む)この新しいカスタム投稿ステータスを反映する必要があります。さらに、ポストステータスAPIを適切に使用する必要があるコアの「ドラフト」および「保留」ステータスへのハードコーディングされた参照が多数あります。
register_post_status()のすべての既存の引数は完全に実装する必要があります。投稿タイプごとの引数もサポートする必要があります。コア全体に物事が実装されると、おそらくAPIの機能とビットをサポートする必要があります。
WordPressコアコードを見ると、この説明がまだ有効であることがわかります。つまり:
管理UI(投稿送信ボックスとクイック編集を含む)カスタム投稿ステータスを反映しません。コアの CODEのこの部分 を確認します。
<?php _e( 'Status:' ); ?> <span id="post-status-display">
<?php
switch ( $post->post_status ) {
case 'private':
_e( 'Privately Published' );
break;
case 'publish':
_e( 'Published' );
break;
case 'future':
_e( 'Scheduled' );
break;
case 'pending':
_e( 'Pending Review' );
break;
case 'draft':
case 'auto-draft':
_e( 'Draft' );
break;
}
?>
</span>
CODEにはカスタム投稿ステータスのアクション/フィルターフックなしまたは変更が含まれます。したがって、現時点で唯一の論理的な方法は、この機能がWordPressコアに実装されるまで、JavaScriptを使用してUI実装を変更することです。
register_post_status()へのすべての既存の引数はまだ完全には実装されていません&したがって、バグがあるように見える場合があります。
Post Status APIを完全に実装するには、さらに多くの議論と作業が必要です。
機能の欠如、またはバグと呼んでも、事実は変わりません。PostStatus APIを完了するには、さらに多くの作業が必要です。したがって、これがあなたにとってあまりにも重要な場合は、上記のサポートチケットのディスカッションに参加して、開発プロセスを促進することをお勧めします。
開発プロセス全体では多くの自主的な作業が必要になりますが、クエリに影響を与えない引数show_in_admin_all_list
についてコメントすることができます。これにより、少なくとも異常のこの部分を残りのStatus APIよりも早く改善できます。
現在のように、show_in_admin_all_list
引数は、すべての投稿リストのAll(*)
ステータスヘッダー部分にのみ影響します。たとえば、
Image-1:すべての投稿リストステータスヘッダー(すべての投稿が選択されている)
ただし、リストに表示される投稿には影響しません(ただし、そうする必要があります)。
カスタムステータスmy_hidden_status
の投稿がリストにも表示されないようにするには、public
引数をfalse
に設定する必要があります。
これにより、register_post_status()
関数呼び出しが次のようになります。
register_post_status( 'my_hidden_status', array(
'label' => _x( 'My Hidden Status', 'post' ),
'public' => false,
'show_in_admin_all_list' => false,
'show_in_admin_status_list' => false,
'label_count' => _n_noop( 'My Hidden Status <span class="count">(%s)</span>', 'My Hidden Status <span class="count">(%s)</span>' )
) );
これにより、All(*)
ステータスヘッダーに正しいカウントが表示され、my_hidden_status
またはAll Posts
リストからAll {custom_post_type}
の投稿も削除されます。
もちろん、これにより、基本的にWordPress管理パネルからmy_hidden_status
の投稿にアクセスできなくなります。それが意図である場合は、それ以外の場合は問題ありません。別のリストヘッダーにshow_in_admin_status_list
を使用して、my_hidden_status
の投稿を表示できます。
register_post_status( 'my_hidden_status', array(
'label' => _x( 'My Hidden Status', 'post' ),
'public' => false,
'show_in_admin_all_list' => false,
'show_in_admin_status_list' => true,
'label_count' => _n_noop( 'My Hidden Status <span class="count">(%s)</span>', 'My Hidden Status <span class="count">(%s)</span>' )
) );
これにより、次のような別のヘッダーにステータスmy_hidden_status
の投稿リストが表示されます。
Image-2:すべての投稿リストステータスヘッダー(カスタムステータスが選択されている)
関連するDBクエリは、wp-includes/post.php
ファイルのwp_count_posts()
関数から取得されます。 関連CODE を見ると、register_post_status()
関数からの引数がそこに実装されていないことがわかります。また、コアCODEのこの部分をフィルタリングまたは拡張する方法もありません。
$query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s";
if ( 'readable' == $perm && is_user_logged_in() ) {
$post_type_object = get_post_type_object( $type );
if ( ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
$query .= $wpdb->prepare(
" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))",
get_current_user_id()
);
}
}
$query .= ' GROUP BY post_status';
特定のステータスでshow_in_admin_all_list
とshow_in_admin_status_list
の両方がfalse
に設定されていない限り、関連する投稿をクエリから削除しないでください。そうしないと、WordPressは適切なstatus header
を生成できません(画像2を参照)。
ただし、show_in_admin_all_list
とshow_in_admin_status_list
の両方がfalse
に設定されている場合、WordPressはそのカスタムステータスのカウント情報を必要としません。論理的には、このケースでは、AND post_status != 'my_hidden_status'
部分でクエリパフォーマンスが少し向上します。多数の投稿(数百万など)があり、ほとんどの投稿(90%を言った)がそのカスタムステータスからのものである場合。
それでも、特定のケースではパフォーマンスが少し向上する可能性があるにもかかわらず、コアがCODEのこの部分を更新しない場合がある2つの理由があります。
WordPressデータベースは、type_status_date
、wp-posts
、post_type
、ID
フィールドに基づいてpost_status
テーブルエントリにインデックスを付けるpost_date
という名前のインデックスを使用します。 つまり、クエリはAND post_status != 'my_hidden_status'
部分がなくても十分に高速です。
15K以上の投稿でテストしましたが、数ミリ秒しかかかりません。インデックス付きGROUP BY最適化の詳細については、 このMySQLドキュメント を確認してください。 MySQLインデックスの調整により、WP Coreを変更しなくても、より良い結果が得られる場合があります。たとえば、post_type
列とpost_status
列で別のインデックスを追加すると、数ミリ秒のゲインが得られる場合があります。
特定のケースでAND post_status != 'my_hidden_status'
を追加するとクエリが(ミリ秒単位で)速くなる場合がありますが、WordPressが非表示のカスタムの可能性を考慮する必要があるため、WordPressステータスには数個の投稿しかありません。これらの場合、AND post_status != 'my_hidden_status'
を追加すると、実際にはクエリ結果が少し遅くなります(数ミリ秒だけ)。
したがって、すべてを考慮すると、WordPressは、カスタムステータスのAND post_status != 'my_hidden_status'
とshow_in_admin_all_list
の両方がfalse
に設定されている場合、show_in_admin_status_list
でクエリを更新する場合としない場合があります。ただし、少なくとも、関連するクエリをフィルター可能にすると、開発者の柔軟性が向上します。
フィルタリングしようとしているクエリは、実際にはwp_count_posts
関数によって呼び出されます。このクエリをフィルタ処理する唯一の方法は、query
フィルタを使用することです(wpdb
クラスquery
メソッド内にあります)。
フィルタquery
は、$wpdb
インスタンスで呼び出されるすべてのmysqlクエリに使用されるので、必要な場所からフィルタを登録することをお勧めします。そのためには、load-edit.php
アクションにフィルタを追加します。
/* register the filter from edit.php page (works for all post types) */
add_action('load-edit.php', 'wpse_initiate_filter');
function wpse_initiate_filter($query) {
add_filter('query', 'wpse_filter_posts_count_query');
}
/* modify original query to filter out my_hidden_status */
function wpse_filter_posts_count_query($query) {
if (strpos($query, 'SELECT post_status') === 0) {
$query = str_replace(" GROUP BY", " AND post_status != 'my_hidden_status' GROUP BY", $query);
}
return $query;
}
それはバグですか?それはそれがしなければならないよりももう少し多くの仕事をしています、しかしそれは少しの予期しない出力ももたらさず、そしてそれは他のサイト設定に関する潜在的な問題を避けます。だから私は(ほとんど)ノーと言うでしょう。
問題のクエリは、編集画面に表示する前に見つかった投稿の数を数えるのに役立ちます。それはページが後でそれらを必要とするならそれがこれらの数が便利であるようにステータスによってすべての投稿を数えます。
私の考えは、あまり使われていない投稿ステータスが詰まってクエリが遅くなる可能性を防ぐために、クエリを意図的に単純にしたことです。たとえば、phpMyAdminのテストでは、ベースクエリは0.0011秒かかり、約300件の投稿がありました。 5つの未使用またはほとんど使用されていない投稿ステータスを除外するための句を追加すると、時間が0.0024に増えました。
あなたの状況では、潜在的な結果の90%を除外することがクエリをスピードアップすることは正しいと思います。 query filter でそれをフィルタリングしてみることができます。
補足として:これを調べているときに、"public" => true
のregister_post_status
がshow_in_admin_all_list
の値をオーバーライドして、編集画面にそのステータスの投稿を表示することに気付きました。他のregister_*
関数では、より特定的な引数がpublic
引数をオーバーライドする傾向があるので、私はその部分をバグと呼びます。