前編に引き続き、Craft CMS で日本語タイトルをローマ字変換して slug にセットする方法について考えていきますが、 実装にあたって欲しい機能は次の3つです。
- エントリのタイトルをローマ字変換して slug にセットする
- エントリの初回保存時のみ、実行する
- slug に日本語が含まれない場合は、何もしない
このくらいであれば、モジュールとして用意するのが手軽で良さそうですね。
では、具体的な手順を見ていきましょう。
これは Craft CMS Advent Calendar 2023 20日目の記事です。
モジュールの作成
はじめに、モジュールを作成しましょう。
モジュールの作成は、Craft Generator を利用します。
Craft Generator の導入方法については、Craft CMS のプラグインやモジュールのひな形を作るを参考にしてください。
Craft CMS 本体のインストールディレクトリに移動して、次のコマンドを実行します。
./craft make module
ここでは、Craft CMS のモジュールを作ってみようと同じ内容で作成しました。
Should the module be loaded during app initialization?
で yes
と答えているため、自動的に config/app.php
にも変更が加えられます。
管理画面の ユーティリティ > システム情報
にアクセスすると、モジュールが読み込まれていることを確認できますね。
実行ファイルの配置
次に、前編で作成した実行ファイル convert2hepburn.py
を Craft CMS 本体のインストールディレクトリ直下にある modules/sampleModule/
内に配置します。
なお、Craft CMS の実行環境で python3
と pykakasi
が使える前提となりますので、必要に応じてインストールしておいてください。
カスタムモジュールにイベント処理を追加
最後に、modules/sampleModule/Module.php
を開き、次のように修正します。
<?php
namespace modules\sampleModule;
use Craft;
use yii\base\Module as BaseModule;
use craft\elements\Entry;
use craft\events\ModelEvent;
use yii\base\Event;
/**
* sample-module module
*
* @method static Module getInstance()
*/
class Module extends BaseModule
{
public function init(): void
{
Craft::setAlias('@modules/sampleModule', __DIR__);
// Set the controllerNamespace based on whether this is a console or web request
if (Craft::$app->request->isConsoleRequest) {
$this->controllerNamespace = 'modules\\sampleModule\\console\\controllers';
} else {
$this->controllerNamespace = 'modules\\sampleModule\\controllers';
}
parent::init();
// Defer most setup tasks until Craft is fully initialized
Craft::$app->onInit(function() {
$this->attachEventHandlers();
// ...
});
}
private function attachEventHandlers(): void
{
Event::on(
Entry::class,
Entry::EVENT_BEFORE_SAVE,
function (ModelEvent $event) {
$entry = $event->sender;
// 初回セーブ、かつ、$entry->slug に日本語を含む場合のみ実行
if ($entry->firstSave && preg_match('/[ぁ-ん]+|[ァ-ヴ]+|[一-龠]+/u', $entry->slug)) {
// 実行ファイルのパスをセット
$filePath = CRAFT_BASE_PATH . '/modules/sampleModule/convert2hepburn.py';
// コマンドを整形して、実行
$command = 'python3 ' . $filePath . ' ' . escapeshellarg($entry->title);
exec($command, $output);
// ローマ字変換された文字列を $entry->slug にセット
$entry->slug = $output[0];
}
}
);
}
}
このサンプルでも、実際に追記したのは次の2箇所だけです。
必要なクラスの読み込み
今回は「エントリの保存前イベント」を操作したいため、次のクラスが必要です。
use craft\elements\Entry;
use craft\events\ModelEvent;
use yii\base\Event;
イベント処理
ここでは、自動保存を除くエントリの初回保存時に slug へ日本語を含む場合のみ、ローマ字変換を行うようにしています。
Event::on(
Entry::class,
Entry::EVENT_BEFORE_SAVE,
function (ModelEvent $event) {
$entry = $event->sender;
// 初回セーブ、かつ、$entry->slug に日本語を含む場合のみ実行
if ($entry->firstSave && preg_match('/[ぁ-ん]+|[ァ-ヴ]+|[一-龠]+/u', $entry->slug)) {
// 実行ファイルのパスをセット
$filePath = CRAFT_BASE_PATH . '/modules/sampleModule/convert2hepburn.py';
// コマンドを整形して、実行
$command = 'python3 ' . $filePath . ' ' . escapeshellarg($entry->title);
exec($command, $output);
// ローマ字変換された文字列を $entry->slug にセット
$entry->slug = $output[0];
}
}
);
exec()
で実行するにあたり、エントリのタイトルを escapeshellarg()
でエスケープしています。
また、実行結果は $output[0]
に格納されるため、これを $entry->slug
にセットしています。
サンプルとしてザックリ実装しているため、対象セクションを制限したり、エラーハンドリングを追加するなど、必要に応じて調整してください。
動作を確認してみる
では、実際に動作を確認してみましょう。
自動保存の状態では、slug は日本語表示のままです。
command + S
で明示的に保存したところ、slug がローマ字変換されました。
これで完成ですね。
まとめ
2回にわたって、Craft CMS で日本語タイトルをローマ字変換して slug にセットする方法について考えてきました。
込み入った実装でなければ、モジュールとして用意するのが手軽で良さそうですね。
また、(邪道かとは思いつつ)PHP に拘り過ぎないことも大事かな?と、改めて感じました。
たまたま目にしたポストがきっかけだったものの、実際に作ってみるとなかなか面白い機能で、個人的にも勉強になりました。
という訳で。
ハッシュタグ #craftcms
でポストいただければ、勝手に試してブログ記事にさせてもらう・・・かもしれません。