关于 kuroco-server-processing
面向 Kuroco 开发者的服务端处理技能,涵盖 Smarty 模板、Webhook、批处理和外部集成,并结合插件参考与 API、触发器实现模式。
主要功能
- 01Smarty 插件参考
- 02模板语法与示例
- 03批处理和触发器模式
- 04内部与外部 API 调用
- 05Webhook 与服务集成指南
适用场景
- 01查找模板任务所需的 Smarty 插件
- 02规划定时数据导入或导出
- 03选择外部 API 集成方式
MCP 相关
该技能提到可用 `/kuroco-docs` 技能搜索和参阅 Kuroco 官方文档;未说明 MCP 服务功能。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ diverta/ kuroco-skills --skill kuroco-server-processing安装后在 Claude Code 中输入/kuroco-server-processing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlreferences/all-plugins.mdapi-plugins.mdarray-plugins.mdauth-plugins.mdexamples.mdfile-plugins.mdform-plugins.mdintegration-design.mdintegration-plugins.mdintegrations.mdstring-plugins.mdsyntax.mdvue-plugins.md详细介绍
Kuroco サーバーサイド処理
KurocoのSmartyテンプレートプラグインリファレンスおよびWebhook・バッチ処理パターン。
ドキュメント参照: /kuroco-docs スキルを使用してKuroco公式ドキュメントを検索・参照できます。
目次
Part 1: Smartyプラグインリファレンス
- よく使うプラグイン
- プラグイン種別(関数・修飾子・ブロック)→ references/syntax.md
- カテゴリ別リファレンス
- 使用例(一覧表示・Slack通知・権限表示・エラー処理・ページング)→ references/examples.md
- Smarty構文リファレンス - 基本構文、制御構造、組み込み変数
Part 2: Webhook・バッチ処理パターン
- バッチ処理
- 内部API呼び出し
- 外部システム連携の方式設計 → 深掘りは references/integration-design.md
- 外部API呼び出し
- トリガー処理
- Webhook(受信エンドポイント・URL 形式)→ references/integrations.md
- 外部サービス連携 → 詳細は references/integrations.md
Part 1: Smartyプラグインリファレンス
KurocoのSmartyテンプレートで使用可能な全プラグインの完全リファレンス。
よく使うプラグイン
変数・データ操作
| プラグイン | 説明 | 例 |
|---|---|---|
assign | 変数代入。var はドット区切りで入れ子の配列に書ける | {assign var="request.status" value="pending"} |
append | 配列追加。キーが変数のときはこちら | {append var="arr" index=$key value="値"} |
json_decode | JSONパース | {$json|json_decode:true} |
rcms_json_encode | JSONエンコード | {$arr|@rcms_json_encode} |
API・データ取得
| プラグイン | 説明 | 例 |
|---|---|---|
api_internal | 内部API呼び出し | {api_internal endpoint='/rcms-api/1/news' var='result'} |
api_method | エンドポイントを作らずモデルのオペレーションを直接実行(GETのみ) | {api_method var='result' model='Topics' method='list' ...} |
assign_tag_list | タグ一覧取得 | {assign_tag_list var='tags'} |
→ 詳細: references/api-plugins.md
文字列処理
| プラグイン | 説明 | 例 |
|---|---|---|
escape | エスケープ | {$html|escape} |
truncate | 文字列切り詰め | {$text|truncate:100:"..."} |
mb_truncate | マルチバイト対応 | {$text|mb_truncate:50} |
date_format | 日付フォーマット | {$date|date_format:"%Y-%m-%d"} |
translate | 翻訳 | {$key|translate} |
nl2br | 改行をBRに | {$text|nl2br} |
replace | 文字列置換 | {$text|replace:"a":"b"} |
→ 詳細: references/string-plugins.md
フォーム・UI
| プラグイン | 説明 | 例 |
|---|---|---|
fileupload | ファイルアップロード | {fileupload id="photo" hidden_nm="photo_url" url=$upload_url}{/fileupload} |
inquiry_input | フォーム入力 | {inquiry_input col="name" ...} |
pager | ページネーション | {pager info=$pageInfo} |
→ 詳細: references/form-plugins.md
認証・権限
| プラグイン | 説明 | 例 |
|---|---|---|
rcms_auth | 権限制御ブロック | {rcms_auth target="read:/topics/"}...{/rcms_auth} |
login | ログイン処理 | {login ...} |
logout | ログアウト処理 | {logout ...} |
→ 詳細: references/auth-plugins.md
外部サービス連携
| プラグイン | 説明 | 例 |
|---|---|---|
sendmail | メール送信 | {sendmail to=$email subject="件名" contents="本文"} |
slack_post_message | Slack通知 | {slack_post_message channel="#general" text="..."} |
ai_completion | AI呼び出し | {ai_completion var='result' message=$prompt model='gpt-4'} |
github_deploy | GitHubデプロイ | {github_deploy ...} |
→ 詳細: references/integration-plugins.md
ファイル操作
| プラグイン | 説明 | 例 |
|---|---|---|
write_file | ファイル書き込み | {write_file var="path" value="内容"} |
put_file | ストレージアップロード | {put_file path="/files/..." tmp_path=$tmp} |
read_file | ファイルを1行ずつ読み込み(ブロック) | {read_file name="log" path="/files/user/..." row="line"}{$line}{/read_file} |
read_dir | ディレクトリ読み込み | {read_dir name="files" path="/files/user/..." file_var='file'}...{/read_dir} |
→ 詳細: references/file-plugins.md
Vue.js 集成
| 插件 | 说明 | 示例 |
|---|---|---|
rcms_vue_component | Vue 组件 | {rcms_vue_component config="rcms-mng" name="..."} |
head_include | 添加到 head | {head_include file="..."} |
→ 详情:references/vue-plugins.md
分类参考
| 类别 | 文件 | 主要插件 |
|---|---|---|
| 语法参考 | syntax.md | 基本语法、控制结构、内置变量、最佳实践 |
| API・数据获取 | api-plugins.md | api_internal, api_method, assign_tag_list |
| 字符串处理 | string-plugins.md | escape, truncate, date_format, translate |
| 数组操作 | array-plugins.md | count, in_array, implode, explode, sort 系列 |
| 表单・UI | form-plugins.md | fileupload, inquiry_input, pager, html_* |
| 认证・权限 | auth-plugins.md | rcms_auth, login, logout |
| 外部集成 | integration-plugins.md | sendmail, slack_*, ai_completion |
| 文件操作 | file-plugins.md | write_file, put_file, read_file, read_dir |
| Vue.js 集成 | vue-plugins.md | rcms_vue_component, head_include |
| 所有插件 | all-plugins.md | 全部 151 个插件列表 |
第 2 部分:Webhook・批处理模式
Kuroco HeadlessCMS 中有关 Webhook、批处理和外部集成的最佳实践。
关于 Smarty 语法:批处理和触发器使用 Smarty 模板编写。语法和插件详情请参阅上文第 1 部分。
批处理
概述
批处理是按固定时间间隔自动执行的处理。
执行频率选项:
| 频率 | 用途 |
|---|---|
| 每 15 分钟 | 需要频繁同步时 |
| 每 30 分钟 | 准实时处理 |
| 每小时 | 定期汇总・更新 |
| 每天(指定时间) | 每日报告、备份 |
免费用户的执行限制:选择卡片付款但尚未登记卡片的网站,批处理启动(登记)次数限制为每小时 100 次。计数的是批处理启动次数,而不是批处理中发出的请求数(向外部发送
{api}的次数另计,每小时 1,000 次)。已登记卡片或采用发票付款则不受限制。单次批处理的执行时间上限默认是 4 小时,Smarty 批处理为 6 小时——超出后会因超时而失败。处理大量数据时,与其占满此时限,不如按照后文的“超时对策”进行分页拆分,缩短单次执行时间。
使用场景
- 生成 CSV 并与外部系统集成
- 从外部系统导入数据
- 汇总日志・计算统计数据
- 定期发送邮件
- 集成 GitHub Actions(部署触发器)
创建批处理
管理界面:[运维] → [批处理] → [添加]
| 项目 | 说明 | 示例 |
|---|---|---|
| 标题 | 批处理名称 | CSV 导出批处理 |
| 标识符 | 唯一标识符(字母数字) | csv_export |
| 执行频率 | 执行间隔 | 每天 03:00 |
| 执行内容 | 使用 Smarty 语法编写 | 请参阅下文 |
调用内部 API
基本语法
{api_internal
endpoint='/rcms-api/1/news'
method='GET'
member_id=1
queries=$queries
var='response'
}
获取内容列表
{assign var="queries" value=$dataSet.emptyArray}
{append var="queries" index="cnt" value=0}
{append var="queries" index="filter" value="topics_flg = 1"}
{api_internal
endpoint='/rcms-api/1/news'
method='GET'
member_id=1
queries=$queries
var='news_list'
}
{foreach from=$news_list.list item="news"}
ID: {$news.topics_id}, タイトル: {$news.subject}
{/foreach}
创建内容
POST 请求正文也通过 queries 传递(不存在名为 body 的参数)。
{assign var="body" value=$dataSet.emptyArray}
{append var="body" index="subject" value="タイトル"}
{append var="body" index="contents" value="本文"}
{append var="body" index="open_flg" value=1}
{api_internal
endpoint='/rcms-api/1/news/insert'
method='POST'
member_id=1
queries=$body
var='result'
}
更新(/update/{topics_id})也采用相同形式,只需将要更改的键放入 queries。扩展字段使用 ext_slug 名称作为键(未设置时采用 ext_1 / ext_col_01 格式)——关于键名的确认和 bulk_upsert,请参阅 /kuroco-api-content。
外部系统集成方式设计
连接外部系统前,先决定采用以下 3 种模式中的哪一种(选择标准与 /kuroco-app-builder 的 0-4 相同)。
| 模式 | 架构 | 适用场景 |
|---|---|---|
| 直接调用 | 前端直接调用外部 API。Kuroco 不参与 | 外部 API 已允许 CORS、密钥可以放在前端、优先考虑实时性 |
| 代理(经由 Kuroco) | 从自定义端点的 Smarty 模板中通过 {api} 插件调用外部 API,并返回结果 | 希望隐藏密钥、将认证/CORS/速率限制统一交由 Kuroco 处理、需要加工响应 |
| 导入 | 预先将外部数据导入 Topics/CSV 表,通过标准 Topics API 提供 | 更新频率较低、希望外部数据也能使用 Kuroco 标准功能(搜索、缓存、多语言) |
判断标准:
- 是否需要保密密钥? → 如果需要,选择代理或导入。直接调用时,前端 JS 可以读取密钥,因此不能用于非公开密钥
- 是否需要实时性? → 需要时选择代理,可以接受延迟时选择导入
- 是否希望外部数据也能使用 Kuroco 标准功能(搜索、分类、缓存、多语言)? → 如果希望,选择导入
- 爬虫不适合轮询结构化 API(适用于抓取网页和文件进行导入,抓取本身会计入请求费用)。要定期获取结构化 API 时,即使选择导入,也应使用批处理+
{api} - 向外部发送通知(Slack / LINE / SMS / 邮件)不属于上述 3 种模式。从触发器处理调用集成插件,或发送到触发器邮件地址即可(→ 外部服务集成)
如果对方提供 REST API,通常不会卡在“能否通过 {api} 连接”这个问题上。设计重点应放在 (1) 机密信息的存放位置({secret}) 和 (2) 令牌的生命周期管理。选择后的确认事项——{api} 的限制(每次 1 个文件,timeout 默认 30 秒、最长 3600 秒;自定义端点本身会在 30 秒后终止)、批处理/爬虫/Webhook 的适用情况、每次获取 OAuth 令牌(JIT)还是保存到受保护的 Topics 记录中、Instagram 长期令牌会在 60 天后失效等实际案例中的陷阱,以及设计成果模板——汇总在 references/integration-design.md 中。选择代理或导入时,请在实现前阅读(只需要了解语法时,可以继续阅读下一节)。关于通过代理将结果返回前端的写法,请参阅代理端点的返回方式。
外部API呼び出し
外部APIの呼び出しには {api} プラグインを使う({api_internal}はKuroco自身のAPIを呼ぶ別プラグインなので混同しない。api_requestという名前のプラグインは存在しない)。
基本構文
{api
endpoint='https://api.example.com/endpoint'
method='GET'
headers=$headers
var='response'
status_var='status'
}
POSTリクエスト例(JSON)
headersは'Key: value'形式の文字列を並べた配列で指定する。JSONボディはjson_bodyに渡す。
{secret var='api_key' key='EXAMPLE_API_KEY'}
{assign_array var=headers values=""}
{append var=headers value='Content-Type: application/json'}
{append var=headers value="Authorization: Bearer `$api_key`"}
{assign_array var=body values=""}
{append var=body index='message' value='Hello'}
{api
endpoint='https://api.example.com/post'
method='POST'
headers=$headers
json_body=$body|@json_encode
json_var='response'
status_var='status'
}
非JSON(例: CSV)を送る場合
body属性を使う。JSON以外の内容でも、マルチバイト文字をエスケープするため|@json_encodeを通す必要がある。Content-Typeヘッダーはtext/***形式で明示する。
{assign_array var=headers values=""}
{append var=headers value='Content-Type: text/csv'}
{assign var=csv value="ID,NAME,PRICE\n1,apple,150\n2,orange,200"}
{api
endpoint='https://api.example.com/upload'
method='PUT'
headers=$headers
body=$csv|@json_encode
var='response'
status_var='status'
}
主なパラメータ
| パラメータ | 内容 |
|---|---|
endpoint | 呼び出し先URL(必須) |
query / queries | クエリ文字列 / クエリパラメータ配列(URL に直接書いてもよい) |
method | GET/POST/PUT/PATCH/DELETE/PURGE/HEAD |
headers | 'Key: value'形式の文字列配列 |
json_body / body | JSON / 非JSONのリクエストボディ |
files | 送信ファイル。1回の呼び出しで送れるのは1ファイルのみ(配列の2件目以降は無視される) |
var / json_var | レスポンス格納変数。JSON を返す API には json_var を使う(デコード済みの配列で受け取れる。var は生文字列) |
status_var | 成否(0/1) |
http_code_var / resp_header_var | HTTP ステータスコード / レスポンスヘッダーの格納変数 |
timeout | タイムアウト秒数。既定 30、指定できるのは 1〜3600(範囲外はエラー)。遅い外部 API なら明示的に伸ばすか、取り込み(バッチ)に倒す |
cache_time | キャッシュ時間(分)。相手 API への往復を減らす。Kuroco 側エンドポイントのキャッシュ(Kuroco の API リクエスト課金を減らす)とは目的が別で、併用できる |
sslcert / sslkey / cainfo | mTLS用の証明書・鍵・CA情報。値は証明書そのものではなくシークレットのキー名 |
外部APIキーなど秘匿すべき値は**{secret}プラグイン**([環境設定]→[シークレット]で事前に登録)で読み出す。$smarty.const.*(サイト定数)は非秘匿の設定値向けで、APIキー等の秘匿情報には使わない。
{secret var='api_key' key='EXAMPLE_API_KEY'}
{assign_array var=headers values=""}
{append var=headers value="Authorization: Bearer `$api_key`"}
{api
endpoint='https://api.example.com/endpoint'
headers=$headers
var='response'
}
プロキシエンドポイントの返却(カスタム処理)
request_api / request_api_post のカスタムエンドポイントは、既定ではテンプレートで assign した data 変数を {"data": …} の形で返す。1リクエストの PHP 実行時間は30秒(API エントリの set_time_limit(30))なので、プロキシで {api} を呼ぶときは timeout を30未満(例: 10)にする——既定の30秒のままだと外部待ちの途中で先にエンドポイント側が打ち切られる。任意の形の JSON をそのまま返したいときはエンドポイント設定の show_contents を有効にし、テンプレートが JSON 文字列を出力する(出力が空なら []、不正な JSON なら Contents JSON error)。リクエストパラメータは $smarty.request.*(GET/POST 共通)や $smarty.post.* で受け、外部 URL に埋める前に検証する。
{assign var=city value=$smarty.request.city|default:"tokyo"}
{secret var='weather_key' key='WEATHER_API_KEY'}
{assign_array var=headers values=""}
{append var=headers value="X-Api-Key: `$weather_key`"}
{api
endpoint="https://api.weather.example/today?city=`$city`"
method='GET'
headers=$headers
json_var='forecast'
status_var='ok'
timeout=10
cache_time=30
}
{if $ok == 1}
{assign var='data' value=$forecast}
{else}
{logger msg1="weather-proxy-error" msg2="city=`$city`"}
{assign_array var=err values=""}
{append var=err index='error' value='weather_unavailable'}
{assign var='data' value=$err}
{/if}
{* 既定はこれで {"data": …} が返る。show_contents を有効にした場合は代わりに {$data|@rcms_json_encode} を出力する *}
トリガー処理
コンテンツ更新時のトリガー
管理画面: [コンテンツ定義] → [トリガー設定]
利用可能なイベント:
| イベント | タイミング |
|---|---|
| 作成時 | コンテンツ新規作成後 |
| 更新時 | コンテンツ更新後 |
| 削除時 | コンテンツ削除後 |
| 公開時 | 公開ステータス変更時 |
| プレビューサイト送信後 | プレビューサイト(ステージサイト)への送信処理完了後 |
利用可能な変数:
{$topics.topics_id} {* コンテンツID *}
{$topics.subject} {* タイトル *}
{$topics.contents} {* 本文 *}
{$topics.ymd} {* 公開日 *}
{$topics.ext_col_01} {* 拡張項目 *}
フォーム送信時のトリガー
管理画面: [フォーム] → [トリガー設定]
{$inquiry.inquiry_id} {* 回答ID *}
{$inquiry.name} {* 名前 *}
{$inquiry.email} {* メールアドレス *}
{$inquiry.message} {* メッセージ *}
外部サービス連携
詳細な連携パターン: references/integrations.md(GitHub Actions / Slack / Chatwork / メール / SendGrid / Webhook / カスタム処理)。LINE・SMS・X はトリガーメールアドレスのみで、references に追加情報は無い
トリガーメールアドレス(メール送信を契機とした連携)
メールの送信先に専用アドレスを指定すると、メール送信を契機に外部サービスへの送信やバッチ処理・AIエージェントの起動ができます。契機になるメールは、トリガー処理の {sendmail}、フォームの自動返信・管理者通知メールの宛先、メルマガのいずれでもよい——コードを書かずに済む宛先設定を先に検討する。
前提: 各宛先は対象チャネルの連携設定が有効になっている必要がある(LINE は [チャネル]→[メッセージング]→[LINE] にトリガーメールアドレスが表示される。Slack はサイト設定の Slack 連携)。ローカル部(@より前)は Slack=チャンネルID または #チャンネル名、LINE=送信先の LINE ユーザーID(公式アカウントの友だち追加 Webhook か LINE ログイン(OAuth SSO)で取得して会員に保存しておく——kuroco-docs の LINE 連携チュートリアル)、SMS=電話番号。送れるのはメール本文のテキスト(LINE は [emoji:…] 記法の絵文字も可)。
| 宛先アドレス | 動作 |
|---|---|
{channel}@slack.r-cms.jp | Slack送信 |
{twitter_id}@tweets.twitter.r-cms.jp | X(Twitter)投稿 |
{batch_id}@batch.r-cms.jp | バッチ処理の起動 |
{ai_agent_id}@agent.r-cms.jp | AIエージェントの起動 |
{LINE ID}@text.line.r-cms.jp | LINE送信 |
{tel}@twilio.r-cms.jp | テキストメッセージ(SMS)送信(Twilio) |
Slack通知
プラグイン名は slack_post_message(slack_send というプラグインは存在しない)。webhook URLではなく、サイト設定のSlack連携(slack_bot_token)を使う。
{slack_post_message
channel="#general"
text="通知メッセージ"
}
メール通知
本文のパラメータ名は contents(body ではない)。
{sendmail
to="[email protected]"
subject="件名"
contents="本文"
}
GitHub Actions連携
{secret var='github_token' key='GITHUB_TOKEN'}
{assign_array var=headers values=""}
{append var=headers value="Authorization: token `$github_token`"}
{append var=headers value='Accept: application/vnd.github.v3+json'}
{assign_array var=body values=""}
{append var=body index='event_type' value='kuroco-update'}
{api
endpoint='https://api.github.com/repos/owner/repo/dispatches'
method='POST'
headers=$headers
json_body=$body|@json_encode
var='response'
status_var='status'
}
ベストプラクティス
- 実行時間: システム負荷の低い時間帯(深夜・早朝)に設定し、大量データは1日1回・ページング分割で処理する(
{while}でページを回す例: references/examples.md) - エラーハンドリング:
errorsは空でも truthy にならないよう|@count > 0で判定し、{logger}(msg1〜msg4、各1KB以内)とslack_post_messageで通知する(例: references/examples.md) - 途中終了のタグは無い。 失敗時に「以降を実行しない」は、書き込み部分を
{if $status == 1}…{/if}(またはerrors|@count == 0)で囲んで表現する - 動的なエンドポイントパスはバッククォートで補間する。
{id}のような波かっこをそのまま書くと Smarty タグとして解釈される - 短縮代入
{$var = ...}は無い。 変数タグに続く引数はコンパイラが読まずに捨てるため、保存も実行も成功したまま代入だけが消える。値の書き込みは{assign}か{append}を使う(references/syntax.md)
{api_internal endpoint="/rcms-api/3/product/update/`$row.topics_id`" method='POST' member_id=1 queries=$body var='res' status_var='ok'}
関連スキル
/kuroco-api-content- API設計・認証パターン、コンテンツCRUD操作/kuroco-admin-mcp- Admin MCP経由の管理操作
関連ドキュメント
../kuroco-docs/docs/tutorials-api-custom-1.md(how-to-use-batch) - バッチ処理の使い方../kuroco-docs/docs/tutorials-content-1.md(auto-run-github-with-contents-update) - GitHub Actions連携../kuroco-docs/docs/tutorials-form-mail-1.md(send-slack-notification-after-a-form-has-been-submitted) - Slack通知../kuroco-docs/docs/reference-smarty-trigger-3.md(trigger-variables) - トリガー変数