WordPressからLeafletのポップアップを操作する

事例の概要

地図表示でマーカーを表示するとき、マーカーをクリックするとポップアップ表示するだけでなく、外部のテキストからポップアップを開くことができれば、より便利です(下図)。

この機能を実現するためには、Leaflet側のマーカーのポップアップとWordPressで表示するテキスト表示を動的に連動させることが必要です。

コード量も増えるので、再利用しやすいようにClassに分けて記述することが理想的です。

【お知らせ】
上記の事例3に示すオブジェクト指向(MVCモデル)の使い方については、本書で詳しく解説しています。


参考文献

参考記事

コード例

事例1:外部からLeafletを操作

事例の概要

本事例は、「Leaflet 外部からポップアップを開く」をもとに作成しました。

コード例
<body>
    <div id="map_1" style="height: 400px;"></div>
</body>

<p>
<a href="1234map_1"onmouseover="popupOn1(0);">【東京都】</a>
<a href="3456map_1" onmouseover="popupOn1(1);">【千葉県】</a>
<a href="589map_1" onmouseover="popupOn1(2);">【埼玉県】</a>
</p>

<script>
//背景地図
	var osm = new L.tileLayer
		('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    		maxZoom: 19,
    		attribution: "Map data © <a href='https://www.openstreetmap.org/copyright' target='_blank'>OpenStreetMap</a> contributors"
		});
	
	var map_1 = L.map('map_1', {
		layers: [osm],	
		center: [35.6896, 139.6918],
		zoom: 9,
    	zoomControl: true
		});

//マーカー情報
  var markers=[];	
	markers[0]=L.marker([35.6896, 139.6918]).addTo(map_1).bindPopup("東京都");
    markers[1]=L.marker([35.6050, 140.1234]).addTo(map_1).bindPopup("千葉県");
    markers[2]=L.marker([35.8572, 139.6490]).addTo(map_1).bindPopup("埼玉県");

//ポップアップを開く関数
  function popupOn1(id){
    markers[id].openPopup();
  }

</script>
上記コードの実行結果

【東京都】 【千葉県】 【埼玉県】

事例2:WordPressのループ処理とLeafletの連携

事例の概要

本事例は、WordPressのサブクエリーによってテキストデータを動的に表示し、そのループ処理の中でLeafletのマーカー表示を行い、WordPressのテキスト側からLeafletのポップアップ操作を行う事例です。

 冒頭のstatic public $const = array() ;でクラス定数$constを定義します。これは、ループ処理の中でマーカーの情報を一時的に格納するための配列定数です。
 $the_query = new WP_Query($args) ;にてサブクエリーを実行します。
 テキストを表示するWhileループの中で、クラス定数$constに、 緯度($lat),経度( $lon), コンテンツのタイトル($title)などを格納します。以上がPHPの処理です。
 次に、HTMLによる背景地図の設定を行います。
 <div id="map_2" style="height: 400px;"></div>
 最後にLeaflet.jsによる描画処理を行います。

コード例
static public $const = array() ;//クラス定数を定義
	
	public function __construct()
	{

//サブクエリー(テキストを抽出)
	$args = array(
		'post_type' => 'post',
		'tax_query' => array(
		'relation' => 'AND',
			array(
				'taxonomy' => 'region',			
				'field' => 'term_id',
				'terms' => '9790',//中央区
			),
			array(
				'taxonomy' => 'genre',				
				'field' => 'term_id',
				'terms' => '10274',//商店街
			)
		)
	);
	$the_query = new WP_Query($args) ;
//サブループ
	if($the_query->have_posts()){
		While($the_query->have_posts()){
			$the_query->the_post();
				$count++;
//表示(View)部分
	//クラス定数へ緯度経度情報を書き込み
			$array = code40307::$const ;//クラス定数を読み込み
			$num = $count-1 ;
			$id = get_the_ID() ;
			$title = get_post($id)->post_title ;
			$lat = get_post_meta($id, 'latitude', true);//緯度
			$lon = get_post_meta($id, 'longitude', true);//経度
			$array[] = [$id, $lat, $lon, $num, $title];//多次元配列に要素を追加
			code40307::$const = $array ;//クラス定数へ書き込み
	//HTML記述
			?><a class="<?php
				echo $par2->id ;
				echo ' ' ;
				echo 'tag' ;
			?>"href="<?php
				echo get_permalink();
			?>" onmouseover="<?php
				echo 'popupOn2('.$num.');' ;
			?>"><?php
				the_title() ;
				echo "<br>\n" ;
			?></a><?php
					
		}//endwhile
	}//endif

//事物表示
	//クラス定数の呼び出し
	$map_marker_json = json_encode(code40307::$const);
	//地図エリアの設定
	?>
	<body>
    	<div id="map_2" style="height: 400px;"></div>
	</body>

<script>
//背景地図
	var osm = new L.tileLayer
	('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    	maxZoom: 19,
    	attribution: "Map data © <a href='https://www.openstreetmap.org/copyright' target='_blank'>OpenStreetMap</a> contributors"
	});	
	var map_2 = L.map('map_2', {
		layers: [osm],	
		center: [35.664897,139.776624],
		zoom: 15,
    	zoomControl: true
		});

//マーカー表示	
	var array = JSON.parse('<?php echo $map_marker_json; ?>');
	var addmarker2=[];
	var i = 0
	//ループ
	array.forEach(function(id){
    	addmarker2[i]=L.marker([id[1],id[2]]).addTo(map_2).bindPopup(id[4]);
		i++;
	});//endeach

//ポップアップを開く関数
	function popupOn2(id){
		addmarker2[id].openPopup();
	}	
	
</script>
上記コードの実行結果
築地(西仲通り商店街)明治時代の埋め立て工事により出来上がった町。

事例3:MVCモデルにLeafletを組み込む

事例の概要

  • 事例2で示したコードは、①WordPressのサブクエリー・サブループによるテキスト表示、②HTMLによる背景地図の表示、③Leaflet.jsによる事物の描画を順に行うものでした。
  • 本事例では、コードの再利用性を高めることを目的に、①②③をそれぞれ別のClassに記述します。

コード例

//外部からLeafletを操作する(オブジエクト指向MVCモデル)
class code40309
{

static public $const = array() ;//クラス定数を定義
	
	public function __construct()
	{
		$args = array(
			'model' => '37694',
			'view' => '40309',
			'pattern_m' => 'Sour',
			'entity_from' => 'Term',
			'entity_to' => 'Post',
			'post_type' => 'post',
			'orand' => 'and',			
			'tax' => array('region','genre'),//地域、ジャンル
			'field_value' => array('9809','10274'),	//台東区、商店街		
		);
		$user = new Controller37694($args) ;
	
		$user = new View40309Map() ;
		
		$user = new View40309Mapmarker() ;
			
	}
}

//表示を行うクラス(View)
class View40309
{
	public function __construct($par)
	{
		$array2 = code40309::$const ;//クラス定数を読み込み
		$num = $par->num ;
		$num = $num-1 ;
		$id = get_the_ID() ;
		$title = get_post($id)->post_title ;
		$lat = get_post_meta($id, 'latitude', true);//緯度
		$lon = get_post_meta($id, 'longitude', true);//経度
		$array2[] = [$id, $lat, $lon, $num, $title];//多次元配列に要素を追加
		code40309::$const = $array2 ;//クラス定数へ書き込み
				
		?><a class="<?php
			echo $par2->id ;
			echo ' ' ;
			echo 'tag' ;
		?>"href="<?php
			echo get_permalink();
		?>" onmouseover="<?php
			echo 'popupOn('.$num.');' ;
		?>"><?php	
			the_title() ;
			echo "<br>\n" ;
		?></a><?php

	}//endfunction
}//endclass


//背景地図を表示するクラス
class View40309Map
{
	public function __construct()
	{
?>
	<body>
    	<div id="map_3" style="height: 400px;"></div>
	</body>

<script>
	var osm = new L.tileLayer
	('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    	maxZoom: 19,
    	attribution: "Map data © <a href='https://www.openstreetmap.org/copyright' target='_blank'>OpenStreetMap</a> contributors"
	});
	
	var map_3 = L.map('map_3', {
		//layers: [osm,old1],
		layers: [osm],	
		center: [35.712364,139.787258],
		zoom: 14,
    	zoomControl: true
		});
</script>

<?php
	}//endfunction
}//endclass

//マーカーを表示するクラス
class View40309Mapmarker
{
	public function __construct()
	{
		$map_marker_json2 = json_encode(code40309::$const);
		?>
<script>
		var array = JSON.parse('<?php echo $map_marker_json2; ?>');
		var addmarker=[];
		var i = 0
		array.forEach(function(id){
    		addmarker[i]=L.marker([id[1],id[2]]).addTo(map_3).bindPopup(id[4]);
			i++;
		});//endeach

  //ポップアップを開く関数
  function popupOn(id){
    addmarker[id].openPopup();
  }

</script>
<?php
	}//endfunction
}//endclass

上記コードの実行結果

浅草橋(おかず横丁)昔ながらの商店街。重厚な看板建築。
上野(アメ横センター地下食品街)日本の中の異国。
浅草(浅草地下街)700円の理髪店。昭和の匂いの残る地下街。
入谷~吉原(せんわ通り)美しい柳並木。水道尻。
入谷~吉原(金美館通り)映画館の名前の通りです。

ER図活用によるWebサイトの全体デザイン

ER図

WordPressの投稿タイプやタクソノミーを理解しようとするとき、ER図を書いてみると、視覚的に理解しやすくなります。

データの集合をエンティティと呼びます。下図は、3つのエンティティ(ブログ投稿、市区町村、ジャンル)をデータの実例付きで図示したものです。
 ER図では、主キーと外部キーを記述します。主キーは、図056の最左端のデータ項目で、エンティティのレコードを識別します。表の右端にある「市区町村ID」「ジャンルID」は、それ自身が別のエンティティの主キーとなり得るデータ項目で、外部キーと呼ばれます。 一つのエンティティに主キーは必ず一つですが、外部キーは複数持つことができます。図では、ブログ投稿は二つの外部キーを持つことによって、「ジャンル」と「市区町村」2つのエンティティを関連を持っています。
 また、「市区町村」の事例は、外部キーが自身の主キーと結びつく「親子関係」のエンティティの事例です。

ブログ投稿と市区町村の関係は、1:N

・1つのブログ投稿に対し1つの市区町村が関連。
・その市区町村は別のブログ投稿とも関連。

ブログ投稿とジャンルの関係は、N:N

・ジャンルは、1つのブログ投稿に対し複数設定可能。
(例)
西仲通り商店街は、「商店街」と「路地」に関連

市区町村は親子ループ(1:N)を持つ

・1つの親は1つまたは複数の子を持つ。
・子に対し、親は1つ。
・同一エンティティの中で主キーと外部キーが結びつく(親子関係)。

主キーと外部キー

上記のER図の主キーと外部キーのみを表記すると下図のようになります。主キーと外部キーに注目すると、下記4パターンに集約されます。
ⓐDestinationパターン
ⓑSourceパターン(MetaQuery、TaxQuery)
ⓒAncestorsパターン(現世代→先祖)
ⓓDescendantsパターン(現世代→子孫)

WEBサイトの要件をER図に書き表す

Webサイトを開発する前に全体のデザイン(設計)をすることが必要です。まず、エンティティを抽出し、それらの関連づけを行うための主キー、外部キーはを決めることが重要です。

下図は当サイトの場合のER図の事例です。WordPressは投稿タイプとタクソノミーの2種類がありますので、どちらにするかも最初にするかを決めておく必要があります。

WordPressの外部キー

エンティティ同士の関連には、
 ❶投稿タイプとタクソノミーの関連づけ
 ❷投稿タイプのカスタムフィールドによる関連づけ
 ❸parentフィールドによる親子関係の関連づけ
の3種類があります。

参考文献

参考記事

オブジェクト指向によるWordPressへのMVCモデル適用

WordPressはイベント駆動型モデルであると言われています。これは、URLを指定するだけで自動的にデータを取得(メインクエリー)し、自動的にテンプレートファイルを選択して画面表示(メインループ)するものです。

しかし、カスタム投稿タイプやカスタムタクソノミーを使ったWebアプリケーション開発に重きを置く場合は、サブクエリーを多用する場面が増えてきます。

WordPressには、サブクエリーを効率よく開発するためのモデルがありません。

今回は、サブクエリーを効率よく開発するために、MVCモデルを適用することについて解説します。

MVCモデルは、Modelクラス、Viewクラスにコードを集約し、オブジェックト指向の継承やオーバーライドを使って、類似のコードを抽象化することによって、コーディングの作業を軽減することができます。

次にオブジェクト指向でないコード(従来の書き方)とMVCモデルを使ったオブジェクト指向のコードを比較してみることにします。

オブジェクト指向でないコード

//サブクエリー
	 $args = array(		
 //条件の記述
	 );
 //WP_Query
	 $the_query = new WP_Query($args) ;

//サブループ
	 if($the_query->have_posts()){
	   While($the_query->have_posts()){
		   $the_query->the_post();
		     //表示の記述
		     the_title() ;
	       echo "<br>\n" ;	
	   }
	 }//endif

オブジェクト指向のコード(MVCモデル)

class Controller
{
 public function __construct($var){
	   $par =(object)$var;
	   $user = new Model($args);
   または
   $user = new ViewPost() ;
   $user->format();
 }
}

class Model
{
	public function __construct($var)
	{
	
//サブクエリー
		$args = array(		
  //条件の記述
		);
  //WP_Query
		$the_query = new WP_Query($args) ;

//サブループ
		if($the_query->have_posts()){
			While($the_query->have_posts()){
				$the_query->the_post();
					//Viewクラスの呼び出し
					$user = new ViewPost() ;
                                 $user->format();
			}
		}//endif
	}//endfunction
}//endclass

class View
{
public function __format()	

	}//endfunction
}//endclass

class ViewPost extends View
{
public function __format()
			//表示
			the_title() ;
			echo "<br>\n" ;		
	}//endfunction
}//endclass
//呼び出す側 
$args = arry(
//条件の記述
);
$user  = new Controller($args);

サブクエリー(WP_Query)とサブループは、書き方のパータンがたくさんあり、すべてのパターンを覚えるのは大変なことです。そのため、書くたびにコードディングミスが起こり、完成するまでに時間がかかります。当然のことながら、これをメンテする作業も大変です。

これに対し、オブジェクト指向で書かれたコードは、呼び出す側は、フィルタリング条件を記述してクラスを呼び出すだけで、サブクエリー~サブループ~表示までの処理が完了します。
 もちろん、呼び出される側のクラスとして、Controllerクラス、Modelクラス、Viewクラスがあり、これらのコードを合わせると、オブジェクト指向を使った場合の方がコードの量は格段に増えます。しかし、これらのクラスは、再利用することを前提に作成していますので、次回からは、呼び出す側の記述のみで済みます。
 また、クラスには、スーパークラス(親クラス)の機能を継承して、差分の部分のみをサブクラス(子クラス)に記述することができ、メンテの効率が向上します。

参考文献

参考記事

WordPressの基本構造の概念図

WordPressの基本の理解で最も重要なことは、構造の理解です。理解するためには、図で示すことが最も近道です。
WordPressは、クエリーとループから成り立っています。

クエリー:データの検索
ループ:データの表示

WordPressの入門時に一番初めに理解すべきことは、メインクエリーとメインループですが、メインクエリーは「WordPressコア」と呼ばれる基本部分に包含されていて、通常はカスタマイズできないということです。(メインクエリーをカスタマイズするには、「フック」という特別なカスタマイズ方法を用います。)

WordPressの基本構造の概念図

WordPressのカスタマイズを理解の第一歩は、テーマの中にあるメインループを見つけ出し、ループの中の記述を自分の好みに合うようにカスタマイズし、実感をつかむことです。

<?php 
if ( have_posts() ) {
	while ( have_posts() ) {
		the_post(); 
		//
		// この部分が記述(カスタマイズ)部分
		//
	} // end while
} // end if
?>

上記のコードのif ( have_posts() )から} // end ifまでがメインループの記述で、その内側の部分がカスタマイズ部分で、ここに、たとえば、the_title();と書けば、投稿のタイトルが表示され、the_content();と書けば、投稿の本文が表示されるわけです。

<?php 
if ( have_posts() ) {
	while ( have_posts() ) {
		the_post(); 
		//記述(カスタマイズ)部分
          the_title();
          the_content();
		//
	} // end while
} // end if
?>

もう一つ重要なポイントは、このメインループが実行される手前の段階で、「WordPressコア」の中のメインクエリーが、既に実行を完了しており、その結果がオブジェクトと呼ばれるデータの塊に保持されているということです。この塊から具体的なデータを抜き出す命令が、the_title();the_content();です。このとき、データは複数件あるので、これをメインループで回して表示しています。

WordPressのカスタマイズで頻繁に出てくるサブループについては、上記の概念図に併記すると理解が深まります。
メインクエリーが「WordPressコア」の中にあって、自動的に実行されるものであるのに対し、サブクエリーは、自分でコードを書く(カスタマイズする)ことが必要ですが、行っている処理は、メインクエリーと同じです。(両方ともWP_Queryが実行されている同じ処理。)

サブクエリーの結果は、オブジェクトに出力され、それを表示するのがサブループです。メインループとサブループの書き方は、ほぼ同じです。

上記の概念図では、左から右へ「クエリー」「ループ」「表示」と情報が転送され、全体としては、上から下へ「メイン」「サブ」と処理が進んでいくことを図示しています。

参考文献

参考記事

WP_Queryのカスタマイズ事例(4)万能型サブクエリー

これまで、WP_Queryのカスタマイズ事例※1※2※3を示してきましたが、今回は、このうちのDestinationパターン※1とSourceパターン※2の事例を統合した万能型サブクエリーについて解説します。

参考文献

参考記事

※1WP_Queryのカスタマイズ事例(2)Sourceパターン( meta_queryとtax_query)※2WP_Queryのカスタマイズ事例(1)Destinationパターン

コード例

事例1:万能型カスタムWP_Query

呼び出す側

$args = array(
	'model' => '37694',
	'view' => '37694',
	'pattern_m' => 'Sour',
	'entity_from' => 'Term',
	'entity_to' => 'Post',
	'post_type' => 'post',
	'tax' => array('region','genre'),//タクソノミー名:地域、ジャンル
	'field_value' => array('9790','10274'),	//タクソノミーの値:中央区、商店街		
);
$user = new Controller37694($args) ;

Controllerクラス

class Controller37694
{	
	
	public function __construct($args)
	{
//////配列をオブジェクトに変換
		$par =(object)$args;
//////Modelメソッドの呼び出し
			$model_name = 'Model'.$par->model ;	
			$model_obj = new $model_name($par) ;
	}//endfunction
}//endclass

Modelクラス

class Model37694
{
	public function __construct($par)
	{
//参照パターン毎に$argsの値を設定するため、分岐させるための$args_nameの値を設定。

		$args_name = $par->pattern_m.$par->entity_from.$par->entity_to ;
		if ($args_name == 'SourTermPost'){

			$query_name = 'tax_query' ;
		}elseif($args_name == 'SourPostPost'){
			$query_name = 'meta_query' ;		
		}
			$args = array(
				'order' => $par->order,
				'orderby' => $par->orderby,
				'include' => $par->foreign_key,//タクソノミー用DPT
				'hide_empty' => false,//Listのとき要DPT
    			'meta_key' => $par->meta_key,//DPP
				'post_type' => $par->post_type,//DPP
				'post__in' => $par->foreign_key,//DPP
				'posts_per_page' => -1,//全行表示DPP
				$query_name => array(
				'relation'  => $par->orand ,
					array(
						'taxonomy' => $par->tax[0],
						'field' => 'term_id',//STP
						'terms' => $par->field_value[0],//STP
						'key' => $par->field[0],//SPP
						'value' => $par->field_value[0],//SPP
					),
					array(
						'taxonomy' => $par->tax[1],
						'field' => 'term_id',//STP
						'terms' => $par->field_value[1],//STP
						'key' => $par->field[1],//SPP
						'value' => $par->field_value[1],//SPP
					)
				)
			);

		if ($args_name == 'DestPostTerm'){
			$the_query = get_terms($par->tax, $args);			
		}else{
			$the_query = new WP_Query($args) ;
		}

		
////////////////////表示ループ
//Viewクラスのクラス名を設定
	$view_name = 'View' . $par->view;
	$num = 0 ;
		
//表示するエンティティがpostの場合
	if ($par->entity_to == 'Post'){
//while文でのループ処理
		if ( $the_query->have_posts() ) {
			while ( $the_query->have_posts() ) {
				$the_query->the_post();
					$num = $loopcounter++ +1;
					if ($num == '1' && !empty($par->title)){

						echo '<h2>' . $par->title . '</h2>' ;//タイトルを表示
 					}
//カウントアップした番号$numをオブジェクト$parに設定
					$par->num = $num ;
				
//Viewオブジェクトをインスタンス化
					$view_obj = new $view_name($par);				
			}// end while
			wp_reset_postdata();
		}//end if
		
//表示するエンティティがtermの場合
	}elseif ($par->entity_to == 'Term'){
		echo '<h2>' . $par->title . '</h2>' ;

//foreach文でのループ処理
		foreach ($the_query as $term){
		$num = $loopcounter++ +1;
//カウントアップした番号$numと表示するオブジェクト$termをオブジェクト$parに設定
			$par->term = $term ;

//Viewオブジェクトをインスタンス化
			$view_obj = new $view_name($par);
		}//endforeach

	}else{
	}//endif
	}//endfunction

}//endclass

Viewクラス

class View37694
{
	public function __construct($par)
	{
		the_title() ;
		echo "<br>\n" ;	
	}//endfunction
}//endclass
築地(西仲通り商店街)明治時代の埋め立て工事により出来上がった町。

WP_Queryのカスタマイズ事例(3)親子( 先祖・子孫)クエリー。

カスタム投稿タイプの先祖の表示。

前回※1 「投稿のカスタムフィールドに関連付けられた投稿の表示」で、ブログ記事に文献の情報を関連付ける事例を紹介しました。(実際の画面サンプルはこちらです。)

この例では、「第八章 月島の商業」が関連付けられていますが、この上の階層である「第三編 明治以降の月島」と最上位階層である書籍名の「月島発展史」を併せて表示しています。

カスタム投稿タイプ「参考文献」は、親子関係を持った木(ツリー)構造になっていて、最初に関連付けされた「第八章 月島の商業」をキーに、祖先(父母→祖父母)の階層を表示しています。

リスト37639は、カスタム投稿タイプの祖先を表示するコードです。

カスタム投稿タイプの子孫の表示。

カスタム投稿タイプ「参考文献」の全体を一覧表示する場合は、階層のトップのIDを指定し、それをキーに子孫の階層を上から順番に検索して表示します。(実際の画面サンプルはこちらです。)

リスト37639は、投稿の子孫を表示するコードです。WordPressのテンプレートタグ「get posts」を使って子孫を検索しています。 

タクソノミーの祖先と子孫の表示

木(ツリー)構造を持つタクソノミーの全体を表示する事例を紹介します。(実際の画面サンプルはこちらです。)

たとえば「中央区」を選択した場合、祖先に東京都、子孫に月島3丁目があります。これらの表示をクリックするとどちらにでも移動できるようにすると便利です。また、自分が現在どの階層にいるかも解りやすくなります。

リスト36732は、タクソノミーの祖先と子孫の両方を表示する事例です。現世代の「中央区」を指定すると、まずその先祖を表示し、次に子孫を表示します。

参考文献

参考記事

コード例

事例1:カスタム投稿の先祖を表示

呼び出す側

$par2->gen_id = '18661';
$par2->post_type = 'reference' ;
$user = new Model37639() ;
    $user->generation($par2) ;

呼び出される側(クラス)

class Model37639 extends WP_Query
{
	public function generation($par2)
	{
		$ance = array() ;
		$ance = get_ancestors($par2->gen_id, $par2->post_type) ;
		//$cnt = count($ance);
		$ance = array_reverse($ance) ;
		$k = 0 ;
		While ( !empty($ance[$k])) {
			$par2->id = $ance[$k] ;
			$par2->k = $k  ;
			$View_obj = new View37639a($par2) ;
			$k = $k +1 ;
		}//endwhile
	}//endfunction

}//endclass

class View37639a
{
	public function __construct($par2)
	{
		$postslist = get_post($par2->id) ;
 		setup_postdata($postslist);
		echo $postslist->post_title."<br>\n" ;
		
	}//endfunction
}//endclass

Warning: Creating default object from empty value in /home/xs663544/kokontouzai.jp/public_html/wp-content/plugins/wp-OOP/wp-OOP-CodeSample.php on line 508

ID: 18661
先祖
k=0 18444月島発展史
k=1 18665第三編 明治以後の月島
現世代
k=2 18661第八章 月島の商業

事例2:カスタム投稿の子孫を表示

呼び出す側

$par2->gen_id = '18444';
$par2->post_type = 'reference' ;
echo "<br>\n".'ID: '.$par2->gen_id."<br>\n" ;
$user = new Model37642() ;
    $user->generation($par2) ;

呼び出される側(クラス)

class Model37642 extends WP_Query
{
	public function __construct()
	{
//コンストラクタは、なぜ今回使わないのか。
	}//endfunction
	
	public function generation($par2)
	{

//現世代を表示
		echo '現世代'."<br>\n" ;
		$par2->id = $par2->gen_id ;
		$par2->k = 0 ;
		$View_obj = new View37642a($par2) ;
		
//子孫を表示
		echo '子孫'."<br>\n" ;
		$this->children($par2) ;		
	}
	
	public function children($par2)
	{
//抽出処理
		$k = $par2->k ;	
		$args = array(
			'post_type' => $par2->post_type ,			
			'post_parent' => $par2->id ,
			'orderby' => 'menu_order',
			'order'   => 'ASC',
		);
		$the_query = get_posts($args) ;
		if(empty($the_query)){
			return ;
		}
//ループ処理
		$k = $k +1 ;
		foreach($the_query as $query){
			$par2->id = $query->ID ;
			$par2->k = $k ;			
			$View_obj = new View37642a($par2) ;
			$this->children($par2) ;//再帰処理。
		}
		
	}//endfunction
}//endclass

class View37642a
{
	public function __construct($par2)
	{
		$postslist = get_post($par2->id) ;
 		setup_postdata($postslist);
		echo 'k='.$par2->k.' '.$par2->id ;
		echo $postslist->post_title."<br>\n" ;
		
	}//endfunction
}//endclass

Warning: Creating default object from empty value in /home/xs663544/kokontouzai.jp/public_html/wp-content/plugins/wp-OOP/wp-OOP-CodeSample.php on line 433

ID: 18444
現世代
k=0 18444月島発展史
子孫
k=1 18669第二編 江戶時代の月島
k=2 18675第一章 石川島佃島の塡築
k=1 18665第三編 明治以後の月島
k=2 18445第二章 月島、新佃島の填築
k=2 18661第八章 月島の商業

事例3:タクソノミーの先祖と子孫を同時表示

呼び出す側

$par2->gen_id = '9790';
$par2->entity_name = 'region' ;
echo "<br>\n".'ID: '.$par2->gen_id."<br>\n" ;
$user = new Model36732() ;
    $user->generation($par2) ;

呼び出される側(クラス)

class Model36732//計算するクラス。
{
	public function __construct()
	{
//コンストラクタは、なぜ今回使わないのか。
	}//endfunction
	
	public function generation($par2)
	{
		$ance = array() ;
		$ance = get_ancestors($par2->gen_id, $par2->entity_name) ;
		//$cnt = count($ance);
		$ance = array_reverse($ance) ;

//////先祖が存在しない場合、$anceは中身は空なので、次の処理へ進む。
//先祖を表示。
echo '先祖'."<br>\n" ;
		$k = 0 ;
		While ( !empty($ance[$k])) {
			$par2->id = $ance[$k] ;
			$par2->k = $k ;
			$View_obj = new View36732a($par2) ;
			$k = $k +1 ;
		}//endwhile

//現世代を表示
echo '現世代'."<br>\n" ;
		$par2->id = $par2->gen_id ;
		$par2->k = $k ;
		$View_obj = new View36732a($par2) ;
		
//子孫を表示
echo '子孫'."<br>\n" ;
		$this->children($par2) ;		
	}
	
	public function children($par2)
	{
//抽出処理
		$k = $par2->k ;	
		$args = array(
			'parent' => $par2->id ,	
		);
		$the_query = get_terms($par2->entity_name, $args) ;
		if(empty($the_query)){	
			return ;
		}
//ループ処理
		$k = $k +1 ;
		foreach($the_query as $term){
			$par2->id = $term->term_id ;
			$par2->term = $term ;//$par2に追加。
			$par2->k = $k ;//$par2に追加。
			$View_obj = new View36732b($par2) ;
			$this->children($par2) ;//再帰処理。
		}
		
	}//endfunction
}//endclass

class View36732a//表示するクラス。
{
	public function __construct($par2)
	{
		$term = get_term($par2->id , $par2->entity_name ) ;
		echo 'k='.$par2->k.' '.$par2->id ;
		echo $term->name."<br>\n" ;
	}//endfunction

}//endclass

class View36732b//表示するクラス。
{
	public function __construct($par2)
	{
		echo 'k='.$par2->k.' '.$par2->id ;
		echo $par2->term->name."<br>\n" ;
	}//endfunction

}//endclass

Warning: Creating default object from empty value in /home/xs663544/kokontouzai.jp/public_html/wp-content/plugins/wp-OOP/wp-OOP-CodeSample.php on line 564

ID: 9790
先祖
k=0 7079全国
k=1 2740東京都
現世代
k=2 9790中央区
子孫
k=3 12370日本橋室町3丁目
k=3 12404日本橋室町1丁目
k=3 12405日本橋富沢町
k=3 12406日本橋大伝馬町
k=3 10164日本橋中洲
k=3 10160日本橋人形町二丁目
k=3 2751日本橋人形町一丁目
k=3 10163日本橋人形町三丁目
k=3 10161日本橋箱崎町
k=3 10162日本橋小網町
k=3 9907日本橋本町一丁目
k=3 10076日本橋本町四丁目
k=3 2748八丁堀三丁目
k=3 9903八重洲一丁目
k=3 9908八重洲二丁目
k=3 2750京橋三丁目
k=3 7442八丁堀二丁目
k=3 2747銀座二丁目
k=3 10061銀座三丁目
k=3 10062銀座四丁目
k=3 10063銀座五丁目
k=3 10064銀座六丁目
k=3 10059銀座七丁目
k=3 10058銀座八丁目
k=3 2749新富1丁目
k=3 9788築地2丁目
k=3 10508築地7丁目
k=3 2752新川1丁目
k=3 10509新川2丁目
k=3 12355日本橋室町2丁目
k=3 9880佃1丁目
k=3 9789月島3丁目

WP_Queryのカスタマイズ事例(2)Sourceパターン( meta_queryとtax_query)

リスト37167は、meta_queryの事例。
リスト37179は、tax_queryの事例です。

参考文献

参考記事

この記事を参照している記事

WP_Queryのカスタマイズ事例(4)万能型サブクエリー
WP_Queryのカスタマイズ事例(1)Destinationパターン

コード例

事例1:Sourceパターン(Post→Post) meta_query

class code37167
{
	public function __construct()
	{
		$args = array(
			'model' => '37167',
			'view' => '37167',
			'post_type' => 'post',
			'field' => array('ref'),//参考文献
			'field_value' => array('18661'),//第八章 月島の商業
		);
		$user = new Controller37167($args) ;
	}//endfunction
}//endclass

class Controller37167
{	
	
	public function __construct($args)
	{
//////配列をオブジェクトに変換
		$par =(object)$args;
//////Modelメソッドの呼び出し
			$model_name = 'Model'.$par->model ;	
			$model_obj = new $model_name($par) ;
	}//endfunction
}//endclass

class Model37167
{
	public function __construct($par)
	{
		$args = array(		
			'post_type' => $par->post_type,
			'meta_query' => array(
			'relation' => 'OR',
				array(
					'key' => $par->field[0],
					'value' => $par->field_value[0],
				)
			)
		);
		$the_query = new WP_Query($args) ;

//ループ~表示処理(Viewクラス)の呼び出し。
		if($the_query->have_posts()){
			While($the_query->have_posts()){
				$the_query->the_post();
					$view_name = 'View'.$par->view ;
					$view_obj = new $view_name($par) ;
			}
		}//endif
	}//endfunction

}//endclass

class View37167
{
	public function __construct($par)
	{
		the_title() ;
		echo "<br>\n" ;
	}//endfunction
}//endclass
築地(和風スナック)沢の鶴の看板。月島三丁目。
築地(西仲通り商店街)明治時代の埋め立て工事により出来上がった町。

事例2:Sourceパターン(Term→Post) tax_query

class code37179
{
	public function __construct()
	{
		$args = array(
			'model' => '37179',
			'view' => '37179',
			'tax' => array('region','genre'),//タクソノミー名:地域、ジャンル
			'field_value' => array('9790','10274'),	//タクソノミーの値:中央区、商店街		
			'post_type' => 'post',//投稿タイプ:ブログ記事
		);
		$user = new Controller37179($args) ;
	}//endfunction
}//endclass

class Controller37179
{	
	public function __construct($args)
	{
//////配列をオブジェクトに変換
		$par =(object)$args;
//////Modelクラスの呼び出し
		$model_name = 'Model'.$par->model ;	
		$model_obj = new $model_name($par) ;
	}//endfunction
}//endclass

class Model37179//投稿を表示
{
	public function __construct($par)
	{

		$args = array(		
			'post_type' => $par->post_type,
			'tax_query' => array(
			'relation' => 'OR',
				array(
					'taxonomy' => $par->tax[0],				
					'field' => 'term_id',
					'terms' => $par->field_value[0],
				),
				array(
					'taxonomy' => $par->tax[1],				
					'field' => 'term_id',
					'terms' => $par->field_value[1],
				)
			)
		);
		$the_query = new WP_Query($args) ;

//ループ~表示処理(Viewクラス)の呼び出し。
		if($the_query->have_posts()){
			While($the_query->have_posts()){
				$the_query->the_post();
					$view_name = 'View'.$par->view ;
					$view_obj = new $view_name($par) ;
			}
		}//endif
	}//endfunction
}//endclass


class View37179
{
	public function __construct($par)
	{
		the_title() ;
		echo "<br>\n" ;
	}//endfunction
}//endclass
人形町(日本橋大伝馬町の路地)江戸の下水道が現代に引き継がれています。
人形町(問屋橋跡北側の路地)日本橋富沢町。浜町川跡の商店街。
人形町(真砂座の碑)明治39年、夏目漱石「猫」上演。
日本橋(てんぷら天松)昭和11年創業。
日本橋(清水理美容院)理容室と美容院。
日本橋(十軒店跡の碑)江戸時代の仮設専門店街。人形市。
日本橋(浮世小路)浮世ショウジ。落語「百川」の舞台。
茂原(榎町商店街)カラフルな看板建築建物群。
浅草橋(おかず横丁)昔ながらの商店街。重厚な看板建築。
川崎南町(名画通り)路地にまっすぐに伸びる側溝。
日立(日立銀座通りの写真)駅構内の写真展。
長崎丸山(銅座市場跡)現在は取り壊されています。
板橋(坂下マーケット)ゲートだけが残っています。
板橋(トンネルマーケット)立喰いそば屋脇のトンネル。
成増(成増マーケット)すずらん通りの昭和の空間。
町田(仲見世商店街)西のアメ横とよばれています。
船橋(仲通り商店会)Y字路の商店街。
上野(アメ横センター地下食品街)日本の中の異国。
銀座(名店「三州屋銀座店」)1968年創業の老舗割烹。
銀座(金春小路)かつては置屋や待合が並ぶ花街。
銀座(路地の中の自動ドア)通り抜けできます。
銀座(豊岩稲荷)130年以上前の銀座煉瓦街時代の名残。
銀座(三愛ビル)1963年開業の銀座のランドマーク。
銀座(出世地蔵尊)昭和27年のキャバレー「美松」の火事で移転。
銀座(キャバレー美松跡地)現在の三越百貨店新館がある場所。
銀座(三原小路隣の袋小路)2階建ての長屋形式の店舗。
日本橋(老舗カレー店)開業50周年
日本橋(鳥萬)戦前の建物。4階建てのように見える3階建て。
日本橋(大勝軒)昭和32年の建築。緑のタイル。
日本橋(老舗割烹「嶋村」)嘉永3年(1850年)創業。金ぷら
日本橋(アダルトグッズ店)TENGAあります。
日本橋(理容室跡)木々が生い茂る中のサインポール。
日本橋(雀荘)オフィス街の中に10軒近く。
日本橋(花街跡)横丁や路地に遊興の歴史。
小岩(駅裏の商店街)小さな小島のような一画。
王子(いなり通り)かつて花街があった場所の商店街。
人形町(小春軒)山県有朋のお抱え料理人が創業。
人形町(金刀比羅宮)芳町芸妓組合、新田新作が寄進。
人形町(浜田家)芳町唯一の料亭
人形町(思案橋)吉原へ行こうか、芝居に行こうか。
人形町(桃乳舎)芸術的な看板建築。桃のマーク。
人形町(高尾稲荷社)高尾大夫の霊を祭っている稲荷神社。
人形町(キラク)1951年開業。年季の入った看板と暖簾。
人形町(歯科医院のゴミ箱)特注の備え付けタイプ。
人形町(㐂寿司)かつての花街の記憶が残る建物。
人形町(よし梅本店)戦火を免れて残った店。
大塚(三業通り)看板がリニューアル。芸者さんのモニュメント。
築地(日の出湯)佃小橋から見える煙突付きマンション。
築地(和風スナック)沢の鶴の看板。月島三丁目。
築地(西仲通り商店街)明治時代の埋め立て工事により出来上がった町。
築地(旅館大宗)純和風。周囲は、高層ビルが建ちち並びます。
築地(看板建築)3階建て。正面から見ると2階建て。
築地(築地場外市場)寺院の建物と市場の建物がつながっています。
築地(天婦ら「おかめ」)昭和初期からある料理屋です。
亀戸(亀七通り商店街)大看板。両側にゲート。
福富町(長者町八丁目共同ビル)マッサージ店の看板。
福富町(福仲ビル)商店街共同建築。2階と3階は居住部分。
天王町(横浜洪福寺松原商店街)朝獲れの鯖。
磯子(浜マーケット)戦後の闇市が発展してできました。
磯子(丸山市場)美空ひばりの生家の近く。
新川(於岩稲荷田宮神社)花柳界や歌舞伎関係者が参詣。
新川(新川大神宮)酒問屋が信仰。待合と芸妓屋が集中していた場所。
新川(料理屋「増田や」跡)現在は居酒屋チェーンの店舗。
丸の内(長者町繊維街)看板が連なります。
荒木町(車力門通り)荒木町三業地の入口。
藤岡(割烹料理屋「花月」)仲町の通り。料理屋が建ち並ぶ一画。
相模原(タンクトップ)西門商店街。日用品の店舗。
武蔵小杉(センターロード小杉)超ミニスカスッチー。
門前仲町(清住庭園東側共同ビル)3階建ての長屋建築。
新富町(正金アパート)昭和の初期からあるアパート。
新富町(路地)昔ながらの路地。飲食店の看板。
新富町(花街跡)新富座の開業とともに芸妓、置屋が増加。
新富町(新島原遊廓跡地)外国人のための遊廓。
巣鴨(地蔵通り商店街)巣鴨名物「お地蔵様の赤パン」。
麻布(元麻布の長屋)高層マンションとのアンバランスな対比。
吉祥寺(のれん小路)かつては小さな飲み屋が連なっていた横丁。
吉祥寺(ハモニカ横丁)終戦直後の闇市の姿。
日暮里(繊維問屋街)コスプレ人気で活況を呈しています。
高山(末広二番街)花岡遊廓跡地の東側。
浅草(浅草地下街)700円の理髪店。昭和の匂いの残る地下街。
長崎丸山(銅座市場)通り抜けられません。
戸部(岩亀横丁)「がんき」の屋号を持つ寿司屋、サウナ。
南千住(三ノ輪商店街)荒川区随一の大商店街。
日本橋(理髪店)昭和5年築の看板建築。モダンなデザイン。
日本橋(麻雀クラブ富士)昭和25年頃は「パチンコ富士」でした。
日本橋(八重洲の飲み屋街)八重洲のあの日。
日本橋(ビデオボックス)都会の真ん中に密集。
京橋(雀荘)幻想的な水色の建物。モダンな玄関の部分。
京橋(レトロな商店街)戦前の看板建築がひっそりと残る一画。
京橋(京橋柳町遊里跡地)吉原の元祖。関が原の合戦後。
京橋(江戸歌舞伎発祥の地)江戸三座。猿若中村座。
白山(仲通り商店街)かつての銘酒屋があったあたり。
仙台(壱弐参横丁)戦後の公設中央市場が原形。
根津(牛乳店と貸本屋)ホモちゃんマーク。牛乳の看板。
赤羽(明店街)「通りぬけ」の看板。ミルクホール。
銀座(8丁目並木通り近く)銀座の柳にピンクビラ。
銀座(シネパトス)地下街にあるアダルトショップ
銀座(金春湯)文久3年開業の歴史ある銭湯です。
銀座(白いバラ)アルサロブ-ムを今に伝える店です。
銀座(東京温泉跡地)元祖トルコ風呂。延べ1,600坪の建物。

WP_Queryのカスタマイズ事例(1)Destinationパターン

今回は、投稿データに関連付けられたタクソノミーや別の投稿を表示する方法について紹介します。

WP_Queryは、あるデータの集合(これをエンティティと呼びます)の外部キーから別のエンティティの主キーを検索しデータ群(オブジェクト)取得する仕組み(クラス)です。
 WordPressの場合のエンティティは、「投稿タイプ」「カスタム投稿」「カテゴリー」「ターム」「カスタムタクソノミー」などのデータの集合です。これらのエンティティ同士は、主キーと外部キーで関連付けられます。

下図は、ブログ投稿の外部キーにカスタムタクソノミー「ジャンル」が関連づけられている場合を図示したものです。

Destinationパターン

リスト37209は、投稿のカスタムフィールドに関連付けられた投稿の表示の事例です。
ブログ記事のような投稿データに、別の投稿データを関連づけて表示したい場合があります。

リスト37211は、投稿に関連付けられたタクソノミーの表示の事例です。
ブログ記事のような投稿データには、タクソノミー(カテゴリー、タグ)を関連づけて記事の分類分けをしますが、このとき、ブログ記事のタイトルの上部や本文の末尾などにタクソノミーを表示したい場合があります。

ブログ投稿(Post)とジャンル(Term)のER図

参考文献

参考記事

※1WP_Queryのカスタマイズ事例(2)Sourceパターン( meta_queryとtax_query)

この記事を参照している記事

WP_Queryのカスタマイズ事例(4)万能型サブクエリー

コード例

事例1:Destinationパターン(Post→Post)

class code37209
{
	public function __construct()
	{	
		$user = new Model37209() ;
	}//endfunction
}//endclass

class Model37209 extends WP_Query
{
	public function __construct()
	{
		$args = array(		
			'post_type' => 'post',
			'post__in' => array('18348'),//IDを配列で指定。
		);
		$the_query = new WP_Query($args) ;		

//ループ~表示処理(Viewクラス)の呼び出し。
		if($the_query->have_posts()){
			While($the_query->have_posts()){
				$the_query->the_post();
					$view_obj = new View37209($par) ;
			}
		}//endif
	}//endfunction

}//endclass

class View37209
{
	public function __construct($par)//$parはいらない。
	{
		the_title() ;
		echo "<br>\n" ;
		
//次の処理の準備
//投稿に関連付けられているカスタムフィールドのIDを取得する。
	$myposts = get_post_meta(get_the_ID(), 'ref', false) ;//'ref'を指定。
	if (!empty($myposts)){
		$par->foreign_key = $myposts ;
		$user = new Model37209a($par) ;
	}else{
		return ;
	}
		
	}//endfunction
}//endclass

class Model37209a
{
	public function __construct($par)
	{	
		$args1 = array(
			'post__in' => $par->foreign_key,//配列をそのまま記述
			'post_type' => 'reference',//DPP
		);
		$the_query = new WP_Query($args1) ;//WP_Query	

//ループ~表示処理(Viewクラス)の呼び出し。
		if($the_query->have_posts()){
			While($the_query->have_posts()){
				$the_query->the_post();
					$view_obj = new View37209a($par) ;
			}
		}//endif
	}//endfunction

}//endclass

class View37209a
{
	public function __construct($par)
	{

		the_title() ;
		echo "<br>\n" ;
		
	}//endfunction
}//endclass
築地(西仲通り商店街)明治時代の埋め立て工事により出来上がった町。

Warning: Creating default object from empty value in /home/xs663544/kokontouzai.jp/public_html/wp-content/plugins/wp-OOP/wp-OOP-CodeSample.php on line 781
第八章 月島の商業
月島再発見学

事例2:Destinationパターン(Post→Term)

class code37211
{
	public function __construct()
	{	
		$user = new Model37211() ;
	}//endfunction
}//endclass

class Model37211
{
	public function __construct()
	{
		$args = array(		
			'post_type' => 'post',
			'post__in' => array('18348'),//IDを配列で指定。
		);
		$the_query = new WP_Query($args) ;		

//ループ~表示処理(Viewクラス)の呼び出し。
		if($the_query->have_posts()){
			While($the_query->have_posts()){
				$the_query->the_post();
					$view_obj = new View37211($par) ;
			}
		}//endif
	}//endfunction

}//endclass

class View37211
{
	public function __construct($par)
	{
		the_title() ;
		echo "<br>\n" ;

//次の処理の準備
//投稿に関連付けられているタクソノミーのIDを取得する。
			$myterms = wp_get_object_terms(get_the_ID(), 'region');
			if (!empty($myterms)){
				$foreign_key = array() ;
				foreach ($myterms as $post){
					array_push( $foreign_key , $post->term_id);
				}
			}else{
				return ;
			}//endif		
		
		$par->foreign_key = $foreign_key ;
		$user = new Model37211a($par) ;
		
	}//endfunction
}//endclass

class Model37211a
{
	public function __construct($par)
	{

		$args = array(		
			'include' => $par->foreign_key,
		);
		$the_query = get_terms('region', $args) ;		

//ループ~表示処理(Viewクラス)の呼び出し。
		foreach ($the_query as $term){
			$par->term = $term ;
				$view_obj = new View37211a($par) ;			
		}
	}//endfunction

}//endclass

class View37211a
{
	public function __construct($par)
	{
		echo $par->term->name."<br>\n" ;
		
	}//endfunction
}//endclass
築地(西仲通り商店街)明治時代の埋め立て工事により出来上がった町。

Warning: Creating default object from empty value in /home/xs663544/kokontouzai.jp/public_html/wp-content/plugins/wp-OOP/wp-OOP-CodeSample.php on line 703
月島3丁目

WP_Queryのカスタマイズ

サブクラスにおいてWP_Queryを使うことのメリットは、拡張(継承)してカスタムクラスを作れることです。Rakhitha Nimesh Ratnayake(ラーキサ・ニーメシュ・ラーネヤク)は、その著書「WordPressによるWebアプリケーション開発」の中で、WP_Queryクラスの継承の用例を示しています。*1

リスト37188は、ラーネヤク氏が示した用例を本書のテーマに即してアレンジしたものです。
通常、WP_Queryを使うときは、次のように配列にすべてのフィルタリング条件を記述しなければなりませんが、リスト37188では、Modelクラスの中にこの記述を書いているので、呼び出す側は、1行のコードのみで済みます。

たしかに、同じフィルタリング条件を何度も繰り返し使う場合はこの方法が有効であり、クラスを継承すれば、少し異なる条件の場合も含めて抽象化できるかもしれません。

しかし、あらゆるパターンのサブクエリー(投稿の場合、タームの場合、親子の場合)と表示をすべて網羅的に抽象化するためには、もう一工夫必要です。

リスト36618は、リスト37188をアレンジし、この課題を解決するための方法です。

呼び出す側に、フィルタリング条件を羅列しますが、そこには値を直接記述します。これを受け取ったModelクラスは、その値をWP_Queryのフィルタリング条件にあてはめます。
この方法のメリットは、面倒なWP_Queryの記述から解放されるということです。
さらに、表示するViewクラスの名称なども呼び出す側の条件に加えることにより、サブクエリーから表示までを一貫して抽象化することができそうです。

参考文献

参考記事

※1PHPのコードをパーツ化する方法(2)クラスを使う方法

コード例

事例1:WP_Queryの拡張①Ratnayake氏の方法

呼び出す側

$the_query = new Model37188();
//ループ
if($the_query->have_posts()){
	While($the_query->have_posts()){
		$the_query->the_post();
		//Viewの記述	
		$view_obj = new View37188($par2) ;			
	}
	wp_reset_postdata();
}//endif

Modelクラス

class Model37188 extends WP_Query
{
	public function __construct( $args = array() )
	{
//クエリー	
		$args = wp_parse_args( $args, array(
			'post_type' => 'glossary',
			'meta_query' => array(
			'relation' => 'AND',
				array(
					'key' => 'gloss_type',
					'value' => '9851',
				),
				array(
					'key' => 'region',
					'value' => '9790',
				)
			)
		)
		);
		parent::__construct($args) ;
		
	}
}

Viewクラス

class View37188
{
	public function __construct($par2)
	{
		the_title() ;
		echo "<br>\n" ;	
	}//endfunction
}//endclass

事例2:WP_Queryの拡張②アレンジした方法

呼び出す側

$args = array(
	'post_type' => 'glossary',
	'key' => array('gloss_type','region'),
	'value' => array('9851','9790')	
	);
$query = new Model36618($args);

Modelクラス

class Model36618 extends WP_Query
{
	public function __construct($var)
	{
//配列をオブジエクトに変換。
	$par =(object)$var;
//クエリー	
		$args = array(	
			'post_type' => $par->post_type,
			'meta_query' => array(
			'relation' => 'AND',
				array(
					'key' => $par->key[0],
					'value' => $par->value[0],
				),
				array(
					'key' => $par->key[1],
					'value' => $par->value[1],
				)
			)
		);
		
		$the_query = new WP_Query($args) ;
//ループ
		if($the_query->have_posts()){
			While($the_query->have_posts()){
				$the_query->the_post();
				//Viewの記述	
				$view_obj = new View36618($par2) ;			
			}
			wp_reset_postdata();
		}//endif
		
	}
}

Viewクラス

class View36618
{
	public function __construct($par2)
	{
		the_title() ;
		echo "<br>\n" ;	
	}//endfunction
}//endclass

Leaflet入門

「Leaflet」は、Webサイトに地図を載せる場合に利用するツールです。
「Leaflet」はフリーソフトでありながら、細かなオプションが用意されているのが特徴です。

リスト1 は、背景となる地図(ベース地図)を表示するコードです。
WordPressにLeafletを埋め込む場合は、事前準備として、function.phpに、Leafletを読み込むコードを記述します。

参考文献

参考記事

コード例

事例1:Leaflet入門(背景地図の表示)

function.php

まず、事前準備として、次のコードをfunction.phpに記述します。

function leaflet_enqueue_styles() {
    wp_enqueue_style( 'leaflet-style', '//unpkg.com/leaflet@1.5.1/dist/leaflet.css', NULL, NULL );
}
add_action( 'wp_enqueue_scripts', 'leaflet_enqueue_styles' );
/* 先にスタイルシートを読み込んでからJavaScriptを読み込む */
function leaflet_enqueue_script() {
    wp_enqueue_script( 'leaflet-js', '//unpkg.com/leaflet@1.5.1/dist/leaflet-src.js', NULL, NULL );
}
add_action('wp_enqueue_scripts', 'leaflet_enqueue_script');

テンプレートファイル

次にテンプレートファイルに次のコードを記述します。

<body>
    <div id="map_1" style="height: 400px;"></div>
</body>

<script>
//////背景地図
	var osm = new L.tileLayer
	('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    	maxZoom: 19,
    	attribution: "Map data © <a href='https://www.openstreetmap.org/copyright' target='_blank'>OpenStreetMap</a> contributors"
	});
	
	var map_1 = L.map('map_1', {
		layers: [osm],	
		center: [35.717007,139.752772],
		zoom: 18,
    	zoomControl: true
		});
</script>

「日本版MapWarper」のジオリファレンス機能について

◆ジオリファレンスとは

古地図をWEB地図上に表示するためには、スキャナーやデジタルカメラなどを使って紙の地図をデジタル化し、それをWEB地図上に貼り付けるわけですが、このとき、
(1)古地図に緯度・経度の情報を付加する作業
(2)古地図を適切な形に整形して (ゆがめて) 現実の地図の上に置く作業
が必要です。この作業のことをジオリファレンスと言います。

◆日本版MapWarperについて

日本版MapWarper」は、このジオリファレンスを簡単に行うことができるツール(ジオリファレンサー)です。
オープンソース・ソフトウェアなので、誰でも無料で利用でき、公開した地図(されている地図)は、誰でも閲覧でき、ダウンロード利用できます。

◆「大正3年頃の鯖江図」のジオリファレンス事例

今回は、鯖江市が公開している古地図データ*1 を日本版MapWarperにアップロードして、ジオリファレンスを行います。

古地図

日本版MapWarperに会員登録し、ログインし、メニューの「地図をアップロードする」を使って古地図をアップロードします。

次に、「整形」の機能を使って、古地図を変形・伸縮させて現実の地図の座標に合うよう整形(ジオリファレンス)します。画面の左側が古地図、右側が現実の地図です。大正時代の地図は現在の地図にぴったりと重なりませんので、ここで補正を行います。両方の地図の一致する場所をダブルクリックして基準点を登録します。今回は、11か所の基準点を登録しました。①から⑪までの基準点が図示されています。

整形画面

最後に「切り抜き」の機能を使って古地図の余分な部分を取り除くと完成です。

「プレビュー」のタブに切り換えると、現実の地図の上に古地図が重ねられた状態が確認できます。*2

プレビュー画面

参考文献

*1
鯖江地区まちづくり推進協議会鯖江市 古地図データ鯖江市 リンク
大正3年頃の鯖江図「新撰鯖江誌」より 1914 リンク

参考記事

PHPのコードをパーツ化する方法(2)クラスを使う方法

前回※1、get_template_part()に引数を渡す方法を紹介しましたが、この方法では、
(1)呼び出す側にset_query_varと呼び出される側にget_query_varをその都度書かなければならないこと。
(2)PHPファイル別々に作成するので、見通しが悪くなること。
ことが、課題です。
そこで、今回は、これに代わる方法として、classを呼び出す方法を紹介します。


参考文献

参考記事

※1PHPのコードをパーツ化する方法(1)get_template_part()で引数を渡す方法

この記事を参照している記事

WP_Queryのカスタマイズ

コード例

事例1:WP_Queryの拡張②アレンジした方法

呼び出す側

$args = array(
	'post_type' => 'glossary',
	'key' => array('gloss_type','region'),
	'value' => array('9851','9790')	
	);
$query = new Model36618($args);

Modelクラス

class Model36618 extends WP_Query
{
	public function __construct($var)
	{
//配列をオブジエクトに変換。
	$par =(object)$var;
//クエリー	
		$args = array(	
			'post_type' => $par->post_type,
			'meta_query' => array(
			'relation' => 'AND',
				array(
					'key' => $par->key[0],
					'value' => $par->value[0],
				),
				array(
					'key' => $par->key[1],
					'value' => $par->value[1],
				)
			)
		);
		
		$the_query = new WP_Query($args) ;
//ループ
		if($the_query->have_posts()){
			While($the_query->have_posts()){
				$the_query->the_post();
				//Viewの記述	
				$view_obj = new View36618($par2) ;			
			}
			wp_reset_postdata();
		}//endif
		
	}
}

Viewクラス

class View36618
{
	public function __construct($par2)
	{
		the_title() ;
		echo "<br>\n" ;	
	}//endfunction
}//endclass

PHPのコードをパーツ化する方法(1)get_template_part()で引数を渡す方法

WordPressのカスタマイズの規模が大きくなると、8割~9割は同じようなPHPのコードを何度も書いていることがあります。このようなときは、別ファイルを作成してソースコードを分割し、コードを再利用することにします。
分割した別ファイルは、get_template_part()によって呼び出しますが、このとき、再利用の度合いを高めるために引数を渡したい場合があります。

WordPressCodexには、テンプレートに変数を渡す方法が解説されています。
今回は、一例として、引数taxと引数termを渡して、テンプレート側サブクエリーを実行する例を紹介します。

参考文献

参考記事

この記事を参照している記事

PHPのコードをパーツ化する方法(2)クラスを使う方法

コード例

事例1:get_template_part()でサブクエリーを呼び出す方法

呼び出す側

$args = array(
	'tax' => 'region',
	'term' => '9789',			
);
set_query_var( 'val', $args) ; 
get_template_part( 'template-parts/sample/content', 'sample' );	

呼び出される側

<?php
//引数を受け取り
		$var = get_query_var('val');
		$par =(object)$var;
//サブクエリー
		$args = array(		
			'post_type' => 'post',
			'tax_query' => array(
				array(
					'taxonomy' => $par->tax,				
					'field' => 'term_id',
					'terms' => $par->term,
				)
			)
		);
		$the_query = new WP_Query($args) ;
//サブループ
		if($the_query->have_posts()){
			While($the_query->have_posts()){
				$the_query->the_post();
					//表示
					the_title() ;
					echo "<br>\n" ;
			}
		}//endif	
築地(和風スナック)沢の鶴の看板。月島三丁目。
築地(西仲通り商店街)明治時代の埋め立て工事により出来上がった町。