私はグリッド内の多くの注目アイテムをロードするページを持っています。最大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;
}
私は、コードに問題があることを理解しています。基本的には、ループ内のすべての画像についてデータベースを1回ヒットするため、処理が遅くなります。
誰もがロードをスピードアップするための解決策を手伝ってくれる?私の考えは、データベースからすべてを一度に取得してそこから表示することですが、それをどのように処理するかについてはまだわかっていません。
ありがとうございます。
編集する
申し訳ありませんが、これについてもう少し説明しておく必要があります。
フルサイズのイメージは必要なものなので、get_the_post_thumbnailはフルサイズのイメージを要求しています。投稿の特集画像はその画像で、常に189 x 189になります。
catch_that_image()は、ユーザーがjsライブラリ(magnific-popup.js)を使用して注目の画像(サムネイル)をクリックしたときに表示される、投稿本文の最初の(かつ唯一の)画像を取得するだけです。
編集2:
私の問題はデータベース関連のようです。呼び出しが遅すぎるため、一度に1つずつ呼び出すことはできません(非常に多数あるため)。 1回の呼び出しですべてを取り戻して、そこから処理する方法はありますか?
答えはeager loadingまたはcache、あるいはその両方です。
この擬似コードをご覧ください:
$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";
}
$ids
の数がn
の場合、この単純なコードはn+1
クエリを実行し、最初にIDをロードし、次にIDごとに1つをロードします。
あなたのコードはさらに悪いです、すべてのIDに対して2つのクエリを実行し、1つは添付ファイルの投稿オブジェクトを取得し、もう1つはattachemnt URLを取得します(実際にはWordPressです)
したがって、2n + 1クエリを実行します...
Dbクエリと呼ばれるEager Loadingは、必要なすべてのデータをone dbリクエストのみでクエリすることにより、n + 1(または2n + 1)クエリの問題を解決する方法です(通常は適切な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でそれをどのように行いますか?次の2つが必要です。
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、または画像が見つからない場合は「#」あなたがしたことを理解するのはかなり難しいです。私の懸念の1つは、あなたがしたのと同じコードの中でget_the_post_thumbnail()
とcatch_that_image()
を一緒に使うことです。私はcatch_that_image()
関数の知識があり、以前にそれを使用しました。それは抜粋でそれを表示するために最初の画像を検索するためにコーダーによって通常使用されるNice-to-know-functionです。しかし、catch_that_image()
なしで同じ結果を得るためのより良い方法があります。特に56個の画像を取得する必要がある場合は、ループとは別に実行される外部関数であるため、サイトの速度は遅くなります。 catch_that_image()
は画像を取得するためにすべての投稿に対して実行する必要があるので、56回実行されます。私がここで間違っているなら私を直してください。
ループがどのように見えるかわかりませんが、それは少し面倒なようです。ここに行く最良の方法は、 WP_Query
を get_posts
と組み合わせて使用してループを構築することです。
WP_Query
では、これを機能させるために1つの引数posts_per_page
を渡すだけで済みます。これを1
に設定する必要があります。そうしないと、同じ画像が複数回表示されます。
次に、ループを実行し、post_type
とpost_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();
?>
あなたはちょうどあなたの正確なニーズを満たすために引数を変更する必要があります、しかし、私はこれがあなたが必要とし、そしてこれから働くことができる基本的なプラットフォームであり、これが本当にスピードで非常に役立つことを願っています。楽しい。
編集wp_reset_postdata();
を使ってクエリをリセットすることを忘れないでください