ドキュメント
開発者向けのプラグイン開発とテーマデザインのガイドです。
プラグイン開発
YikaiCMS のプラグインシステムは WordPress スタイルの Action / Filter フック機構を採用しており、コアコードを変更することなく機能を拡張できます。
ディレクトリ構成
各プラグインは plugins/ 配下のフォルダーであり、少なくとも 2 つのファイルを含みます:
plugins/
my-plugin/
plugin.json # プラグイン記述ファイル(必須)
main.php # エントリーファイル(必須)
admin.php # 管理画面ページ(任意)
plugin.json
プラグインのメタ情報を記述し、システムはこれをもとに管理画面でプラグイン一覧を表示します。
{
"name": "私のプラグイン",
"version": "1.0.0",
"description": "これはプラグインの機能説明です。",
"author": "あなたの名前",
"requires_php": "8.0",
"requires_cms": "1.0.0"
}
name — 管理画面に表示されるプラグイン名
requires_php — 必要な最低 PHP バージョン
requires_cms — 必要な最低 CMS バージョン
フックシステム
main.php の中で add_action() と add_filter() を使ってフックのコールバックを登録します。
利用可能な Action フック
| フック名 | トリガー位置 |
|---|---|
plugins_loaded | すべてのプラグインの読み込み完了後 |
ik_head | フロントの </head> 直前、CSS / meta を挿入 |
ik_header_after | フロントのナビゲーションバーの後 |
ik_footer_before | フロントの footer 開始前 |
ik_footer_scripts | フロントの </body> 直前、JS を挿入 |
ik_admin_head | 管理画面の </head> 直前 |
ik_admin_footer_scripts | 管理画面の </body> 直前 |
API 関数
// コールバックを登録(priority が小さいほど先に実行、デフォルト 10) add_action(string $hook, callable $callback, int $priority = 10): void // フックをトリガー do_action(string $hook, mixed ...$args): void // フィルターを登録 add_filter(string $hook, callable $callback, int $priority = 10): void // フィルターを適用し、処理後の値を返す apply_filters(string $hook, mixed $value, mixed ...$args): mixed
管理画面ページ
プラグインに管理画面の設定 UI が必要な場合は admin.php を作成し、/admin/plugin_page.php?plugin=プラグインのディレクトリ名 からアクセスします。
<?php
// plugins/my-plugin/admin.php
if (!defined('ROOT_PATH')) {
exit('Access Denied');
}
$pageTitle = '私のプラグインの設定';
require_once ROOT_PATH . '/admin/includes/header.php';
?>
<div class="max-w-3xl">
<h2 class="text-xl font-bold mb-4">プラグイン設定</h2>
<!-- あなたの設定フォーム -->
</div>
<?php require_once ROOT_PATH . '/admin/includes/footer.php'; ?>
main.php の中で、プラグインカードに「管理画面」へのエントリーリンクを追加できます:
add_action('ik_admin_footer_scripts', function () {
if (basename($_SERVER['SCRIPT_NAME']) !== 'plugin.php') return;
echo '<script>
(function(){
var card = document.getElementById("plugin-my-plugin");
if (!card) return;
var info = card.querySelector(".text-xs.text-gray-400");
if (info) {
var a = document.createElement("a");
a.href = "/admin/plugin_page.php?plugin=my-plugin";
a.className = "text-primary hover:underline ml-4";
a.textContent = "管理画面を開く";
info.appendChild(a);
}
})();
</script>';
});
完全な例:トップへ戻るプラグイン
ページ右下に「トップへ戻る」ボタンを表示する、最もシンプルなフロントエンドプラグインです。
plugins/back-to-top/plugin.json
{
"name": "トップへ戻る",
"version": "1.0.0",
"description": "フロントページの右下にトップへ戻るボタンを表示します。",
"author": "Yikai CMS",
"requires_php": "8.0",
"requires_cms": "1.0.0"
}
plugins/back-to-top/main.php
<?php
if (!defined('ROOT_PATH')) {
exit('Access Denied');
}
add_action('ik_footer_scripts', function () {
?>
<div id="backToTop" onclick="window.scrollTo({top:0,behavior:'smooth'})"
style="position:fixed;bottom:30px;right:30px;z-index:9999;
width:44px;height:44px;border-radius:50%;
background:#3b82f6;color:#fff;display:none;
align-items:center;justify-content:center;
cursor:pointer;box-shadow:0 2px 12px rgba(59,130,246,0.4)">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2.5">
<path d="M18 15l-6-6-6 6"/>
</svg>
</div>
<script>
(function(){
var btn = document.getElementById('backToTop');
window.addEventListener('scroll', function(){
btn.style.display = window.scrollY > 400 ? 'flex' : 'none';
});
})();
</script>
<?php
});
テーマデザイン
YikaiCMS のテーマシステムはファイル上書き機構に基づいています。テンプレートファイルをテーマディレクトリに置くと、システムが自動的にテーマ版を優先して読み込み、上書きされていないファイルは includes/ のデフォルトテンプレートにフォールバックします。
ディレクトリ構成
themes/
my-theme/
theme.json # テーマ記述(必須)
assets/
images/
screenshot.png # プレビュー画像(管理画面に表示)
css/
style.css # テーマのカスタムスタイル(任意)
layouts/
header.php # ヘッダーレイアウト
footer.php # フッターレイアウト
blocks/
banner.php # トップページのカルーセルブロック
about.php # トップページの「私たちについて」ブロック
channel.php # トップページのチャンネルコンテンツブロック
stats.php # 統計ブロック
advantage.php # 強み紹介ブロック
testimonials.php # お客様の声ブロック
cta.php # 行動喚起(CTA)ブロック
partials/
breadcrumb.php # パンくずナビゲーション
page-hero.php # ページ上部のヒーローバナー
pagination.php # ページネーションコンポーネント
article-card.php # 記事カード
product-card.php # 製品カード
case-card.php # 事例カード
job-card.php # 求人カード
すべてのファイルは任意であり、カスタマイズしたいファイルだけを上書きすればよいです。
theme.json
{
"name": "私のテーマ",
"description": "シンプルで上品な企業サイトのテンプレート",
"version": "1.0.0",
"author": "あなたの名前",
"screenshot": "assets/images/screenshot.png",
"supports": [
"banner", "about", "stats",
"testimonials", "advantage", "cta", "channel"
]
}
screenshot — プレビュー画像のパス(テーマルートからの相対パス)。16:10 の比率を推奨し、1280×800px が望ましい
supports — テーマが対応するトップページのブロックタイプを宣言
レイアウトファイル
layouts/header.php と layouts/footer.php は、サイト全体で共通のヘッダーとフッターです。
header.php の基本構造
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo e($pageTitle ? $pageTitle . ' - ' : '');
echo e(config('site_name')); ?></title>
<link rel="stylesheet" href="/assets/css/tailwind.css">
<!-- テーマのカスタム CSS を読み込む -->
<link rel="stylesheet" href="<?php echo theme_asset('css/style.css'); ?>">
<?php do_action('ik_head'); ?>
</head>
<body>
<!-- ナビゲーションバーの HTML -->
<?php do_action('ik_header_after'); ?>
footer.php の基本構造
<?php do_action('ik_footer_before'); ?>
<footer>
<!-- フッターの HTML -->
</footer>
<?php do_action('ik_footer_scripts'); ?>
</body>
</html>
do_action() の呼び出しを必ず残してください。そうしないとプラグインのフックが機能しません。
トップページブロック
blocks/ 配下のファイルはトップページの各ブロックに対応し、index.php が設定された順序で読み込みます。各ブロックでは以下の定義済み変数を直接利用できます:
| ブロックファイル | 利用可能な変数 |
|---|---|
banner.php | $banners — カルーセル配列 |
about.php | config('home_about_*') で設定を取得 |
channel.php | $homeChannels — トップページに表示するチャンネル |
stats.php | config('home_stat_*') で数値を取得 |
advantage.php | config('home_adv_*') で強み項目を取得 |
testimonials.php | config('home_testimonials') で JSON を取得 |
cta.php | config('home_cta_*') で文言を取得 |
共通コンポーネント (Partials)
partials/ 配下のファイルは再利用可能な UI コンポーネントで、一覧ページや詳細ページで require によって読み込まれます:
// パンくずを読み込む(テーマディレクトリから自動的に検索し、includes/partials/ にフォールバック)
require theme_path('partials/breadcrumb.php');
// 製品カードを読み込む
require theme_path('partials/product-card.php');
コンポーネント内で利用できる変数は呼び出しコンテキストによって異なります。たとえば product-card.php では $item(単一の製品データ)が利用できます。
よく使う関数
| 関数 | 説明 |
|---|---|
config($key, $default) | システム設定を読み込む |
e($string) | HTML エスケープ出力 |
__($key) | 多言語翻訳 |
theme_path($file) | テーマテンプレートの絶対パスを取得(自動フォールバック) |
theme_asset($file) | テーマの静的リソース URL を取得 |
currentTheme() | 現在有効なテーマの slug |
channelUrl($channel) | チャンネル URL を生成 |
thumbnail($path, $size) | サムネイル URL を生成 |
parseShortcodes($html) | コンテンツ内のショートコードを解析 |
do_action($hook) | フックをトリガー(レイアウトでは必ず残す) |
themes/ ディレクトリに置き、管理画面の「テーマ管理」ページでプレビューおよび有効化できます。
デプロイ設定
YikaiCMS は URL の疑似静的化(動的 URL → .html 形式)に対応し、SEO を高めます。v1.12.9 以降は単一エントリールーターを内蔵し、WordPress のリライトルールと完全互換——ほとんどの環境で 1 手順、または設定不要です。
| 環境 | 設定方法 |
|---|---|
| BTパネル / aaPanel(Nginx) | リライト設定に include …/deploy/nginx-baota.conf; の 1 行(下の Nginx の節を参照。「wordpress」プリセットだけにしない) |
| アリババクラウド / 共有仮想ホスト(Nginx) | NGINX 設定に 1 行 の try_files を貼る(下記) |
| Yikai Panel(易开面板・Windows ローカル) | 設定不要——Nginx 用の YikaiCMS ルールを内蔵、Apache では同梱の .htaccess を使用 |
| Apache / 一般的な共有ホスト | 設定不要——.htaccess 同梱 |
| 自前の Nginx サーバー | try_files 1 行;静的配信には完全ルール(下記) |
Nginx 疑似静的化の設定
✓ 推奨:同梱ルールを include(セキュリティ遮断を含む)
BT / aaPanel 等:サイトのリライト設定にこの 1 行だけを書きます(パスはサイトのディレクトリに置き換え)。同梱の deploy/nginx-baota.conf にはルーティングと機密ディレクトリの遮断が含まれ、アップグレード時に自動更新されます。
include /www/wwwroot/サイトディレクトリ/deploy/nginx-baota.conf;
⚠ 「wordpress」プリセットだけにしない
try_files 1 行だけのルールは、ディスク上に実在するファイルをそのまま返します。SQLite サイトのデータベース storage/database.sqlite はサイトディレクトリ内にあるため、だれでもダウンロードできてしまいます。設定後、ブラウザで /storage/database.sqlite を開き、403 または 404 になることを確認してください。
server ブロックを手書きする場合は、次の 2 つを追加してください(1 つ目で機密ディレクトリを遮断。必ず先に置く):
location ~* ^/(config|storage|vendor|includes|install/sql|bin|migrations|recipes)(/|$) {
return 403;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
上級者向け:完全ルール(静的 HTML 直接配信、最高性能)
root 権限がある場合は完全ルールを使用:生成済みの .html を Nginx が直接返し PHP を経由しません。server ブロックに統合(上記 1 行の代わり):
location ~ ^/detail/(\d+)\.html$ { rewrite ^ /detail.php?id=$1 last; }
location ~ ^/case/(\d+)\.html$ { rewrite ^ /detail.php?id=$1 last; }
location ~ ^/case/([a-z0-9_-]+)\.html$ { rewrite ^ /detail.php?slug=$1 last; }
location ~ ^/list/(\d+)\.html$ { rewrite ^ /list.php?id=$1 last; }
location ~ ^/list/(\d+)/page/(\d+)\.html$ { rewrite ^ /list.php?id=$1&page=$2 last; }
location ~ ^/([a-z0-9_-]+)/page/(\d+)\.html$ { rewrite ^ /list.php?slug=$1&page=$2 last; }
location ~ ^/product/(\d+)\.html$ { rewrite ^ /product.php?id=$1 last; }
location ~ ^/product/([a-z0-9_-]+)/page/(\d+)\.html$ { rewrite ^ /list.php?slug=product&cat=$1&page=$2 last; }
location ~ ^/product/([a-z0-9_-]+)\.html$ { rewrite ^ /list.php?slug=product&cat=$1 last; }
location ~ ^/job/(\d+)\.html$ { rewrite ^ /job_detail.php?id=$1 last; }
location ~ ^/([a-z0-9_-]+)/([a-z0-9_-]+)\.html$ { rewrite ^ /page.php?parent=$1&slug=$2 last; }
location ~ ^/([a-z0-9_-]+)\.html$ { rewrite ^ /page.php?slug=$1 last; }
location / { try_files $uri $uri/ /index.php?$query_string; }
Apache 疑似静的化の設定
Apache 環境では、YikaiCMS に .htaccess ファイルが付属しており、インストール後に自動的に有効になるため、追加の設定は不要です。Apache で mod_rewrite モジュールが有効になっていることを確認してください。
疑似静的化が機能しない場合は、以下の点を確認してください:
- Apache 設定で
AllowOverride Allが有効になっている mod_rewriteモジュールが読み込まれている(a2enmod rewrite).htaccessファイルがサイトのルートディレクトリに存在する
Alibaba Cloud 拡張版共有ホスティング
Alibaba Cloud 拡張版 Linux 共有ホスティングは Nginx エンジンを使用しており、.htaccess をサポートしません。ホスティングのコントロールパネルで疑似静的化ルールを個別に設定する必要があります。
設定手順
- クラウド共有ホスティング管理ページにログインする
- 対象のホストを見つけ、管理をクリックする
- 左側のナビゲーション:高度な環境設定 → NGINX 設定
- テキストボックスに下記の設定内容を貼り付ける
- 設定を保存をクリックする
✓ 推奨:最小ルール(機密ディレクトリの遮断を含む)
パネル既定の location / {} と location ~ /\.ht {deny all;} を、下の内容にまとめて置き換えます。最初の 2 つはデータベースがある storage/ などを保護するため省略できません。設定後 /storage/database.sqlite が 403 または 404 になることを確認してください。より完全な版(アップロード内 PHP の遮断など)はパッケージの deploy/aliyun-nginx-minimal.txt にあります。
location ~ ^/(config|storage|vendor|includes|install/sql|bin|migrations|recipes)/ {
deny all;
}
location ~ /\.(git|env|htaccess|htpasswd) {
deny all;
}
location / {
if (!-e $request_filename) {
rewrite ^ /index.php last;
}
}
上級者向け:完全ルール(静的 HTML 直接配信が必要な場合のみ)
この仮想ホストは location 内の限られたディレクティブのみ対応のため、すべて 1 つの location / に記述(上の機密ディレクトリ遮断の 2 つは残し、location / だけを置き換え):
location / {
rewrite ^/detail/(\d+)\.html$ /detail.php?id=$1 last;
rewrite ^/case/(\d+)\.html$ /detail.php?id=$1 last;
rewrite ^/case/([a-z0-9_-]+)\.html$ /detail.php?slug=$1 last;
rewrite ^/list/(\d+)\.html$ /list.php?id=$1 last;
rewrite ^/list/(\d+)/page/(\d+)\.html$ /list.php?id=$1&page=$2 last;
rewrite ^/([a-z0-9_-]+)/page/(\d+)\.html$ /list.php?slug=$1&page=$2 last;
rewrite ^/product/(\d+)\.html$ /product.php?id=$1 last;
rewrite ^/product/([a-z0-9_-]+)/page/(\d+)\.html$ /list.php?slug=product&cat=$1&page=$2 last;
rewrite ^/product/([a-z0-9_-]+)\.html$ /list.php?slug=product&cat=$1 last;
rewrite ^/job/(\d+)\.html$ /job_detail.php?id=$1 last;
rewrite ^/([a-z0-9_-]+)/([a-z0-9_-]+)\.html$ /page.php?parent=$1&slug=$2 last;
rewrite ^/([a-z0-9_-]+)\.html$ /page.php?slug=$1 last;
try_files $uri $uri/ /index.php?$args;
}
location / { } に置き換えれば復旧できます。
/works/16.html)がある場合は、try_files の前に対応する rewrite ルールを追加してください。より具体的なルールはより一般的なルールの前に置きます。
URL 対応表
| 疑似静的 URL | 実際のリクエスト | 説明 |
|---|---|---|
/detail/16.html | /detail.php?id=16 | コンテンツ詳細ページ |
/case/16.html | /detail.php?id=16 | 事例詳細ページ |
/about.html | /page.php?slug=about | 単一ページ |
/news.html | /page.php?slug=news | チャンネル一覧 |
/news/page/2.html | /list.php?slug=news&page=2 | 一覧ページネーション |
/product/phone.html | /list.php?slug=product&cat=phone | 製品カテゴリー |
/product/16.html | /product.php?id=16 | 製品詳細 |
/job/1.html | /job_detail.php?id=1 | 求人詳細 |
/about/team.html | /page.php?parent=about&slug=team | 第 2 階層ページ |