Wonderful! WordPress

画像の枚数によるタグクラウドの自作

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

サイドバーにタグクラウドを表示するのに wordpress には標準で wp_tag_cloud() という関数が用意されていますし、フォントの大きさだけでなく色も変えるなどプラグインも数多く存在しています。

実際、以前は WP Colorful Tag Cloud を使用していましたし、 WP-Cumulus は今も使用中です。(いえ、もう、だいぶ前に使わなくなっています)
ただ、どれもタグクラウドは投稿タグにしてもカテゴリーにしてもその使用頻度、その投稿タグ(カテゴリー)が使用されている投稿の件数が表示の基準となっています。

私の画像サイトは鳥名を投稿タグに使っていますが、投稿の件数ではなくその投稿タグに属する画像の枚数を基準にしてタグクラウドを表示させたいのです。というところで自分で作ることにします。
これには別にも使用したいことがあって、画像一覧のページにおいて、鳥名で絞り込んでの画像一覧を表示させる場合に、その鳥名をタグクラウドから指定するのに使いたいということです。

関数で、その投稿タグに属する画像の数を得ることができるのか、そもそもそんな関数が存在するのかすらわからなかったので関数はあきらめて直接データベースにアクセスすることにしました。
SQL に関しては前ページ画像一覧ページでお世話になった「PHPによるWordPressカスタマイズブック―3.x対応」の本を参考にして試行錯誤して組み立てました。
投稿タグに属する画像の個数を求める SQL は以下のようでいいと思います。

SELECT COUNT(a.ID) FROM $wpdb->posts a, $wpdb->posts p, $wpdb->term_relationships r, $wpdb->term_taxonomy x, $wpdb->terms t
WHERE  a.post_parent = p.ID
AND p.ID = r.object_id
AND r.term_taxonomy_id =x.term_taxonomy_id
AND x.term_id=t.term_id
AND a.post_mime_type LIKE 'image/%'
AND a.post_type = 'attachment'
AND p.post_status = 'publish'
AND x.taxonomy='post_tag'
AND t.slug='${stag_name}'
SQL
CopyExpand

${stag_name} に投稿タグのslugを入力します。

このタグクラウドを自作するにあたって出力に関しては表示で2種類、そしてそれぞれにリンクで2種類、計4種類の出力を考えています。
鳥画像の英名、学名を掲載しているのでアクセスログを見ていると外国からのアクセスも少数あったりします。日本語環境のない人たちにどのように表示されるのかよくわかりませんが、少なくとも日本語は文字化けするだけだと思われるので、その場合は日本語の表示は無い方が良いはずです。で、鳥名の一覧がわかるだけでもいいのではと思い、ブラウザの言語設定に ja 以外の言語が設定されている場合はタグリストとして英名で表示しようというのが一つです。
そして、リンクに関しては普通に投稿タグのページ tag.php などに対してのリンクと投稿タグによって絞り込んだ画像一覧ページを表示するためのリンクです。
と、いうことで作成する関数には2つの引数を設けました。

<?PHP
function createtagscloud($openum,$eng){
	global $wpdb; 

	$tags_names=get_tags('sort_column=menu_order');
	$tag_num=0;
	$maxcount=0;
	$tag_data=array();
	foreach($tags_names as $list){

		$stag_name=$list->slug;
$sql=<<<HERE
SELECT COUNT(a.ID) FROM $wpdb->posts a, $wpdb->posts p, $wpdb->term_relationships r, $wpdb->term_taxonomy x, $wpdb->terms t
WHERE  a.post_parent = p.ID
AND p.ID = r.object_id
AND r.term_taxonomy_id =x.term_taxonomy_id
AND x.term_id=t.term_id
AND a.post_mime_type LIKE 'image/%'
AND a.post_type = 'attachment'
AND p.post_status = 'publish'
AND x.taxonomy='post_tag'
AND t.slug='${stag_name}'
HERE;
		$tag_counter=$wpdb->get_var($sql);
		$tag_data[$list->slug]=$list->name."-".$tag_counter;
		if($maxcount<$tag_counter){
			$maxcount=$tag_counter;
		}
	}
		
	if($maxcount<10){
		$maxcount=10;
	}else{
		$maxcount=ceil($maxcount/10)*10-150;
	}
	$d1=floor($maxcount*0.1);
	$d2=floor($maxcount*0.2);
	$d3=floor($maxcount*0.3);
	$d4=floor($maxcount*0.4);
	$d5=floor($maxcount*0.5);
	$d8=floor($maxcount*0.75);
	$d9=floor(($maxcount+100)*0.9);

	if($eng==1){
		ksort($tag_data,SORT_STRING);
		echo "<ul id=\"engtags\">";
	}
		
	foreach($tag_data as $key=>$val){
		$nameval=mb_substr($val,0,mb_strpos($val,"-"));
		$countval=mb_substr($val,mb_strpos($val,"-")+1);
		if($countval==0){
			$tag_num=8;
		}elseif($countval<=8){
			$tag_num=0;
		}elseif($countval<=$d1){
			$tag_num=1;
		}elseif($countval<=$d2){
			$tag_num=2;
		}elseif($countval<=$d3){
			$tag_num=3;
		}elseif($countval<=$d4){
			$tag_num=4;
		}elseif($countval<=$d5){
			$tag_num=5;
		}elseif($countval<=$d8){
			$tag_num=6;
		}elseif($countval<=$d9){
			$tag_num=7;
		}else{
			$tag_num=9;
		}
		if($openum==0){
			if($eng==0){
				echo '<a href="'.get_term_link($key,'post_tag').'" class="imgtags'.$tag_num.'" title="'.$countval.'件">'.$nameval.'</a>&ensp;';
			}else{
				$engname=str_replace("_"," ",$key);
				echo '<li><a href="'.get_term_link($key,'post_tag').'" title="'.$countval.'pieces"><span class="imgtags'.$tag_num.' eimgtag">'.$engname.'</span></a></li>';
			}
		}else{
			if($eng==0){
				echo "<a href=\"JavaScript:sendtagslug('x".$key."')\" class=\"imgtags".$tag_num."\" title=\"".$countval."件\">".$nameval."</a>&ensp;";
			}else{
				$engname=str_replace("_"," ",$key);
				echo "<li><a href=\"JavaScript:sendtagslug('x".$key."')\" title=\"".$countval."pieces\"><span class=\"imgtags".$tag_num." eimgtag\">".$engname."</span></a></li>";
			}
		}
	}
	if($eng==1){
		echo "</ul>";
	}			
}
?>
PHP
CopyExpand

2行目の引数に関しては $openum がリンク、 $eng が日本語か英語かの指定。 $openum ==0で通常の投稿タグページ、!=0で画像一覧、 $eng ==0で日本語、!=0で英語表示。
3行目の global $wpdb; はfunction.php内の関数でデータベースにアクセスするときのお約束で必要です。
5行目で全投稿タグの情報を取得します。
9行目から投稿タグ一つ一つに対して処理するループの開始です。
11から24行目でその投稿タグに属する画像の数を取得。
25行目で投稿タグのslugを添え字にして和名と画像の数を”ー”でつないだ文字列の連想配列を生成していきます。これは英語表示の時にタグのデータをまとめてslugをアルファベット順で並び替えるために作っています。
26から28行目で画像の個数の最大値をもとめています。
31から42行目まではループが終わり全投稿タグの個数を得られたところで、画像の個数によるclass分けのための数値を設定しています。34行目の”-150”、42行目の”+100”という数字は私のサイトにおいて画像の数の多い2種類が他より突出しているために他とのバランスをとるための小細工です。たいした意味はありません。
44から47行目は英語表示指定($eng==1)の時、生成したタグのデータが入った連想配列を添え字のslugでアルファベット順に並び替えています。そして英語表示の場合は<li></li>タグで出力するので先んじて<ul>タグを出力しておきます。
49から88行目のループで全投稿タグの情報を出力します。 $openum $eng によって条件分けしています。82行目と85行目の JavaScript:sendtagslug は投稿タグで絞り込んで画像一覧ページを表示するための関数ですがこの部分はまだ未投稿です。
最後に英語表示の場合は</ul>タグを出力します。
・・・

2013年4月3日追記。

上記期日にアップしたphpのチューニングによるサイト表示速度の改善の記事においてこの自作タグクラウドのコードも改善しました。

<?php
function createtagscloud($openum,$eng){
	global $wpdb; 

	//日本語表示か英語かの指定は始めにソートさせる項目を指定する。
	if($eng==0){
		$tags_names=get_tags('orderby=name');
	}else{
		$tags_names=get_tags('orderby=slug');
	}
	$tag_num=0;
	$maxcount=0;
	$tag_data=array();
	$japary=array();
	$cntary=array();
	/*画像の枚数によって表示する色のクラスの度合いを決めるために
	最多枚数のデータをまず得る。
	一度オブジェクトをループさせるのでその時に必要なデータを配列に
	収め、以前のように連想配列を使うのは止めてそれぞれ個別の配列に
	した。*/
	foreach($tags_names as $list){
		$stag_name=$list->slug;
$sql=<<<HERE
SELECT COUNT(a.ID) FROM $wpdb->posts a, $wpdb->posts p, $wpdb->term_relationships r, $wpdb->term_taxonomy x, $wpdb->terms t
WHERE  a.post_parent = p.ID
AND p.ID = r.object_id
AND r.term_taxonomy_id =x.term_taxonomy_id
AND x.term_id=t.term_id
AND a.post_mime_type LIKE 'image/%'
AND a.post_type = 'attachment'
AND p.post_status = 'publish'
AND x.taxonomy='post_tag'
AND t.slug='${stag_name}'
HERE;
		$tag_counter=$wpdb->get_var($sql);
		$tag_data[]=$stag_name;
		$japary[]=$list->name;
		$cntary[]=$tag_counter;
		if($maxcount<$tag_counter){
			$maxcount=$tag_counter;
		}
	}
		
	if($maxcount<10){
		$maxcount=10;
	}else{
		$maxcount=ceil($maxcount/10)*10-480;
	}
	$d1=floor($maxcount*0.1);
	$d2=floor($maxcount*0.2);
	$d3=floor($maxcount*0.3);
	$d4=floor($maxcount*0.4);
	$d5=floor($maxcount*0.5);
	$d8=floor($maxcount*0.75);
	$d9=floor(($maxcount+100)*0.9);

	if($eng==1){
		echo '<ul id="engtags">';
	}
		
	foreach($tag_data as $key=>$val){
		$countval=$cntary[$key];
		$countint=intval($countval);
		if($countint==0){
			$tag_num=8;
		}elseif($countint<=8){
			$tag_num=0;
		}elseif($countint<=$d1){
			$tag_num=1;
		}elseif($countint<=$d2){
			$tag_num=2;
		}elseif($countint<=$d3){
			$tag_num=3;
		}elseif($countint<=$d4){
			$tag_num=4;
		}elseif($countint<=$d5){
			$tag_num=5;
		}elseif($countint<=$d8){
			$tag_num=6;
		}elseif($countint<=$d9){
			$tag_num=7;
		}else{
			$tag_num=9;
		}
		if($openum==0){
			if($eng==0){
				echo '<a href="https://strix.main.jp/?tag='.$val.'" class="imgtags'.$tag_num.'" title="'.$countval.'枚">'.$japary[$key].'</a>&ensp;';
			}else{
				$engname=ucwords(strtr($val,'_',' '));
				echo '<li><a href="https://strix.main.jp/?tag='.$val.'" title="'.$countval.'pieces"><span class="imgtags'.$tag_num.' eimgtag">'.$engname.'</span></a></li>';
			}
		}else{
			if($eng==0){
				echo "<a href=\"JavaScript:sendtagslug('x".$val."')\" class=\"imgtags".$tag_num."\" title=\"".$countval."枚\">".$japary[$key]."</a>&ensp;";
			}else{
				$engname=ucwords(strtr($val,'_',' '));
				echo "<li><a href=\"JavaScript:sendtagslug('x".$val."')\" title=\"".$countval."pieces\"><span class=\"imgtags".$tag_num." eimgtag\">".$engname."</span></a></li>";
			}
		}
	}
	if($eng==1){
		echo '</ul>';
	}			
}
?>
PHP
CopyExpand

各投稿タグページへのリンクは関数を使わないで、「/?tag=」+slugというパターンが決まっているので文字列にて直に指定しています。
・・・

後になって良く見てみるとまだまだ速度アップのマージンはありそうです。
と、いろいろあーだこーだと考えた末に、次なる一手を講じました。
ここのページが長くなりそうなので、続きは新しいページ、「続、画像の枚数によるタグクラウドの自作」へと展開することにします。

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=16258

Sanbanse Funabashi

Top

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