这个代码有效吗--或者有更好的方法吗?

时间:2013-11-12 作者:Louise

我有一个配方WP网站,它使用CPT来处理配方内容。

客户想要一个所有配方的A-Z目录列表。我找到Wordpress答案,发现以下代码满足了我的要求:

add_shortcode(\'recipe_list\', \'recipe_query\');
function recipe_query($atts, $content){
$args = array(
    \'post_type\' => \'recipes\',
    \'orderby\' => \'title\',
    \'order\' => \'ASC\',
    \'posts_per_page\' => -1
);

$query = new WP_Query( $args );

$dl = \'\';
$glossary_letter = \'\';
$active_letters = array( );

while ( $query->have_posts() ) {
$query->the_post();
$term_letter = strtoupper( substr( get_the_title(), 0, 1 ) );
if ( $glossary_letter != $term_letter ) {
    $dl .= (count( $active_letters ) ? \'</ul>\' : \'\') . \'<li id="\' . $term_letter . \'"><span class="subheading">\' . $term_letter . \'</span><ul>\';
    $glossary_letter = $term_letter;
    $active_letters[] = $term_letter;
}
$dl .= \'<li><a href="\'.get_permalink().\'">\' . get_the_title() . \'</a></li>\';

}
$dl .= \'</ul></li>\';

$ul = \'<ul class="letters">\';
foreach ( array( \'0\', \'1\', \'2\', \'3\', \'4\', \'5\', \'6\', \'7\', \'8\', \'9\', \'A\', \'B\', \'C\', \'D\', \'E\', \'F\', \'G\', \'H\', \'I\', \'J\', \'K\', \'L\', \'M\', \'N\', \'O\', \'P\', \'Q\', \'R\', \'S\', \'T\', \'U\', \'V\', \'W\', \'X\', \'Y\', \'Z\' ) as $letter ) {
    $ul .= \'<li>\' . (in_array( $letter, $active_letters ) ? \'<a href="#\' . $letter . \'">\' . $letter . \'</a>\' : $letter) . \'</li>\';
}
$ul .= \'</ul>\';

return \'<div id="glossary">\' . $ul . \'<ul class="definitions">\' . $dl . \'</ul></div>\';
}
现在有1020个配方,它似乎比其他页面运行得慢,而且由于我是一个弗兰肯斯坦程序员(有些来自这里,有些来自那里),我决定询问真正的php程序员。Is there a better, more efficient way to write the code?

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

我建议使用缓存——生成HTML标记并将其存储在缓存中,然后使用它,而不是在每个页面加载时生成列表。

当然,如果配方被添加、删除或更改标题,则必须清除缓存。

add_shortcode(\'recipe_list\', \'recipe_query\');
function recipe_query( $atts, $content ){

     //Get mark-up from cache (if present)
     $html = get_transient( \'wpse123038_recipe_list\' );

     if( !$html ){
          //Nothing in cache - generate mark-up
          $html = \'\';
          ....

          //Store in cache (for a long time - a year?)
          set_transient( \'wpse123038_recipe_list\', $html, 60*60*24*365 );     
     }

     return $html;
}
现在,每次我们添加/删除一篇文章(或者可能已经发布,然后我们将其设置为“草稿”)——基本上是在任何时候,它都可能从不在列表中变为在列表中:)。(注意,您还需要在配方标题更改时清除缓存…)

function wpse123038_recipe_status_changes( $new_status, $old_status, $post ) {

    //Check if status has changed
    if( $new_status == $old_status ){
        return;
    }

    //Check post type
    if( \'recipes\' != get_post_type( $post) ){
         return;
    }

    //Check if we\'re publishing on \'unpublishing\' it.
    if( \'publish\' == $new_status || \'publish\' == $old_status ){
         delete_transient( \'wpse123038_recipe_list\' );

         //For bonus points, regenerate the cache here :)
    }

}
add_action( \'transition_post_status\', \'wpse123038_recipe_status_changes\', 10, 3 );
因此,当配方发布或“未发布”时,缓存将被清除。这意味着下一个访问者必须等待再次生成标记。

当然,我们通常不太关心管理端的页面加载时间,所以当缓存被清除时,您可以重新生成它。在前端提供(通常)无缝体验。

结束

相关推荐

如何访问axonomy-xxx.php模板文件中的$Query变量?

在自定义模板文件中,我按以下方式创建查询:<?php $query = new WP_Query(array(\'post_type\' => \'aya-bi-aya\',\'author\' => $current_user->ID,\'paged\' => $paged, \'post_status\' => array(\'publish\') ) ); ?> 为了执行分页,我在循环之后调用分页函数,如下所示:<?php my_pagina