如何唯一标识查询?

时间:2014-06-13 作者:Nicolai Grossherr

今天我在考虑如何区分查询,主要是创建唯一标识符。在这个过程中,我进行了一些尝试,请参见下面的代码。

主要思想是根据$query$query_vars 的属性WP_Query. 实际上已经有了一个属性query_vars_hash, 但它很早就创建了一个子集vars,对于区分在同一请求上发生的查询没有帮助。

以下是我目前掌握的情况:

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_varsuhash_$query->query. 当然,在这个示例中,第一个和第二个是相同的,但将来可能需要执行现有query_vars_hash 所有物此外,你必须自己去做才能确定。

所以问题是,首先,这是唯一标识查询的合理方法吗

<小时>

Edit:

@G、 M.对于所提出的问题所暗示的一切都非常正确。实际上我想添加这些信息,只是在发布时没有足够的时间,现在这只是多余的,但我想确认一下事实。

1 个回复
最合适的回答,由SO网友:gmazzap 整理而成

tl;dr: 为查询构建价格合理的唯一标识符是可能的,但这毫无用处。

如果要查找查询对象的唯一标识符,则可以使用spl_object_hash, 但IMHO非常无用:它是不可预测的,而且即使查询变量相同,但设置在两个不同的查询对象上,您也会得到不同的id。使用它的唯一原因是可以获得这样的统计信息:“在此请求期间XX不同WP_Query 对象已实例化。“”

如果您将注意力放在查询变量上,可能是因为您正在查找标识查询结果的id,即当您可以从两个不同的查询对象获得相同的id时,两个查询的结果应该相同。

在这种情况下,我要给你一个不好的惊喜:这永远不会发生,因为无论你使用什么技术,如果你基于查询变量构建你的查询id,你都不会考虑\'posts_*\' 过滤器(\'posts\\u where\',\'posts\\u 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 相同,因此基于查询变量返回唯一id的虚拟回调将为这两个查询返回相同的id,但第一个查询返回所有已发布的帖子,第二个查询不返回任何内容。

这就是为什么查询变量不是构建唯一查询id的良好起点。

如果重要的是查询结果,那么应该集中精力查询sql请求:当请求相同时,结果也会相同,另外请求是一个字符串,所以很容易散列。

当请求已完全构建,但尚未执行时,范围的良好候选挂钩应该是一个,\'split_the_query\' 过滤器挂钩应完好。

// 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 );
现在,我们有了一种构建唯一查询标识符的方法:当我们可以从两个查询中获得相同的标识符时,那么这两个查询的结果是相同的。

但是我们能做什么呢?可能是这样的统计数据:

add_action(\'shutdown\', function() {
   global $query_ids;
   echo count( $query_ids ) . " different WP_Query requests were performed.";
});
我找不到这样的统计数据有什么用处,但也许有人可以。

我知道您正在考虑使用查询标识符来缓存查询,并且在id相同时不要触发数据库请求,这是一个好主意,但是。。。你不能。

问题是,当WordPress构建了请求,然后立即运行它,这样您就没有机会短路它!

或者更好,一旦WordPress使用$wpdb->get_results 要执行查询,请执行一次$wpdb 是一个全局变量,有可能用一个能够缓存的修改过的wpdb类替换该对象,这是一个好主意,但在这种情况下,一旦所有缓存都发生在$wpdb 基于在那里运行的sql请求。

实质上,问题是WordPress面临两大问题:WP_Query 逻辑(以及其他关于WP_Query 混乱代码):

构建过程的查询和运行过程的查询是不可分离的WP_Query::get_posts() 方法。在这两个问题没有解决之前,无法阻止运行sql查询。如何为查询创建唯一id只能用于偏心统计。。。

结束

相关推荐

POST_TAG不起作用的WP_TAX_QUERY

使用pre\\u get\\u posts挂钩,我试图通过将搜索限制在应用了某些(多个)标记的帖子上,来允许用户缩小搜索范围。这是我的钩子和功能:add_filter(\'pre_get_posts\', array($this, \'pre_get_posts\'), 0); function pre_get_posts( $query ) { if ( !is_admin() && $query->is_search ) { $query