瞬变不适用于自定义循环

时间:2014-09-08 作者:Marius

我正在做WordPress主题。由于我需要显示特色帖子、相关帖子、最近帖子的一些小部件等等,所以我需要使用多个自定义循环。因此,数据库查询的数量也增加了。

为了优化主题以获得更好的性能,我遇到了http://codex.wordpress.org/Transients_API , 这似乎是一种缓存循环的好方法,我不需要在每次重新加载页面时更新循环。

到目前为止还不错,我在wp\\U nav\\U菜单中使用了transient,它正常工作。我设法减少了一点db查询的数量。

当我尝试将瞬态用于自定义循环时,出现了问题。

瞬态被保存。我可以得到瞬态值。唯一的问题是,数据库查询的数量似乎明显高于使用WP\\U查询时的数量,而不使用临时查询。

这是我的自定义循环:

if( false === ( $loop = get_transient(\'featured\') ) ) {
    $loop = new WP_Query( array( \'posts_per_page\' => 20 ) );
    set_transient(\'featured\', $loop, 60 * MINUTE_IN_SECONDS);
}

if( $loop->have_posts() ) :

    while( $loop->have_posts() ) : $loop->the_post();

        the_title();
        the_post_thumbnail(\'thumb\');

    endwhile;

endif;
wp_reset_postdata();
用于显示数据库查询数和执行时间的代码如下:

<?php echo get_num_queries(); ?> queries in <?php timer_stop(1); ?> seconds.
使用查询调试插件,我发现update\\u meta\\u cache()会生成大量查询。

我无法解释为什么数据库查询的数量不是减少而是增加,为什么这对菜单有效,但对自定义循环无效。也许我错过了什么。非常感谢您的帮助。

2 个回复
最合适的回答,由SO网友:Pieter Goosen 整理而成

我昨天确实在写一篇文章(看看吧here) 也遇到了同样的问题。我也是新来的Transient API, 从未实际使用过:-)。

这里的问题是,对于特定的循环,您需要在瞬态之外使用特定的值。您只是存储了错误的值,正因为如此,您得到了这些超负荷的db点击。

为了解释,这里是我提到的答案中的部分代码。我需要创建一个类别列表,其中包含属于这些类别的帖子标题。为此,我运行自定义查询,然后使用$q 创建我的列表

    $args = array( 
        \'posts_per_page\' => -1
    );

    $query = new WP_Query($args); 

    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = \'<a href="\'. get_permalink() .\'">\' . get_the_title() .\'</a>\';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = \'<a href="\' . get_category_link( $category ) . \'">\' . $category->name . \'</a>\';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();
这让我6 queries in 0.06348 seconds.

好的,如果你看一下法典中的例子,你应该把你的new WP_Query 导致瞬态。如果我那样做,结果完全是乱七八糟的

<?php
if( false === ( $query = get_transient(\'custom_query\') ) ) {
    $args = array( 
        \'posts_per_page\' => -1
    );

    $query = new WP_Query($args); 
 set_transient(\'custom_query\', $query, 60 * MINUTE_IN_SECONDS);
}
    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = \'<a href="\'. get_permalink() .\'">\' . get_the_title() .\'</a>\';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = \'<a href="\' . get_category_link( $category ) . \'">\' . $category->name . \'</a>\';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();


?>
使用上面的代码,我的结果如下所示31 queries in 0.19141 seconds. 这需要25次查询,大约需要0.13秒。原因是,对于每一篇帖子,Wordpress都需要重新访问db以检索帖子所属的类别,因为这不会存储在您的transient中。25额外查询是my db中的帖子数量。所以,你看,你存储了错误的信息,实际上浪费了很多资源。我不需要来自new WP_Query, 但是q美元的结果/价值

因此,要正确利用瞬态,必须存储所需的正确值。要做到这一点,我需要将我的完整查询添加到瞬态中,以确保它只运行一次,也就是在创建瞬态时。在那之后,自定义查询就不再需要了,而且是多余的,唯一需要存储并且我现在正在寻找的就是值$q. 因此,这就是如何更改查询以在创建瞬态后删除自定义查询,并仅保存$q

需要注意的是,我沿途更改了临时名称,只是为了测试目的,以显示时间和查询。还要注意,在创建瞬态时,需要使用值(在本例中$q) 您需要保存

 if ( false === ( $q = get_transient( \'category_list\' ) ) ) {

    $args = array( 
        \'posts_per_page\' => -1
    );

    $query = new WP_Query($args); 

    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = \'<a href="\'. get_permalink() .\'">\' . get_the_title() .\'</a>\';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = \'<a href="\' . get_category_link( $category ) . \'">\' . $category->name . \'</a>\';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();

set_transient( \'category_list\', $q, 12 * HOUR_IN_SECONDS );
}
这个给我2 queries in 0.00195 seconds. 你看我现在是如何有效地利用瞬变的。$q 这是一个由许多值组成的数组`现在可以用来创建我的列表,而实现我的目标只需点击2 db

我希望这一切都有意义

SO网友:Mark Kaplun

您的代码有3个问题

您可以使用一个DB查询来保存另一个DB查询。您可以查询一个瞬态值,而不是post表,这可能更快,也可能不更快,但不会节省与DB通信的代价。

不应将对象存储在瞬态或选项中。根据文档值,应该只有标量,这可能是get\\u transient在代码中失败的原因。wp\\u query的一个重要部分是通过将返回的post对象存储在缓存中来进行缓存预处理,这可能会影响其余代码的性能(在此上下文中,缓存是短期的每会话缓存)

缓存的正确方法是缓存生成的HTML。您的代码试图保存一个查询,但如果缓存HTML,则会再保存40个查询

结束

相关推荐

WP_QUERY:类别中的帖子或自定义帖子类型

我不想打扰你们,但这已经让我发疯了。我有一个名为“listas-2”的特定类别中的遗留帖子模型,它使用短代码来显示一些奇特的东西。现在,我已经创建了一个名为“lista”的自定义post类型,它使用post\\u metas做了同样的事情,但做得更好。现在的问题是,我必须在分页的同时对两者进行归档,其中包含遗留和新帖子。我无法同时显示两者,已经尝试添加tax\\u查询,但我无法,因为自定义帖子类型不使用它,只使用普通帖子。我还尝试合并查询,但我遇到了很多分页问题。目标:一个WP\\u查询,请求类别“lis