今日は、主に一意の識別子を作成するために、クエリをどのように区別するかを考えていました。私が少し遊んだ過程で、以下のコードを見てください。
主な考え方は、$query
の$query_vars
またはWP_Query
プロパティに応じてそれを行うことです。実際には既にquery_vars_hash
というプロパティがありますが、varのサブセットでかなり早く作成されているため、同じリクエストで発生したクエリを区別するのに役立ちません。
以下は私がこれまでに持っているものです:
add_action( 'pre_get_posts', 'unique_query' );
/**
* unique_query
*
* Create unique identifier
*
*/
function unique_query( $query ) {
global $wp_query;
$query_hashes = array();
if ( is_admin() ) return;
/**
* Skip additional cases
*/
/**
if ( ! isset( $query->query['post_type'] )
|| empty( $query->query['post_type'] )
|| $query->query['post_type'] == 'nav_menu_item'
|| $query->is_main_query()
) {
return;
}
/**/
/**
* Debug stuff
*/
/**
echo '<pre>';
print_r( $query );
print_r( $wp_query );
print_r( $query->query );
print_r( $wp_query->query );
print_r( $query->query_vars );
print_r( $wp_query->query_vars );
echo '</pre>';
/**/
/**
* Setup query hashes array
*/
$query_hashes[ '$wp_query->query_vars_hash' ] = $wp_query->query_vars_hash;
$query_hashes[ 'uhash_$wp_query->query_vars' ] = md5( serialize( $wp_query->query_vars ) );
$query_hashes[ '$query->query_vars_hash' ] = $query->query_vars_hash;
$query_hashes[ 'uhash_$query->query_vars' ] = md5( serialize( $query->query_vars ) );
$query_hashes[ 'uhash_$query->query' ] = md5( serialize( $query->query ) );
$query_hashes[ 'uhash_$wp_query->query' ] = md5( serialize( $wp_query->query ) );
/**
* Print query hashes array
*/
echo '<pre>';
print_r( $query_hashes );
echo '</pre>';
}
これにより、次のような出力例が生成されます。
/* Main query */
[$wp_query->query_vars_hash] => ffb3c63f9b858ab4882d8e9ed20fce67
[uhash_$wp_query->query_vars] => ffb3c63f9b858ab4882d8e9ed20fce67
[$query->query_vars_hash] => ffb3c63f9b858ab4882d8e9ed20fce67
[uhash_$query->query_vars] => ffb3c63f9b858ab4882d8e9ed20fce67
[uhash_$query->query] => 40cd750bba9870f18aada2478b24840a
[uhash_$wp_query->query] => 40cd750bba9870f18aada2478b24840a
/* Query of wp_nav_menu */
[$wp_query->query_vars_hash] => ffb3c63f9b858ab4882d8e9ed20fce67
[uhash_$wp_query->query_vars] => 59e1dad0ba690eed5e758fbf15cda702
[$query->query_vars_hash] => c5a049c558df9cf4cfd14dad179a97e8
[uhash_$query->query_vars] => c5a049c558df9cf4cfd14dad179a97e8
[uhash_$query->query] => d4226d11be5a53e8b44d5b85db43e8b0
[uhash_$wp_query->query] => 40cd750bba9870f18aada2478b24840a
/* Front/home query */
[$wp_query->query_vars_hash] => ffb3c63f9b858ab4882d8e9ed20fce67
[uhash_$wp_query->query_vars] => 59e1dad0ba690eed5e758fbf15cda702
[$query->query_vars_hash] => 712b303f79eef3c8b5928d4ed8acfe2f
[uhash_$query->query_vars] => 712b303f79eef3c8b5928d4ed8acfe2f
[uhash_$query->query] => b7ac5bdfe084209f0142d7ab3aa0683e
[uhash_$wp_query->query] => 40cd750bba9870f18aada2478b24840a
お分かりのように、明確な決定のための唯一の候補は$query->query_vars_hash
/uhash_$query->query_vars
またはuhash_$query->query
です。もちろんこの例では1番目と2番目のものは同じですが、将来的には既存のquery_vars_hash
プロパティでカバーされていないことをする必要があるかもしれません。確かに自分でやらなければなりません。
これはクエリを一意に識別するための合理的なアプローチですか?または、特に何かが足りない場合は特に、より良いものがある可能性があります。 、 興味ある。
編集:
@ G.提起された問題で暗示されたすべてのことについてほとんど正しいです。私は実際にこの情報を追加することを心に留めていました、投稿する時点でちょうど十分な時間がありませんでした、今それはただ冗長になるでしょう、しかし私は事実を確認したかったです。
tl; dr:手ごろな価格でクエリ用の一意の識別子を作成することは可能ですが、まったく役に立ちません。
Query objects の一意の識別子を探しているなら、 spl_object_hash
を使うことができますが、IMHOはまったく役に立ちません。それは予測不可能であり、query varsであっても異なるIDを得ます。同一ですが、2つの異なるクエリオブジェクトに設定されます。 "このリクエストの間にXX個のWP_Query
個のオブジェクトがインスタンス化されました。"
Query variables に注意を向けたのは、おそらくquery results を識別するためのIDを探しているからです。つまり、2つの異なるqueryオブジェクトから同じidを取得できる場合両方のクエリで同じにします。
そのような場合、私はあなたにとって悪い驚きです:あなたが使用するテクニックに関係なく、あなたがクエリ変数に基づいてあなたのクエリIDを構築するなら、あなたは'posts_*'
filters( 'posts_where'、 'を考慮しません) posts_join 'など、それらは19 IIRCです。
コンセプトの証明:
$query1 = new WP_Query( 'post_type=post' );
add_filter( 'posts_where', function() { return ' AND 1 = 0'; } );
$query2 = new WP_Query( 'post_type=post' );
$query1
と$query2
は同一なので、クエリvarsに基づいて一意のIDを返す仮想コールバックは2つのクエリに対して同一のIDを返しますが、最初のクエリはすべての公開された投稿を返し、2番目のクエリは何も返しません。
これが、クエリ変数が一意のクエリIDを構築するための良い出発点ではない理由です。
クエリの結果が重要な場合は、クエリのSQLリクエストに集中する必要があります。リクエストが同じ場合、結果は同じになります。さらに、リクエストは文字列なので、簡単にハッシュできます。
スコープの適切な候補フックは、リクエストが完全に構築されているがまだ実行されていない場合に1つにする必要があります。 'split_the_query' filterフックは問題ないはずです。
// prepare our ids storage
add_action( 'init', function() {
global $query_ids;
$query_ids = array();
});
// use the filter to build and store the id
add_filter( 'split_the_query', function( $split_the_query, $query ) {
$hash = md5( $query->request );
$hash .= $split_the_query ? '_split' : '';
global $query_ids;
if ( ! in_array( $hash, $query_ids, TRUE ) ) {
$query_ids[] = $hash; // store hash if not already stored
}
return $split_the_query; // return $split_the_query as is
}, PHP_INT_MAX, 2 );
これで、一意のクエリ識別子を作成する方法があります。2つのクエリから同じ識別子を取得できる場合、2つのクエリの結果は同じになります。
しかし、それを使って何ができるでしょうか。おそらく以下のような統計です。
add_action('shutdown', function() {
global $query_ids;
echo count( $query_ids ) . " different WP_Query requests were performed.";
});
そのような統計の有用性が何であるか私にはわかりませんが、誰かができるかもしれません。
cache クエリにクエリ識別子を使用することを考えているのですが、idが同じ場合はデータベースリクエストをトリガーしません。 。
問題は、WordPressがリクエストを作成した後すぐにそれを実行し、それをショートする機会がないということです。
あるいは、WordPressが$wpdb->get_results
を使用してクエリを実行し、$wpdb
がグローバル変数になったら、そのオブジェクトをキャッシュ可能な変更されたwpdbクラスに置き換えることをお勧めしますが、その場合は意味がありません。 sqlリクエストに基づいてすべてのキャッシュが$wpdb
上で発生した後のクエリの一意のIDがそこで実行されました。
実質的には、問題はWordPressがWP_Query
ロジックに関して2つの大きな問題を抱えていることです(とりわけ、WP_Query
厄介なコードについて)。
WP_Query::get_posts()
メソッドが呼び出されると、sqlクエリが実行されるのを防ぐ方法はありません。これらの2つの問題がそこにとどまるまで、私見はクエリのためにユニークなidを作成することは偏心した統計のためにだけ使われることができるものです...