この記事は公開または最後に更新されてから538日が経過しています。情報が古くなっている可能性があるのでご注意下さい。

画像サイトに画像一覧ページはつきものです。
無いと困るというものでもありませんが、やはり一覧表示できれば便利ですから欲しいと思います。


画像一覧ページに関しては、この本の「画像一覧のページを作る」の項目を基本的にほぼそのまま利用させていただきました。
データベースに直接アクセスする方法をはじめとして、多くのことを学ぶことができた本です。とてもお世話になりました。
自分のページにあわせて改良した点はといえば、読み込む画像の数が多いのでミドルサイズを読み込むように変更しました。
画像のアドレス/概要/タイトルを得る の部分です。

<?php
// 画像のアドレス/概要/タイトルを得る
	$post = $attachment;
	setup_postdata($post);
	$url = wp_get_attachment_url($post->ID);
	$alt = $post->post_content;
	$title = $post->post_excerpt;
	$midimg= wp_get_attachment_image_src($post->ID,'medium');
	$urlmini=$midimg[0];
?>
PHP
CopyExpand

7~8行目が追加した分。
wp_get_attachment_image_src($post->ID,'medium') で画像のpostのIDを指定し medium サイズの画像の情報を得ます。
この場合の情報は配列にて返され、

  • [0]=>url
  • [1]=>width
  • [2]=>height

と、なっています。
そして実際に画像を出力するところの <img src="<?php echo $url; ?> の部分の $url $urlmini に置き換えています。

<?php if ($row_first) : ?><tr><?php endif; ?>
  <td class="one-image">
    <table class="one-image-tbl">
      <tr>
        <td class="one-image-tbl-img">
	      <a href="JavaScript:showpop('<?php echo $url; ?>')"><img src="<?php echo $urlmini; ?>" width="<?php echo $width; ?>" height="<?php echo $height; ?>" alt="<?php echo $alt ?>" title="<?php echo $title ?>" /></a>
        </td>
      </tr>
PHP
CopyExpand

このページでも画像をクリックした時の拡大表示の処理はここの前のページ画像をクリックした時のログで修正をくわえた showpop 関数を使用しています。
・・・

※ 2020/3/16 追記

この記事を書いてから(画像一覧ページを初めて作ったときからという方がいいのか)、随分と改良を重ねてもともとのものからはかなり違ったものになっていたりする。どういうやり方が良いのだろうかといろいろと試したみたことの備忘録。どこかに残しておかないとまちがいなく忘れてしまうので。

SQL の処理速度を考えるなら、取得する項目を少なくする、検索する条件を少なくする、関連づけるテーブルを少なくする、といったことを吟味する必要がある。例えば、教本においては、画像のデータが入っているwp_posts テーブルの、その画像のデータはすべて取得しているのだけれど、自分の場合であれば必要なものは、画像データのIDとその親投稿のID ( post_parent )だけ。メディアとしてアップロードしているのは画像のみだとしたら、post_mime_type LIKE 'image/%' の条件はいらない。
であればそのSQL はこんな具合になる。

<?php
$sql = <<< HERE
SELECT a.ID,a.post_parent FROM $wpdb->posts a, $wpdb->posts p
WHERE a.post_parent = p.ID
AND a.post_type = 'attachment'
AND p.post_type = 'post'
AND p.post_status = 'publish'
ORDER BY p.post_date DESC,a.post_title DESC
LIMIT $offset, $per_page
HERE;

$attachments = $wpdb->get_results($sql);
?>
PHP
CopyExpand

そして画像を順に書き出す処理となる。
レイアウトにテーブルを使うなんてことは昔話。

<article class="image-list">
<?php
	$ctr = 0;
	$post_title = '';
	$attached_title = '';
	$parentid = 0;
	$post_url = '';
	$prevprtpostid = 0;

	// 画像を順に出力する
	foreach ($attachments as $attachment) {

		// 画像の貼り付け先投稿のタイトルとアドレスを得る
		$parentid = $attachment -> post_parent;

		// 前の画像と貼り付け先投稿が異なる場合だけその親投稿の情報を取得
		if ( $prevprtpostid !== $parentid ) {
			$post_title = get_the_title( $parentid );
			$attached_title = 'Post:' . get_the_date ( 'Y/m/d', $parentid );
			$post_url = get_permalink( $parentid );
			$prevprtpostid = $parentid;
		}

		// 画像のアドレス/概要/タイトルを得る
		$attchid = $attachment->ID;
		$tmpmeta = get_post_meta( $attchid, '_wp_attachment_metadata', true );
		$url = $tmpmeta['file'];
		$midimgsize = '-' . $tmpmeta['sizes']['medium']['widht'] . 'x' . $tmpmeta['sizes']['medium']['height'] . '.jpg';
		$urlmini ='https://strix.main.jp/wp-content/uploads/' . str_replace ( '.jpg', $midimgsize, $url );
		$alt = $post_title;
		$title='';

		++$ctr;

		if ( 1 == $ctr % $per_row ) {// 行の先頭の場合
			echo '<div class="row">'."\n";
		}

?>
		<div class="one-image">
			<p class="one-image-tbl-img">
				<span data-img="<?php echo $url; ?>" class="pimga"><img src="<?php echo $urlmini; ?>" alt="<?php echo $alt ?>" /></span>
			</p>
			<ul class="one-image-tbl-caption">
				<li><?php echo $post_title; ?></li>
				<li><a href="<?php echo $post_url; ?>" title="This image's post page" class="singlelink"><?php echo $attached_title; ?></a></li>
			</ul>
		</div>
<?php
		if ( 0 == $ctr % $per_row ) {// 行の最後の場合
			echo '</div>' . "\n";
		}
	}// end-foreach

	if ( 0 !== $ctr % $per_row ) {// 最後の行で画像が半端な数で終わっている場合
		echo '</div>';
	}
?>
</article>
PHP
CopyExpand

25行目から28行目で、ミディアムサイズの画像の情報を取得するのに、その一例としてget_post_meta() を使う方法もあると。
get_post_meta() といえば、カスタムフィールドの値を取得するときに使うやつね。画像のサムネイルなんかの情報というのは、post ID で関連づけられてwp_postmeta テーブルに保存されている。して、そのkey は、'_wp_attachment_metadata' 。ゆえにその値は、get_post_meta() で取得することができるわけです。
配列で返されるその値は、例えば下のようになってるので必要な値を使えば良いということ。

array(5) { 
	["width"]=> int(1280) 
	["height"]=> int(960) 
	["file"]=> string(22) "2020/02/2001170013.jpg" 
	["sizes"]=> array(2) {   
		["medium"]=>   array(4) {     
			["file"]=>     string(22) "2001170013-500x375.jpg"     
			["width"]=>     int(500)     
			["height"]=>     int(375)     
			["mime-type"]=>     string(10) "image/jpeg"   
		}   
		["thumbnail"]=>   array(4) {     
			["file"]=>     string(22) "2001170013-150x150.jpg"     
			["width"]=>     int(150)     
			["height"]=>     int(150)     
			["mime-type"]=>     string(10) "image/jpeg"   
		} 
	} 
	["image_meta"]=> array(12) {   
		["aperture"]=>   string(1) "0"   
		["credit"]=>   string(0) ""   
		["camera"]=>   string(0) ""   
		["caption"]=>   string(0) ""   
		["created_timestamp"]=>   string(1) "0"   
		["copyright"]=>   string(0) ""   
		["focal_length"]=>   string(1) "0"   
		["iso"]=>   string(1) "0"   
		["shutter_speed"]=>   string(1) "0"   
		["title"]=>   string(0) ""   
		["orientation"]=>   string(1) "0"   
		["keywords"]=>   array(0) {   } 
	}
}
PHP
CopyExpand

というか、当然のこと、この値を得るための関数がちゃんとあったりして。それが、wp_get_attachment_metadata() 。 まぁ、サイズを指定せずに画像のデータがほしいときはこの関数を使えばいいってことでした。あはっ!
で、こういうことを考えていて、ふと、気がついたのは、ならばいっそのこと画像の情報をSQL で取得するときに一緒に画像のmeta 情報も取得してしまえばよいのでは!ってこと。
こんな具合に!

<?php
SELECT a.ID,a.post_parent,b.meta_value FROM wp_posts a, wp_posts p, wp_postmeta b
WHERE a.post_parent = p.ID
AND a.post_type = 'attachment'
AND p.post_type = 'post'
AND p.post_status = 'publish'
AND a.ID = b.post_id
AND b.meta_key = '_wp_attachment_metadata'
ORDER BY p.post_date DESC,a.post_title DESC
LIMIT $offset, $per_page

$attachments = $wpdb->get_results($sql);
?>
PHP
CopyExpand

まぁ、予想通り、テーブルが増えて条件も増えるので結果はかなり遅くなる。画像のデータが128366個ある状況では、meta_value 無しで0.5615秒、有りで1.6246秒という結果。ただ、実際に1ページに表示する画像の数は100もないだろうし、html を書き出す段階で画像の情報を取得するためのデータベースアクセスがなくなることを考えると、どっちかな?という感じはする。
ただし、この場合のmeta_value の値はデータベースの値そのままでシリアライズされた値となっているので、もうひと手間必要となる。そのシリアライズされた値というのはvar_dump すると下のようになってる。

object(stdClass)#4538 (2) {
	["post_parent"]=>string(5) "22840"
	["meta_value"]=>string(675) "a:5:{
		s:5:"width";i:1280;
		s:6:"height";i:960;
		s:4:"file";s:22:"2019/12/1911292772.jpg";
		s:5:"sizes";a:2:{
			s:6:"medium";a:4:{
				s:4:"file";s:22:"1911292772-500x375.jpg";
				s:5:"width";i:500;
				s:6:"height";i:375;
				s:9:"mime-type";s:10:"image/jpeg";
			}
			s:9:"thumbnail";a:4:{
				s:4:"file";s:22:"1911292772-150x150.jpg";
				s:5:"width";i:150;
				s:6:"height";i:150;
				s:9:"mime-type";s:10:"image/jpeg";
			}
		}
		s:10:"image_meta";a:12:{
			s:8:"aperture";s:1:"0";
			s:6:"credit";s:0:"";
			s:6:"camera";s:0:"";
			s:7:"caption";s:0:"";
			s:17:"created_timestamp";s:1:"0";
			s:9:"copyright";s:0:"";
			s:12:"focal_length";s:1:"0";
			s:3:"iso";s:1:"0";
			s:13:"shutter_speed";s:1:"0";
			s:5:"title";s:0:"";
			s:11:"orientation";s:1:"0";
			s:8:"keywords";a:0:{}
		}
	}"
}
PHP
CopyExpand

と、いうことでこの値はデシリアライズして使うことになる。
画像情報を処理する部分だけを書き出すと下のよう。
5行目でデシリアライズした値を配列にて受け取ってる。

<?php
foreach ( $attachments as $attachment ) {

	// 画像のアドレス/概要/タイトルを得る
	$tmpdata = ( array ) unserialize ( $attachment -> meta_value );
	$urldata = $tmpdata['file'];
	$tmpwidth = ( string ) $tmpdata['sizes']['medium']['widht'];
	$tmpheight = ( string ) $tmpdata['sizes']['medium']['height'];
	$midsize = '-' . $tmpwidht . 'x' . $tmpheight . '.jpg';
	$urlmini = 'https://strix.main.jp/tns/wp-content/uploads/' . str_replace ( '.jpg', $midsize, $urldata );

	// ここにhtml を書き出す処理
}
?>
PHP
CopyExpand

教本のもともとのやり方だと、まず画像の数を得てからオフセットを計算して、そのページに表示するのに必要な数の画像データを取得するという方法。まぁ、それが理屈にあったまっとうな方法だとは思う。そうじゃなくてもいいのなら、もしかすると少しでも速くなるかも?という手も試してみるのもいい。そもそもの画像の数がしれた数しかないのであれば、いきなりのSQLですべての画像のデータで必要な項目だけ取得してしまうという方法もありなのではなかろうか。それならSQL 発行も一度ですむ。あとはオフセットを求めて、1ページに表示する画像数で配列を使用する部分だけarray_slice() で抜き取って、不必要な部分は開放、というのはどうだろう。
で、あるカテゴリーだけの画像を表示するページで下のように使用してる。
ちなみに、カテゴリーやタグで投稿を絞り込む場合、name や slug ではなく、そのターム(タクソノミー)ID を使えば、wp_terms テーブルは不必要となるので、テーブルを一つ減らす事ができる。

<?php
$sql = <<< HERE
SELECT a.post_parent, b.meta_value FROM wp_posts a, wp_posts p, wp_term_relationships r, wp_term_taxonomy x, wp_postmeta b
WHERE a.post_parent = p.ID
AND p.ID = r.object_id
AND r.term_taxonomy_id =x.term_taxonomy_id
AND a.post_type = 'attachment'
AND p.post_status = 'publish'
AND x.term_id = 91
AND a.ID = b.post_id
AND b.meta_key = '_wp_attachment_metadata'
ORDER BY p.post_date DESC
HERE;

	$allimages = $wpdb->get_results( $sql );
	$count = count ( $allimages );

	$per_page = 42;

	if ( $count ) {
		// 画像の数から全ページ数を求める
		$page_counts = ceil ( $count / $per_page );

		// URLからページ番号を得る
		$page_no = ( int ) $wp_query -> get('paged');
		if ( $page_no < 1 ) {
			$page_no = 1;
		} else if ( $page_no > $page_counts ) {
			$page_no = $page_counts;
		}

		// オフセットを求める
		$offset = ( $page_no - 1 ) * $per_page;

		$attachments = array_slice ( $allimages, $offset, $per_page );
		$allimages = null;
	}
?>
PHP
CopyExpand

Leave a Reply!

JavaScript is necessary to send a comment.
You can edit and delete your comment if you input a edit key.
Edit key is necessary for attesting you when you edit and delete it.
The tag of HTML cannot be used in comment.
When you comment for the first time, it is displayed after the approval of the administrator.
Because I cannot speak English so much, it takes time to answer.
Required fields are marked *.

※Please enter more than 5 characters only alphabets.
※Edit or delete are possible for 2000 days after approval.

*

♠Simplistic Comment User Editable v4.0

♠When visitors leave comments on the site this site collect the data shown in the comments form, and also the visitor’s IP address and browser user agent string to help spam detection.
♠This site does not use cookie when visitors leave comments and commenter edit comment.
♠This site uses Akismet to reduce spam. Learn how your comment data is processed.

Comments feed

Trackback URL : https://strix.main.jp/wp-trackback.php?p=16232

Sanbanse Funabashi
2010.10.24 sunrise

Top

スクロールさせるか画像をクリックすると元に戻ります。