デフォルトレイアウトと、OGPタグのお話(CakePHP3系)

皆様こんにちは。
今日はCakePHP3系のデフォルトレイアウト(default.ctp)ファイルと、
OGPタグについてお話します。

この記事の結論は、
ogpタグ周りをjavascriptを使用して、
動的に変更する技術を紹介する記事となります。

デフォルトレイアウトって何やねんという方や、
OGPタグって何やねんという方は下記に参考URLを貼り付けましたので、
ご参照いただいた上で本記事をご確認いただけますと幸いです。


【デフォルトレイアウトについて】
*以下ページの『レイアウト』から読み進めてください
https://book.cakephp.org/3.0/ja/views.html#view-layouts

【OGPタグについて】
https://digitalidentity.co.jp/blog/seo/ogp-share-setting.html


■本題
さて、cakephpを使用してWebアプリやサイトを構築していると
デフォルトレイアウト(default.ctp)を使用する事が多々あると思います。
用途は様々ありますが、私はbodyタグ内に各ページのctpファイルを呼び出す使い方が多いです。
以下一例

```html
<!DOCTYPE html>
<html lang="ja" prefix="og: http://ogp.me/ns#">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="content-language" content="ja">
	<meta http-equiv="X-UA-Compatible" content="IE=edge" />
	<meta name="viewport" content="width=device-width,initial-scale=1" />
	<!-- SEO向け 今回は以下metaタグをjsで書き換えるよ-->
	<meta name="description" content="" />
	<meta name="page_title" property="og:title" content="" /> 
	<meta name="type" property="og:type" content="" /> 
	<meta name="desc" property="og:description" content="" />
	<meta name="url" property="og:url" content="" />
	<meta name="site_name" property="og:site_name" content="" />
	<meta name="img_url" property="og:image" content="" />
	<title name="title">テストサイト</title>


	<!-- 各ページごとのcss読み込み -->
	<?php
        　echo $this->Html->css('default');
        　echo $this->fetch('css');
	?>

</head>
<body>
    <!-- ハンバーガーメニュー押した後に開くグローバルナビ -->
	<nav class="gnav">
		<div class="gnav_wrap">
			<ul class="gnav_menu">
				<li class="gnav_menu_item"><span class="line_effect"><a href="<?php ?>">TOP</a></span></li>
				<li class="gnav_menu_item"><span class="line_effect"><a href="<?php ?>">Menu</a></span></li>
			</ul>
		</div>
	</nav>

	<!-- ハンバーガーメニュー  -->
	<a class="menu">
		<span class="line_top"></span>
		<span class="line_center"></span>
		<span class="line_bottom"></span>
	</a>

	<!-- スムーススクロール -->
	<p id="to_top"><a href="#to_top"></a></p>
	<div class="contents_inner">
		<?php
            echo $this->Flash->render();
            echo $this->fetch('content');//←ここに各ページのctpファイルが読み込まれる
        ?>
	</div>

	<!-- 各SNSのJS読み込み -->
	<script name="twitter_js" async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

	<script name="facebook_js" async defer crossorigin="anonymous" src="https://connect.facebook.net/ja_JP/sdk.js#xfbml=1&version=v3.2"></script>

	<script name="line_js" src="https://d.line-scdn.net/r/web/social-plugin/js/thirdparty/loader.min.js" async="async" defer="defer"></script>

	<!-- 全ページに必要なjsファイルの読み込み -->
    <?php
        echo $this->Html->script('smooth');
        echo $this->Html->script('humburger');
        echo $this->Html->script('default');

        //各ページごとのjsファイルの読み込み
        echo $this->fetch('script');
    ?>

</body>
</html>
```


そうすると、
ある事が問題となります。


■ぶち当たる問題
記事コンテンツを配置しているページ(show.ctp等)が複数ある場合、
上記一例で上げた <!-- SEO向け 今回は以下metaタグをjsで書き換えるよ-->
以下のogpタグを書き換える必要が発生します。
default.ctpにハードコーディングとして、
静的に値を入れると他のページでは使いまわせないですよね。


■どう解決するのか
私はjavascriptを使用して解決しました。

考え方としては

1.default.ctpにcontent=""として、空白値を持たせる
<meta name="type" property="og:type" content="" /> 

2.各コンテンツのshow.ctpページにcontent=""の空白値を書き換える値を設置する

3.javascriptで2番の値を1番の空白に入れる処理を書く


以下一例


```js

var path = location.pathname ;
if ( path.match(/show/)) {//showページをの場合
	//SEO対策用
	var metadis = document.head.children;
	var metalen = metadis.length;//メタタグの個数を取得
	for(var i = 0; i < metalen; i++){//メタタグの個数分繰り返し処理
		var proper = metadis[i].getAttribute('name');//メタタグのname属性値を取得
		if(proper === 'page_title'){
			var content = document.getElementsByClassName('main_title');//各showページに配置
			var content = content[0]['innerText'];
			var dis = metadis[i];
			document.title = content;
			dis.setAttribute('content',content);
		}else if(proper === 'type'){
			var content = 'blog';
			var dis = metadis[i];
			dis.setAttribute('content',content);
		}else if(proper === 'url'){
			var content = document.getElementsByClassName('url');
			var content = content[0]['baseURI'];
			var dis = metadis[i];
			dis.setAttribute('content',content);
		}else if(proper === 'site_name'){
			var content = document.getElementsByClassName('main_title');
			var content = content[0]['innerText'];
			var dis = metadis[i];
			dis.setAttribute('content',content);
		}else if(proper === 'img_url'){
			var content = document.getElementsByClassName('main_img');
			var content = content[0]['currentSrc'];
			var dis = metadis[i];
			dis.setAttribute('content',content);
		}
	}

}
```

簡単にですが、
デフォルトレイアウトと、OGPタグのお話について
紹介させていただきました。

もっと良い方法があるよ!等ございましたら、
コメントにてご指摘いただけますと幸いです。

以上です。