baserCMS 4系テーマの5系化(step 1) - 「Omotenashi2」レイアウトファイルをマイグレートしてみる。

- 2025/4/25 追記
「ついでのちょっとした改修提案」項を追記しました。「4系テーマの5系化」と題して、4系テーマを5系にマイグレートするステップを数回に分けて記事にしてみようと思います。 今回は、ステップ1として、レイアウトファイルをマイグレートしてみます。
ステップの考え方としては、動作可能な最小構成のファイルからはじめて、「5系テーマガイド - baserCMS4のテーマを変換」 を参考にしつつ、追々(トライアル&エラーで)その他のファイル(ブログのレイアウトファイルやエレメントファイルなど)を追加、改修する手順で、テーマ全体のマイグレートを実現しようと思います。
というのも、そろそろ5系の学習を(ちゃんと?)始めてみようかと思っても、開発者でもない限り、なかなか体系だってマニュアルやリファレンスを最初から読みくだす人も少ないだろうし、ならばひとまずナレッジとして4系テーマを5系にマイグレートしてみれば、5系の理解を深めるきっかけになるかなぁという目論みで、近頃、関わることが多かったOmotenashi2テーマ(4系)をお題にしてみることにしました。
基本的なフォルダ構成の変更やお約束のオマジナイ(src/Plugin.php
)、config.phpの作成などは、baserCMS5公式ガイドに倣って言わずもがなで準備するとしても、Omotenashi2テーマの場合は、レイアウトファイルの改修対応とテーマ内にコピーされているBcBaserHelper.phpの扱いをどうするかの検討はマスト。BcBaserHelper.phpの扱いをどうするかは、ステップ2以降で取り沙汰するとして、まずは基本的なフォルダ構成の理解とレイアウトファイルをマイグレートしてみようというのが表題です。
マイグレートする5系テーマとしての条件整備は、CakePHP5対応のbaserCMS5.1系対応のテーマとします。チェックは、baserCMS 5.1.5、データベースMySQL8.2、PHP8.2の環境で行います。
事前準備
- まずは、事前にBaserCMS5.1.xをインストールし、デバッグモードに設定します。
CakePHPのエラーを拾うためなので、一通りの作業が終われば適宜、ノーマルモードに戻します。 - 「5系テーマガイド - 独自のテーマを作成する」に倣って、{baserCMSの設置フォルダ}/plugins/Omotenashi2/ を作成。
その上で、plugins/Omotenashi2/に最小限のフォルダ構成とファイルを作成します。 - 管理画面のテーマ管理で、テーマ一覧から「Omotenashi2」テーマを適用します。
この辺りを手っ取り早くやろうとすると、プラグインの「アドオンマイグレーター」 を使っても便利かもしれません。
いや、そもそもテーマ自体の5系化を最初から「アドオンマイグレーター」使えばいいのにと思われるかもですが、実際のところ、マイグレーターを使っても手作業なしで動くことは滅多にありませんし、マイグレーターがマイグレートしたフォルダ一式をバクッとpluginsフォルダに配置されたままだと、一体どこにエラーががあるのか、わからなくなってしまうので(スキルが足りないからかもしれませんが、少なくとも私はそう)、まずは最小のフォルダ・ファイル構成でHome画面がエラーなく表示されるところを目指そうというのがこの記事のコンセプトです。
で、話は「アドオンマイグレーター」に戻りますが、「アドオンマイグレーター」にかけると、5系テーマの基本的なフォルダ構造に、サクッと作り替えてはくれるので、それを利用して、5系テーマの最小のフォルダ・ファイル構成を実現する - というのもありかと思います。
具体的には、
- プラグインクラスを作成する。
<?php
namespace Omotenashi2;
use BaserCore\BcPlugin;
class Omotenashi2Plugin extends BcPlugin {}
- configファイルを作成する。
<?php
return [
'type' => 'Theme',
'title' => 'Omotenashi2',
'description' => '飲食店や雑貨店などの店舗系サイト、コーポレートや各種プロモーション向けのテーマデザインです。
レイアウトはシンプルに作られているので、企業向けのテーマとしてもお使いいただけます。
レスポンシブで作られているので、PC・タブレット・スマートフォン等のデバイスに対応しています。
'author' => 'mune_nori',
'url' => 'https://twitter.com/mune_nori',
'adminLink' => [],
'installMessage' => '',
];
- 4系のレイアウトファイル
theme/omotenashi2/Layouts/default.php
をそのまま5系のplugins/Omotenashi2/templates/layout/default.php
に再配置します。
ここまでは、テーマガイドの通り。ここから、個人的な試行として、
vendor/baserproject/bc-front/templates/Pages/default.php
をコピーし、plugins/Omotenashi2/templates/Pages/default.php
に配置します。 ファイルをコードエディタで開き、不要な<?php $this->BcBaser->updateInfo() ?>
コードを削除します。そうしないと、固定ページコンテンツエリアの末尾に更新日、作成日の日付が意図せず表示されてしまうため。- 4系のアセットファイル群(css、js、imgファイルなど)も未調整のまま、一旦配置しておく。その方が現実的なレイアウトや機能の評価がしやすいため。
以上で事前準備は完了。
詳細
さて、ここからが本題です。
まずはサイトURLにアクセスし、ブラウザでユーザー(フロント側)画面を表示させてみます。plugins/Omotenashi2/templates/layout/default.php
に再配置した4系のレイアウトファイル theme/omotenashi2/Layouts/default.php
のエラーをデバッグモードで拾ってみる。
Warning (2) : Undefined variable
が複数出たものの、案外すんなり画面は表示される。
ざっと(開発ツールでも)見たところ、エラーっぽいところは、以下。
Warning (2) : Undefined variable
が表示された11行目から13行目。admin/functions.js
が404エラー。
その他の読み込みエラーは、以下。
- Omotenashi2テーマ独自のヘッダーエレメントファイルが読み込めていない。→ 原因はelementフォルダ(およびファイル)を配置していないため(当たり前)
- トップスライダーのレイアウトが崩れている。→ BcBaserHelper.php(テーマ内で独自に改修されたもの)を配置していないため(当たり前)
- グローバルメニューの表示が崩れている。→ 原因はelementフォルダ(およびファイル)を配置していないため(当たり前)
- ブログのポストエリアの表示が崩れている。→ 原因はBlogフォルダ(およびファイル)を配置していないため(当たり前)
- エレメントテンプレート「footer_contact」が見つからない。→ 原因はelementフォルダ(およびファイル)を配置していないため(当たり前)
- Omotenashi2テーマ独自のフッターエレメントファイルが読み込めていない。→ 原因はelementフォルダ(およびファイル)を配置していないため(当たり前)
といった感じで、比較的優秀なのかな?!
(当たり前)ステータスのものは、ひとまずスルーして、PHP8系に未対応のコードの修正と、そもそも4系の直近バージョンでも不具合として内在していた箇所をまずは修正していくことにしますが、これらの箇所は、実はほとんどがOGPタグ出力のためのコード部分なので、 先だっての「baserCMS 5系でアイキャッチ画像も使って、OGPタグをいい感じで出力する」記事で取り上げたOGPタグ出力のコード(そもそもOmotenashi2テーマ(4系)のレイアウトファイルから拾い出しているので)を参考に修正します。 修正箇所についての細々したことは、書いているとキリがないので、興味がある方は、「修正箇所:」のコメントアウトを頼りにオリジナルのdefault.phpと比較してご確認ください。
<!DOCTYPE html>
<html dir="ltr" lang="ja">
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# website: http://ogp.me/ns/website#">
<?php $this->BcBaser->charset() ?>
<?php $this->BcBaser->title() ?>
<?php $this->BcBaser->metaDescription() ?>
<?php $this->BcBaser->metaKeywords() ?>
<?php
//OGP
//=====================================
$siteName = $this->BcBaser->getSiteName(); //修正箇所:関数に置き換え。
//修正箇所:$siteUrlは、実際どこにも利用していないため削除。
$description = mb_substr($this->BcBaser->getDescription(), 0, 100); //修正箇所:サイト説明文。例:80-100文字で調整。関数に置き換え。
$title = $this->BcBaser->getTitle(); //ページタイトル95文字以内
$type ="website"; //記事はarticle, それ以外(HOME、固定ページ)はwebsite
$url =$this->BcBaser->getUri($this->BcBaser->getHere());
$publisher = ""; //サイトのFacebookページURLかID。FacebookページのFollowボタンを表示できるようになる。
$fb_id = ""; //FacebookのAPP ID
$author = ""; //TwitterCardに表示されるアカウント名
//修正箇所:$domainは、利用しないため削除。
$currentContent = $this->BcBaser->getCurrentContent();
$eyeCatch = $this->BcUpload->uploadImage('eyecatch',
$currentContent,
[
'table' => 'BaserCore.Contents',
'imgsize' => '',
'alt' => '',
'noimage' => $this->BcBaser->getThemeUrl().'img/common/ogp.jpg',
'output' => 'url',
'link' => false
]
);
$trim = '?';
$eyeCatch = $this->BcBaser->getUri(substr($eyeCatch, 0, strcspn($eyeCatch, $trim))); //取得したURLのクエリー文字列(特定文字「?」以降)を除去し、URIで出力
//ブログ記事の場合のアイキャッチ画像出力
if (!empty($post)) {
$type ="article";
$num = 100; //説明文の文字数制限。例:80-100文字で調整
$str = strip_tags($this->Blog->getPostContent($post, true, false, false)); //説明文(概要+本文から抜き出し)タグ除去
$str = str_replace(["\r\n","\n","\r"],'', $str); //改行除去
if(mb_strlen($str) >= $num) {
$description = mb_substr($str, 0,$num-1)."…";
} else {
$description = $str;
}
//タイトルにはサイトタイトルを含めない
$title = $this->Blog->getPostTitle($post,false) . ' – ' . $this->BcBaser->getSiteName(); //ページタイトル95文字以内
$eyeCatch = $this->Blog->getEyeCatch($post,
[
'output'=>'url',
'imgsize'=>'thumb',
'noimage'=>$this->BcBaser->getThemeUrl().'img/common/blog_ogp.jpg'
]
);
$trim = '?';
$eyeCatch = $this->BcBaser->getUri(substr($eyeCatch, 0, strcspn($eyeCatch, $trim)));
}
?>
<meta property="article:publisher" content="<?php echo $publisher; ?>">
<meta property="og:type" content="<?php echo $type; ?>">
<meta property="og:locale" content="ja_JP">
<meta property="og:site_name" content="<?php echo $siteName; ?>">
<meta property="og:title" content="<?php echo $title; ?>">
<?php //修正箇所:$descriptionに置き換え。 ?>
<meta property="og:description" content="<?php echo $description; ?>">
<meta property="og:url" content="<?php echo $url; ?>">
<meta property="og:image" content="<?php echo $eyeCatch; ?>">
<meta property="fb:app_id" content="<?php echo $fb_id; ?>">
<?php // Twitter Cardsの種類指定 ?>
<meta name="twitter:card" content="summary_large_image">
<?php // カードフッターで使用されるウェブサイトの@TwitterID(無くてもOK) ?>
<meta name="twitter:site" content="<?php echo $author; ?>">
<!-- //修正箇所:その他のOGPタグで代用されるため削除。
<meta name="twitter:creator" content="<?php echo $author; ?>">
<meta name="twitter:domain" content="<?php echo $domain; ?>">
<meta name="twitter:url" content="<?php echo $url; ?>">
<meta name="twitter:title" content="<?php echo $title; ?>">
<meta name="twitter:description" content="<?php echo $this->BcBaser->getDescription() ?>">
<meta name="twitter:image" content="<?php echo $eyeCatch; ?>">
-->
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
<?php $this->BcBaser->icon() ?>
<?php //修正箇所:BcBaser->rss()は、rssフィーダー未実装のため削除。 ?>
<?php $this->BcBaser->css([
'style']); ?>
<?php $this->BcBaser->js([
'jquery-3.4.1.min.js',
//修正箇所:'admin/functions'は、不要なので削除。
'jquery.easing',
'common']); ?>
<?php $this->BcBaser->scripts() ?>
<?php if ($this->BcBaser->isHome()): ?>
<script src="<?php $this->BcBaser->themeUrl() ?>js/slick.min.js"></script>
<script src="<?php $this->BcBaser->themeUrl() ?>js/index.js"></script>
<?php endif ?>
<?php if (!$this->BcBaser->isHome()): ?>
<script src="<?php $this->BcBaser->themeUrl() ?>js/jquery.magnific-popup.min.js"></script>
<script>
$(function() {
//magnific-popup
//修正箇所:[rel='colorbox']属性のaタグに限定
$(".popup, .eyeCatch a, a[rel='colorbox']").magnificPopup({
type: 'image',
mainClass: 'mfp-with-zoom',
removalDelay: 160,
preloader: false,
fixedContentPos: false,
gallery:{enabled:true}
});
});
</script>
<?php endif ?>
<?php $this->BcBaser->googleAnalytics() ?>
</head>
<body<?php if ($this->BcBaser->isHome()): ?> class="index"<?php endif ?>>
<?php $this->BcBaser->header() ?>
<main>
<?php if (!$this->BcBaser->isHome()): ?>
<aside class="breadcrumb">
<nav class="container">
<?php $this->BcBaser->crumbsList(); ?>
</nav>
</aside>
<?php endif ?>
<?php if ($this->BcBaser->isHome()): ?>
<?php $this->BcBaser->flash() ?>
<div class="indexContents">
<div class="mainVisual">
<div class="mainVisual__inner">
<h2 class="mainVisual__hl fontNotoSerif">博多の味、幸せの味<br>美味しいと笑顔になれる</h2>
<?php $this->BcBaser->mainImage(array('num' => 5, 'all' => true, 'class' => 'mainVisualList')) ?>
</div>
</div>
<div class="container">
<section class="topNews">
<div class="topNews__box">
<h2 class="topNews__hl fontNotoSerif">お知らせ</h2>
</div>
<div class="topNewsList">
<?php $this->BcBaser->blogPosts('news', 3) ?>
</div>
</section>
</div>
<?php $this->BcBaser->content() ?>
</div>
<?php else: ?>
<article class="contents">
<?php $this->BcBaser->content() ?>
</article>
<?php endif ?>
</main>
<?php $this->BcBaser->element('footer_contact'); ?>
<?php $this->BcBaser->footer() ?>
<?php $this->BcBaser->func() ?>
</body>
</html>
ひとまず、レイアウトファイルがマイグレートできていないことによるトップページのエラーは、これで解消できたはず。ただ、この後のステップの作業で修正の対応が必要な箇所が出てくるとおもいますので、都度、修正を加えていくことになります。
ついでのちょっとした改修提案
マイグレートの趣旨からは脱線するのですが、ちょっとした提案です。
実は、4系「Omotenashi2」テーマ内には、default.php と tpl_news.php の2種類があって、ブログ(お知らせ)ページに適用する前提のtpl_news.php とそれ以外のページ(トップページ、固定ページ、メールなど)に適用する default.php 想定のようです。
なぜ、レイアウトファイルをブログとそれ以外のページで分けているのかを紐解くと、ブログ記事詳細ページ内にあるFacebook用のいいね!、シェアボタン用のコードで必要とするJavaScript SDKを tpl_news.php にのみに記載して、それらのコードを必要としないブログ以外のページでは無駄に読み込ませない様に配慮している様でした。
それはそれで合点はいくのですが、
<?php if (!empty($post)) {} ?>
<?php if (!$this->BcBaser->isHome()): ?><?php endif ?>
とかの条件分岐は、default.php のそこかしこにあって、この件だけで、別のレイアウトファイルをブログページ用に用意しているのにちょっとした違和感がありました。
なので、tpl_news.php に記載されているFacebook用のいいね!、シェアボタン用のJavaScript SDKの部分を以下の様に条件分岐を入れて default.php に記述してしまい、テーマ全体のレイアウトファイルとしては、default.php のみに一本化したほうがシンプルかと。
<body<?php if ($this->BcBaser->isHome()): ?> class="index"<?php endif ?>>
<?php if (!empty($post)): ?>
<!-- facebook script -->
<div id="fb-root"></div>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "https://connect.facebook.net/ja_JP/sdk.js#xfbml=1&version=v3.0";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
<?php endif ?>
<?php $this->BcBaser->header() ?>
<!-- 中略 -->
</body>
JavaScript SDK自体の現時点で最新のものではない様ですが、そもそも、いまさらFacebookでも、いいね!ボタンでもないような気は一方ですごくするので(笑)、必要な方が必要なボタン用のJavaScript SDKに差し替えていただければと思います。 ちなみにこのままでも、動いているようです。
最後に
今後は、ステップ2、3などとして、BcBaserHelper.phpに代わるOmotenashi2Helper.phpの作成や、その他必要なブログ、メールのテンプレートファイル、elementフォルダ内のテンプレートファイルの修正などについて、追々触れていきたいと思っています。