“问题”在一个页面上加载许多特色图片(自定义模板)

时间:2014-03-13 作者:SlackerCoder

我有一个页面,在网格中加载了许多特色项目。加载多达56幅图像,确实有点延迟。这是它现在运行的代码:

if( count( $postslist ) > 0 ) {
  foreach ($postslist as $post) : setup_postdata($post);
  ?> 
  <div class=\'oneCell\'>
    <?php 
    $image = get_the_post_thumbnail($this_post->ID, \'full size\'); 
    $imageSrc = substr($image, strpos($image, "src") + 5);
    $imageSrc = substr($imageSrc, 0, strPos($imageSrc, "\\""));
    $finalImage = "<img class=\'lazy\' src=\'/images/grey.png\' data-original=\'";
    $finalImage .= $imageSrc . "\' />";
    $lastImage = "<a href=\'";
    $lastImage .= catch_that_image();
    $lastImage .= "\'>";
    $lastImage .= $finalImage;
    $lastImage .= "</a>";
    echo $lastImage;
    ?>
  </div>
  <?php 
  $currentCount = $currentCount + 1;
  endforeach;
}
我知道代码有问题,基本上循环中的每个图像都会对数据库执行一次,这导致了速度变慢。

有人能帮我找到一个加速装载的解决方案吗?我的想法是一次从数据库中获取所有内容并从那里显示出来,但我还没有弄清楚如何处理它。

谢谢

编辑:

对不起,我应该再解释一下:

get\\u The\\u post\\u缩略图需要全尺寸图像,因为全尺寸图像是它所需要的(189x189)。帖子中的特色图片就是该图片,并且始终是189x189。

catch\\u that\\u image()仅在用户使用js库(magnific popup.js)单击特征图像(缩略图)时,抓取帖子正文中要显示的第一个(也是唯一一个)图像。

编辑2:

看起来我的问题与数据库有关。通话速度太慢,无法一次接听一个电话(因为电话太多了)。有没有办法在一次通话中恢复所有内容,然后再从那里进行处理?

2 个回复
SO网友:gmazzap

答案是eager loadingcache 或者两者兼而有之。

快速加载看看这个伪代码:

$ids = get_ids_from_a_db_table();
foreach ( $ids as $id ) {
  $row = get_row_from_foreign_table_using( $id );
  echo "Row title for the ID: $id is $row->title";
}
如果$idsn 比这个简单的代码运行n+1 查询,首先加载id,然后为每个id加载一个id。

你的代码更糟糕,它对每个id运行2个查询,一个用于获取附件帖子对象,一个用于获取附件url(WordPress,不是你,真的吗)

所以您运行2n+1个查询。。。

渴望加载(指db查询)是通过仅在中查询来解决n+1(或2n+1)查询问题的方法one db请求您需要的所有数据(通常使用适当的JOIN + WHERE )

$data = get_data_from_joined_db_tables();
foreach ( $data as $row ) {
  echo "Row title for the ID: $row->id is $row->title";
}
这在WordPress中是如何实现的?你需要两件事:

添加适当的join和where子句以合并post meta表过滤返回的字段WP_Query 要包含元表字段,可以使用查询过滤器来完成这两个操作,这里是一个扩展类WP_Query 这样做:

class Thumb_Query extends WP_Query {

  protected static $args = array( \'nopaging\' => TRUE );

  public function __construct( $args = \'\' ) {
    if ( empty( $args ) ) $args = self::$args; // defaults
    parent::__construct( $args );
  }

  public function get_posts() {
    add_filter(\'posts_clauses\', array( __CLASS__, \'thumb_filters\') );
    $results = parent::get_posts();
    remove_filter(\'posts_clauses\', array( __CLASS__, \'thumb_filters\') );
    return $this->parse_images( $results );
  }

  public static function thumb_filters( $pieces ) {
    $meta = $GLOBALS[\'wpdb\']->postmeta;
    $posts = $GLOBALS[\'wpdb\']->posts;
    $pieces[\'fields\'] .= ", thumbs.meta_value as thumb_id";
    $pieces[\'fields\'] .= ", imgs.post_title as thumb_title";
    $pieces[\'fields\'] .= ", imgdata.meta_value as thumb_file";
    $pieces[\'join\'] .= "INNER JOIN {$meta} thumbs ON ({$posts}.ID = thumbs.post_id)";
    $pieces[\'join\'] .= " INNER JOIN {$posts} imgs ON (thumbs.meta_value = imgs.ID)";
    $pieces[\'join\'] .= " INNER JOIN {$meta} imgdata ON (imgs.ID = imgdata.post_id)";
    $where = " AND ( thumbs.meta_key = \'_thumbnail_id\' AND ";
    $where .= " CAST( thumbs.meta_value AS SIGNED ) > 0 )";
    $where .= " AND ( imgdata.meta_key = \'_wp_attached_file\' )";
    $pieces[\'where\'] .= $where;
    $pieces[\'groupby\'] = " {$posts}.ID";
    return $pieces;
  }

  protected function parse_images( $rows ) {
    $exts = array(\'jpg\', \'jpeg\', \'gif\', \'png\');
    foreach ( $rows as $i => $row ) {
       $urls = wp_extract_urls( $row->post_content );
       $img = FALSE;
       while ( ! $img && ! empty($urls) ) {
         $url = array_shift($urls);
         $ext = strtolower ( pathinfo( $url, PATHINFO_EXTENSION ) );
         if ( in_array( $ext, $exts ) ) $img = $url;
       }
       $rows[$i]->thumb_link = $img ? $img : \'#\';
    }
  }
}
此类扩展WP_Query, 因此,它接受其父级的相同内容,但添加一些过滤器来更改急于加载的thumnail帖子id、thumnail帖子名称和缩略图文件路径。

因此,如果您的查询返回50篇文章,要显示缩略图,请运行101(2n+1)个查询,我的类您只运行1个查询。

此外,在输出结果之前,该类解析所有行,并从帖子内容中提取第一个图像url,并删除添加的过滤器。

如何使用标准WP_Query 参数:

$args = array(
  \'post_type\' => \'portfolio\',
  \'category_name\' => \'featured\',
  \'posts_per_page\' => 50
);
但是使用Thumb_Query 而不是WP_Query

$portfolio = new Thumb_Query( $args );
然后循环并输出:

if ( $portfolio->have_posts() ) {
  $u = wp_upload_dir();
  global $post;
  foreach( $portfolio->posts as $post ) { 
    setup_postdata( $post );
    $f = \'<div class="oneCell"><a href="%s" title="%s">\';
    $f .= \'<img class="lazy" alt="%s" width="189" src="%s" data-original="%s"/>\';
    $f .= \'</a></div>\';
    $title = esc_attr( get_the_title() );
    printf( $f,
      esc_url( $post->thumb_link ),
      $title, $title,
      esc_url( get_template_directory_uri() . \'/images/grey.png\'  ),
      esc_url( trailingslashit($u[\'baseurl\']) . $post->thumb_file )
    );
  }
  wp_reset_postdata();
}
在循环中,您可以访问所有标准帖子属性,但每个帖子都有额外的4个属性:

  • $post->thumb_id 缩略图附件id$post->thumb_title 缩略图附件标题$post->thumb_file 相对于上载文件夹的缩略图文件,类似于\'/2014/04/myfile.jpg\'
  • $post->thumb_link 发布内容中第一个图像的完整url,如果未找到图像,则为“#”

SO网友:Pieter Goosen

很难理解你做了什么。我担心的一个问题是使用get_the_post_thumbnail()catch_that_image() 在相同的代码中一起完成。我知道catch_that_image() 函数,并且以前使用过它。这是一个很好的函数,通常由编码器用来检索第一幅图像以在摘录中显示它。然而,有更好的方法可以在没有catch_that_image(). 我真的认为这会减慢你的网站速度,因为它是一个独立于循环运行的外部功能,特别是当你需要检索56幅图像时。catch_that_image() 需要在每篇文章上运行以检索图像,因此执行了56次。如果我错了,请纠正我。

我不知道你的循环是什么样子,但看起来有点乱。我认为最好的方法是使用WP_Query 与…结合get_posts 构建循环。

在里面WP_Query 你只需要通过一个参数就可以了,posts_per_page. 您需要将此设置为1, 否则,您将多次获得相同的图像。

下一步是运行循环,并使用post_typepost_mime_type. Wordpress将所有附件保存为post type. 并非所有附件都是图像,因此需要指定仅返回作为图像的附件。这是由指定的post_mime_type.

wp_get_attachment_image 将用于返回指定大小的这些图像,在您的代码中,这将是全尺寸的特征图像。

这一切都完成了,整个循环看起来像这样

<?php 
    $new_query = new WP_Query(array(
        \'posts_per_page\'   => 1,
    ));

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

            $args = array (
                \'post_type\' => \'attachment\',
                \'numberposts\' => 56,
                \'status\' => \'publish\',
                \'post_mime_type\' => \'image\',
                \'parent\' => $post->ID
            ); 

            $attachments = get_posts($args);

            if ( $attachments ) {
                foreach ( $attachments as $attachment ) {
                    echo \'<div class="oneCell">\';
                    echo \'<a href="\' . get_permalink( $post->ID ) . \'">\';
                    echo wp_get_attachment_image( $attachment->ID, \'full\' );
                    echo \'</a>\';
                    echo \'</div>\';
                }
            };

        endwhile;

wp_reset_postdata();

?>   
您只需更改参数以满足您的确切需求,但我希望这是您需要的基本平台,可以从中工作,这对提高速度有很大帮助。享受

Edit不要忘记使用重置查询wp_reset_postdata();

结束

相关推荐

Custom post types templates

我已经注册了一个名为“Services”的自定义帖子类型,但当我给这篇帖子提供模板“single Services.php”时,它不接受这个,而是选择了“homepage.php”模板,你能告诉我这个问题吗?它也没有使用“archive services.php”模板,而是使用blog模板(index.php)使现代化代码如下:add_action(\'init\', \'services_register\'); function services_register() { $