Discord Php Interactions
discord-php/DiscordPHP
Build DiscordPHP slash commands and message components — global command trees with subcommands, user- AND guild-installable commands usable in DMs / group DMs / guild channels, Components V2…
baserCMS 5系(CakePHP 5ベース)のプラグインを新規開発・改修する際の正本パターン集。「プラグインを作成」「bcplugin で bake」「管理画面を追加」「Table/Entity の書き方」「initialize でアソシエーション宣言」「validationDefault」「fetchTable と TableRegistry の使い分け」「BcAdminForm /…
$ npx skills add baserproject/basercms --skill basercms5-plugin-development -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install baserproject/basercms basercms5-plugin-development --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/baserproject/basercms.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/basercms5-plugin-development .claude/skills/basercms5-plugin-development && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "basercms5-plugin-development" agent skill from https://github.com/baserproject/basercms/tree/5.4.x/.agents/skills/basercms5-plugin-development into .claude/skills/basercms5-plugin-development/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "basercms5-plugin-development", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/baserproject/basercms/tree/5.4.x/.agents/skills/basercms5-plugin-developmentType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add baserproject/basercms --skill basercms5-plugin-development -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install baserproject/basercms basercms5-plugin-development --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/baserproject/basercms.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/basercms5-plugin-development .agents/skills/basercms5-plugin-development && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "basercms5-plugin-development" agent skill from https://github.com/baserproject/basercms/tree/5.4.x/.agents/skills/basercms5-plugin-development into .agents/skills/basercms5-plugin-development/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "basercms5-plugin-development", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add baserproject/basercms --skill basercms5-plugin-development -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install baserproject/basercms basercms5-plugin-development --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/baserproject/basercms.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/basercms5-plugin-development .cursor/skills/basercms5-plugin-development && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "basercms5-plugin-development" agent skill from https://github.com/baserproject/basercms/tree/5.4.x/.agents/skills/basercms5-plugin-development into .cursor/skills/basercms5-plugin-development/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "basercms5-plugin-development", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/baserproject/basercms.git --path .agents/skills/basercms5-plugin-development--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add baserproject/basercms --skill basercms5-plugin-development -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install baserproject/basercms basercms5-plugin-development --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/baserproject/basercms.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/basercms5-plugin-development .gemini/skills/basercms5-plugin-development && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "basercms5-plugin-development" agent skill from https://github.com/baserproject/basercms/tree/5.4.x/.agents/skills/basercms5-plugin-development into .gemini/skills/basercms5-plugin-development/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "basercms5-plugin-development", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install baserproject/basercms basercms5-plugin-developmentInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add baserproject/basercms --skill basercms5-plugin-development -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/baserproject/basercms.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/basercms5-plugin-development .github/skills/basercms5-plugin-development && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "basercms5-plugin-development" agent skill from https://github.com/baserproject/basercms/tree/5.4.x/.agents/skills/basercms5-plugin-development into .github/skills/basercms5-plugin-development/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "basercms5-plugin-development", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add baserproject/basercms --skill basercms5-plugin-development -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install baserproject/basercms basercms5-plugin-development --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/baserproject/basercms.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/basercms5-plugin-development .opencode/skills/basercms5-plugin-development && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "basercms5-plugin-development" agent skill from https://github.com/baserproject/basercms/tree/5.4.x/.agents/skills/basercms5-plugin-development into .opencode/skills/basercms5-plugin-development/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "basercms5-plugin-development", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
basercms5-plugin-developmentbaserCMS 5系(CakePHP 5ベース)のプラグインを新規開発・改修する際の正本パターン集。「プラグインを作成」「bcplugin で bake」「管理画面を追加」「Table/Entity の書き方」「initialize でアソシエーション宣言」「validationDefault」「fetchTable と TableRegistry の使い分け」「BcAdminForm /…
Basercms5 Plugin Development is an agent skill from baserproject/basercms. baserCMS 5系(CakePHP 5ベース)のプラグインを新規開発・改修する際の正本パターン集。「プラグインを作成」「bcplugin で bake」「管理画面を追加」「Table/Entity の書き方」「initialize でアソシエーション宣言」「validationDefault」「fetchTable と TableRegistry の使い分け」「BcAdminForm / control() の書き方」「検索フォーム element」「control の id/name 生成規則と JS 連携」「イベントリスナー(BcModelEventListener 等)」「adminNavigation の登録」「setting.php / config.php」「BcShortCode 登録」「paginate($query)」「redirect は return」「ids で belongsToMany 保存」「BcKeyValue」「afterSave の再入ガード」「$.bcUtil.adminBaseUrl」「Time::format の ICU パターン」「routes.php の…
Its SKILL.md is about 4.9k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Agent Workflows, covering Hooks and plugins. It works with PHP. The repository describes itself as: baserCMS : Based Website Development Project. The licence is MIT.
9 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 748b4f6. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
composernpmnpxFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npm and npx, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Basercms5 Plugin Development loads about 4.9k tokens when it runs. Until then it costs about 182 tokens; SKILL.md has 981 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from baserproject/basercms at commit 748b4f6, republished under its MIT licence (© baserproject). 981 words, ~4,863 tokens.
.claude/skills/basercms5-plugin-development/SKILL.md (or your agent's skills folder).baserCMS 5系(CakePHP 5ベース)でプラグインを新規開発・改修するときのコーディングパターンを機能別にまとめたもの。環境・ディレクトリ構成・命名規則・コアハック禁止(vendor/baserproject・vendor/cakephp は読み取り専用)などの共通ルールは basercms5-development、テーマ(templates 中心)の開発は basercms5-theme-development、4系からの移行作業は basercms-plugin-4-to-5-upgrade、テストの実行・基盤導入は basercms-unittest、bc-custom-content(カスタムコンテンツ)を使った開発は basercms5-custom-content-development を参照する。
bin/cake bake bc_plugin {PluginName} でプラグイン雛形、bin/cake bake bc_all {ModelName} --plugin {PluginName} で Table/Entity/Controller/テンプレート一式を生成できる。既存プラグインへのテスト基盤の後付け手順は basercms-unittest を参照。src/{PluginName}Plugin.php — プラグインクラスsrc/Controller/(フロント)・src/Controller/Admin/(管理画面)src/Model/Table/・src/Model/Entity/src/View/Helper/・src/Event/(イベントリスナー。置くだけで自動 attach される)config/(config.php・setting.php・routes.php・Migrations/)templates/(フロント)・templates/Admin/(管理画面。検索フォームは templates/Admin/element/search/)webroot/(js/css/img。Vue ソースは webroot/js/src)class SamplePlugin extends \BaserCore\BcPlugin と書く。install(array $options = []): bool は return parent::install($options); を基本とし、bootstrap() は**動的な設定(実行時に決まる値の Configure 追加、ログ設定の登録など)**にのみ使う。bootstrap() に分離する。// config/setting.php
return [
'BcApp' => [...],
'BcShortCode' => ['Sample' => ['Sample.showList']],
];'plugin'・'controller' はいずれも CamelCase で書く('controller' => 'SampleArticles')。snake_case で書くと全管理画面が404になる(メニュー描画時のURL解決に失敗するため対象画面以外も巻き込む)。{controller} セグメントは実際にはプラグイン名をダッシュ区切り(kebab-case)にしたもの(例: BlogTagGroup → /baser/admin/blog-tag-group/{controller}/...)。他プラグインのURLパターンから類推せず、bin/cake routes | grep <PluginName>(大文字小文字を落として検索)で実際のルートを確認してから使う。bc-blog)の管理画面「記事編集」URLは edit/{blogContentId}/{id} の2引数が必須(Admin\BlogPostsController::beforeFilter() が $this->request->getParam('pass.0') をブログコンテンツIDとして要求し、無いと BcException: コンテンツデータが見つかりません。 になる)。記事IDだけの edit/{id} ではアクセスできない。他プラグインが特定ブログ記事の編集画面へリンクを張る場合(例: 追加フィールドプラグインの編集導線)は、edit($blogContentId, $id) のシグネチャ通り両方を渡す。plugins テーブルへ直接 INSERT(status=1)する。DBで有効化されたプラグインは自動で読み込まれるため、composer への登録や composer dump-autoload は不要。phpoffice/phpspreadsheet)は composer require で導入する。雛形アセット(Excel テンプレート等)は templates/Admin/Excel/... に置き、\Cake\Core\Plugin::templatePath('Sample') . 'Admin' . DS . 'Excel' . DS . ... で参照する(templatePath() は末尾スラッシュ付き)。責務分離: バリデーション・ビジネスロジックは Table(src/Model/Table)、行データの振る舞いは Entity(src/Model/Entity)に書く。DB変更は Migration (phinx) を使う。
initialize() で宣言し、エイリアスは複数形にする。className はプラグイン接頭辞付き・複数形で書く。エイリアスは contain()・条件キー・エンティティのプロパティ名すべてに波及する。public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('sample_articles');
$this->addBehavior('BaserCore.BcUpload', [...]);
$this->belongsTo('Users', ['className' => 'BaserCore.Users', 'foreignKey' => 'user_id']);
$this->hasMany('SampleComments', ['className' => 'Sample.SampleComments', 'foreignKey' => 'article_id', 'dependent' => true]);
$this->belongsToMany('SampleTags', [
'className' => 'Sample.SampleTags',
'joinTable' => 'sample_articles_sample_tags',
'foreignKey' => 'article_id',
'targetForeignKey' => 'tag_id',
]);
}dependent は hasMany/hasOne のみ有効。validationDefault() に書く。カスタムルールはシグネチャ ($value, $context) のメソッドを add() で登録する。public function validationDefault(\Cake\Validation\Validator $validator): \Cake\Validation\Validator
{
$validator->notEmptyString('title', 'タイトルを入力してください');
$validator->add('title', 'custom', ['rule' => [$this, 'customMethod'], 'message' => '...']);
return $validator;
}$this->find()->where([...])->contain([...])->orderBy([...])->first()/all()。list は find('list', keyField: 'id', valueField: 'name')。'field IN' => (array)$values と明示する(書かないと Cannot convert value Array 例外)。空配列の IN () は例外になるので、空になりうる場合は先頭でガードして早期 return する。IS 演算子: ['field IS' => null]/否定は ['field IS NOT' => null]。contain() ではなく ->innerJoinWith('Assocs') か matching() を使う(contain は WHERE に使えない)。条件キーは複数形エイリアス(SampleComments.user_id)。常時 join すると関連なし行が除外される点に注意。$entity = $table->newEntity($data);(新規)または $entity = $table->patchEntity($table->get($id), $data);(更新)→ $table->save($entity);。_ids で書く: patchEntity($e, $data + ['sample_tags' => ['_ids' => [$id, ...]]], ['associated' => ['SampleTags']])。表示側は contain(['SampleTags'])。initialize() に $this->addBehavior('BaserCore.BcKeyValue') を足すと saveKeyValue([$key => $value]) が使える。読み出しは find()->where(['name' => $key])->first()->value。func()->sum() + ->first()->alias ?? 0 で書く:$total = $this->find()
->where(['user_id' => $userId])
->select(['total' => $this->find()->func()->sum('amount')])
->first()->total ?? 0;func()->min()/max() は結果が数値型にキャストされて壊れるため、->orderBy(['col' => 'ASC'])->first() で最古/最新行を取り、そのエンティティの日時プロパティを使う。save() に callbacks オプションは存在しない(渡しても黙って無視され afterSave は常に発火する)ため、抑止はフラグで行う。private bool $inAfterSave = false;
public function afterSave(EventInterface $e, EntityInterface $entity, \ArrayObject $o): void
{
if ($this->inAfterSave) return;
$this->inAfterSave = true;
try { /* 他テーブルの save 等 */ } finally { $this->inAfterSave = false; }
}get($id) → delete($entity) で書く(関連の dependent => true が cascade する)。deleteAll() は ORM の cascade を通さず子が孤児として残るので、子を連れて消す削除には使わない。fetchTable() は Controller / Command 専用。Table・Lib・Helper・イベントリスナー内では \Cake\ORM\TableRegistry::getTableLocator()->get('Sample.SampleArticles') を使う(fetchTable を呼ぶと BadMethodCallException)。エイリアスは常に複数形。getControlSource()(フォーム選択肢の供給元)**は Table に定義し、テンプレートからは $this->BcAdminForm->getControlSource('Sample.SampleArticles.user_id') のように Plugin.複数形モデル.field で呼ぶ(単数形だと MissingTableClassException)。disableHydration() を使うと結果はフラット連想配列になる。select には明示エイリアスを付けて(->select(['id' => 'SampleArticles.id', 'tag_name' => 'SampleTags.name']))$row['id'] でフラット参照する。$this->getConnection()->execute($sql)->fetchAll('assoc')(戻りはフラット連想配列)。トランザクションは $this->getConnection()->begin()/commit()/rollback()。\BaserCore\Model\Table\AppTable を継承した SampleAppTable 等)に置き、各 Table はそれを継承する。管理画面コントローラは src/Controller/Admin/ に置き、プラグインの Admin 基底(SampleAdminAppController など、BcAdminAppController を継承)を経由して継承する。
$this->fetchTable('Sample.SampleArticles')(複数形エイリアス)。$this->paginate($query) に渡す(PaginatorComponent は存在しない。loadComponent('Paginator') は MissingComponentException)。必要な関連は contain()、手書き結合は leftJoinWith()/innerJoinWith()/matching()、->groupBy()/->having() も使える。並べ替え・ページはクエリ文字列 ?sort=&direction=&page= で自動処理される。\BaserCore\Utility\BcSiteConfig::get('admin_list_num') で取得する。ログインユーザーは \BaserCore\Utility\BcUtil::loginUser()(未ログイン時は false を返すので ?-> は効かない。(BcUtil::loginUser() ?: null)?->id か明示分岐で書く)。$this->BcMessage->setSuccess('...') / setError('...')。redirect() は必ず return $this->redirect([...]); と書く。redirect は Response を返すだけで後続コードが実行され続けるため、ガード節(引数チェック→リダイレクト)では return しないと直後の処理まで走って TypeError 等になる。例外: initialize()/beforeFilter() など : void 宣言のメソッド内では return を付けない(付けると TypeError)。withQueryParams()/withData() で新しい request を作って setRequest() する。$this->setRequest($this->getRequest()->withQueryParams(
$this->getRequest()->getQueryParams() + ['begin' => $begin]
));getData('key')/getQuery('key')/getParam('key')/getQueryParams()。ajax 判定は $this->getRequest()->is('ajax')。getParam('controller') は CamelCase('SampleArticles')で返る点に注意(分岐で snake_case と比較すると常に false)。public function initialize(array $config): void { parent::initialize($config); } のシグネチャで書き、コントローラ参照は $this->getController() で取得する。使用するコントローラの initialize() で $this->loadComponent('Sample.Excel') のように明示ロードする(自動ロードはされない)。$this->getRequest()->allowMethod(['post', 'delete']) → $entity = $table->get($id)(RecordNotFoundException を try/catch して「無効な処理です」→ index へ)→ $table->delete($entity)。一覧の bca-submit-token 経由の POST を受けるアクションは FormProtection の unlockedActions に登録する(§6)。set() する。旧来のコールバックによる自動注入は無いので、行ごとの計算値は Table の計算メソッド(calcBalance($entity) 等)を paginate 後にループ適用する。プラグイン設定(Configure::read('Sample'))を多数のテンプレートが参照する場合は、プラグインの Admin 基底コントローラの beforeRender() で一括 set する。public function beforeRender(\Cake\Event\EventInterface $event): void
{
parent::beforeRender($event);
$this->set(\Cake\Core\Configure::read('Sample'));
}BcAdminAppController 直継承ではなくこの基底を継承する(直継承だと設定ビュー変数が全画面で欠落する)。throw new \Cake\Http\Exception\BadRequestException(...) / NotFoundException / InternalErrorException。レスポンス操作は $this->setResponse($this->getResponse()->withStatus(400))。$this->setSearch('sample_articles_index') / $this->setHelp('...') で設定する。$this->BcAdminForm を使い、入力は必ず control() で出す(input() は無い)。フロント用 $this->BcForm/$this->Form や素のウィジェット(text()/select()/multiCheckbox())を直接呼ぶと bca-* の管理スタイルが当たらず崩れる。一覧の一括処理(ListTool.batch)・一括選択(ListTool.checkall)・submit()/button() も BcAdminForm で出す。create($entity)、コンテキストレスなら create(null, ['valueSources' => ['data', 'context']]) と書く(GET検索フォームは ['query', 'context'])。文字列モデル名を渡すと No context provider found for value of type string。['multiple' => 'checkbox'] や multiCheckbox() は崩れる):<?php $selected = array_map('strval', (array)$this->getRequest()->getData('SampleArticle.tags')) ?>
<?php foreach($options as $v => $label): ?>
<?php echo $this->BcAdminForm->control('SampleArticle.tags[]', [
'type' => 'checkbox', 'label' => $label, 'value' => $v,
'checked' => in_array((string)$v, $selected, true), 'hiddenField' => false]) ?>
<?php endforeach ?>'field IN' => (array)$values(§2)。control() の label に HTML を渡すときは配列形式 ['text' => '<span...>', 'escape' => false] と書く(文字列だとエスケープされ生表示)。templates/Admin/element/search/{name}.php(単数 search/) に置く。コントローラの setSearch('sample_articles_index') がこのパスを解決する。検索は GET 送信が基本(条件がURLに残りページャ遷移でも保持)で、コントローラは getQueryParams() から条件を読む。入力値の再表示には valueSources に query を含める。control() の DOM 生成規則を把握して JS と整合させる(描画は通るのに JS 連携が無言で死ぬ最頻出ポイント):control('SampleArticle.publish_date') → id="samplearticle-publish-date"(Text::slug による)。Model[field] 形式: name="SampleArticle[publish_date]"。#SampleArticlePublishDate)や別形式の name を掴む設計なら、JS 側を実生成の id/name に合わせるか、control(..., ['id' => 'SampleArticlePublishDate']) で明示 id を振る(その場合 label の for も合わせる。name は POST キーなので変えない)。フォーム全体への委譲 $("#FormId").on('change', 'select, input', ...) にすると id 依存自体をなくせる。control('Model.field.year', ['type' => 'select', 'options' => $years, 'label' => false]) のように自前 options で書く(year()/month() というメソッドは無い)。getData('Model.field') は ['year' =>, 'month' =>] で受かる。Paginator->sort() や element('pagination') を含む一覧 element を、ページネーションしない画面(編集フォームへの埋め込み等)で描画すると You must set a pagination instance using setPaginated() first で落ちる。ページャ系の描画は「専用一覧コントローラのときだけ」に getParam('controller') === 'SampleArticles'(CamelCase)でガードする。new \Cake\Datasource\Paging\PaginatedResultSet(new \ArrayIterator($rows), $params) をビュー変数に set する(PaginatorHelper が PaginatedInterface を自動検出する)。sort カラムはホワイトリストで ORDER BY を組み立てる。$this->BcFormTable->dispatchBefore()/dispatchAfter()、$this->BcAdminForm->dispatchAfterForm() を使う。BcBaser->link() に画像/HTML を渡すときは ['escape' => false]。アイコンボタンは ['class' => 'bca-btn-icon', 'data-bca-btn-type' => 'add', 'data-bca-btn-size' => 'lg'] の作法で書く。リスナーは src/Event/ に置く。プラグインの BcPlugin が自動 attach するため、リスナーが壊れているとイベント発火で即 Fatal になる点に注意して書く。
BaserCore\Utility\BcEvent::registerPluginEvent()(BaserCorePlugin から有効化済み全プラグインに対して呼ばれる)が、src/Event/{Plugin名}{Controller|Model|View|Helper|Mailer}EventListener.php というファイル名と完全一致するクラスだけを自動生成・EventManager::instance()->on() で登録する。例えば <Plugin> プラグインでヘッダーを差し替えるビューイベントリスナーなら、ファイル名は必ず src/Event/<Plugin>ViewEventListener.php、クラス名も <Plugin>ViewEventListener にする(名前が1文字でもズレると静かに登録されず、イベントが一切発火しない)。BcModelEventListener、コントローラ系は BcControllerEventListener、ビュー系は BcViewEventListener、ヘルパ系は BcHelperEventListener を継承する。public $events = [...] に登録する。'SampleArticles.afterSave'(Table 名の複数形)。'BcBlog.BlogPosts.afterSave'(プラグイン名+Table複数形)。名前が実在イベントと一致しないとエラーも出ずに無発火になるため、発火側を grep -rn "dispatchLayerEvent\|createEvent" vendor/baserproject/... して実在するイベント名に合わせる。BcViewEventDispatcher が標準イベントを {Plugin}.{ViewName}.afterRender として再ディスパッチする方式。'BcBlog.Blog.afterRender' のように View の getPlugin()/getName() に一致させる。'BcBlog.BlogPosts.afterSave' → public function bcBlogBlogPostsAfterSave(EventInterface $event)。型ヒントは \Cake\Event\EventInterface。$event->getData('key')、書き込みは $event->setData('key', $v)、サブジェクト(Table/Controller/View)は $event->getSubject()。保存系イベントのエンティティは $event->getData('entity') で取る。TableRegistry::...->get() は MissingTableClassException になる。ハンドラ内で必要になったときに遅延取得する。Model.afterFind というイベントは存在しない。find 結果の加工は formatResults() かカスタム finder に書く。$view->get('varName') を使う($view->viewVars プロパティは無い)。$view->request プロパティも無い(未知プロパティ参照はヘルパの自動ロード扱いとなり xxxHelper could not be found で全画面を巻き込む)ので $view->getRequest()->getParam(...) で書く。$controller->set('x', $v)(request への代入は immutable のため無効)。$.bcUtil.adminBaseUrl(baseUrl + '/' + baserCorePrefix + '/' + adminPrefix + '/'、末尾スラッシュ付き)に連結して書く: $.bcUtil.adminBaseUrl + 'sample/sample_articles/edit/' + id。$ を参照できないので、computed adminBaseUrl() { return $.bcUtil.adminBaseUrl; } を公開し :href="adminBaseUrl + 'sample/...'" と書く。webroot/js/src)を直して webpack で再ビルドする(コンパイル済み .bundle.js/.bundle.css を手で編集しない)。webpack.config.js があれば cd plugins/Sample && npm install && npx webpack。出力は webroot/js/[name].bundle.js、CSS は ../css/[name].bundle.css。再ビルド後に bundle へ反映されたか grep し、ブラウザは Cmd+Shift+R で確認する。return $this->getResponse()->withType('application/json')->withStringBody(json_encode($rows ?: []));。文字列を return しても出力されない。Vue が参照するフィールドはフラット配列に整形して返す。Unexpected field '...' in POST data)。描画時に DOM に無いフィールドは送信トークンに含まれないため、動的フィールドを POST するアクションは beforeFilter() で $this->FormProtection->setConfig('unlockedActions', ['add', 'edit', ...]) に登録する(CSRF は別ミドルウェアなので維持される)。Vue 側の :name は 'Model[' + i + '][field]' 形式で書く(コントローラの getData('Model') で受かる形)。type: [String, Number] のように許容する。ajax レスポンスが JSON でなく文字列になると v-for が文字単位で反復する(Expected Array, got String が1文字ずつ大量に出たらサーバ側エラーを疑う)。$this->Time->format($d, 'yyyy-MM-dd') は ICU パターンで書く(PHP の date() 形式ではない。Y=週年・m=分・M=月なので 'Y-m-d' と書くと月が0になる)。スラッシュ区切りは 'yyyy/MM/dd'、時刻込みは 'yyyy-MM-dd HH:mm'。第2引数を省略すると日時表示になるため、日付のみは必ず指定する。BcTime->format も同様。$v->format('Y/m/d') は PHP の date() 形式(DateTimeInterface::format)。TimeHelper 経由(ICU)と使い分ける。$this->Time->format($e->x, 'yyyy-MM-dd')(helper は null で空文字)か $e->x?->format('Y-m-d') で書く。Number::format() / NumberHelper::format() / currency() は第1引数 null 不可(TypeError)。nullable な値は format($x ?? 0, [...]) / currency($e->budget ?? 0, ...) とガードする。Text::truncate() / BcText::truncate() も第1引数 string 必須。nullable カラムは truncate((string)$e->notes, 46) と (string) キャストする。$this->Number->format($v, ['places' => 0]) で書く(currency() の第2引数は ICU の ISO 通貨コード前提で、未知コードは接頭辞としてそのまま出力される)。config/routes.php は RouteBuilder のクロージャで書く:<?php
use Cake\Routing\RouteBuilder;
return function (RouteBuilder $routes) {
$routes->connect('/sample/*', ['plugin' => 'Sample', 'controller' => 'SampleArticles', 'action' => 'view']);
};Router::getRequest() を routes.php で使う場合は CLI 実行時に null になるため if (!$request) return; のガードを必ず入れる(無いと bin/cake が全コマンド停止する)。'BcShortCode' キーに登録する(§1のコード例参照)。登録元プラグインが無効だと未登録扱いとなり、コンテンツ中の [Sample.showList] がエラーなく生テキストのまま露出する(プラグイン有効化が前提)。.bca-container(flex) 子要素 .bca-main に min-width:0 が無いためページ全体が横スクロールする。その画面の CSS に .bca-main { min-width: 0; } を足し、テーブルは overflow:auto のスクロールラッパーで囲う(position:sticky の列固定もこれで効く)。CSSがバンドル内なら webpack 再ビルド(§6)。テストの実行手順・プラグイン単体(スタンドアロン)テスト基盤の導入・Fixture Factory の書き方は basercms-unittest スキルを正本として参照する。開発時の要点だけ挙げると: 管理画面はログイン付きコントローラ統合テストで GET 描画200+POST フロー(DB 変化の assert)を固定する、描画200は warning を握り潰すのでテスト後に error.log の pristine を確認する、JS 連携がある画面は「JS が期待する DOM id/name が HTML に実在する」assert(§4の番人パターン)を置く、日付保存は値まで assert する(silently NULL を見逃さない)。
© baserproject, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/basercms5-plugin-development of baserproject/basercms.
Open the folder on GitHubat commit 748b4f6
Basercms5 Plugin Development next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Basercms5 Plugin Development this skillbaserproject/basercms | 190 | — | ~4.9k | Automated safety check: Pass | MIT | |
| Discord Php Interactionsdiscord-php/DiscordPHP | 1.1k | — | ~1.5k | Automated safety check: Pass | MIT | |
| Interaction Flow Keeperdiscord-php/DiscordPHP | 1.1k | — | ~1.7k | Automated safety check: Pass | MIT | |
| Wp Plugin Developmentjorgerosal/wordpress-skills | 100 | — | ~12k | Automated safety check: Pass | MIT | |
| Hook Development for Claude Code Pluginsanthropics/claude-plugins-official | 37k | 11 repos | ~4.1k | Automated safety check: Notes | Apache-2.0 | |
| Claude Code Agent Developmentanthropics/claude-plugins-official | 37k | 8 repos | ~2.8k | Automated safety check: Pass | Apache-2.0 |
discord-php/DiscordPHP
Build DiscordPHP slash commands and message components — global command trees with subcommands, user- AND guild-installable commands usable in DMs / group DMs / guild channels, Components V2…
discord-php/DiscordPHP
Maintain interaction flow — Interaction typing, resolved data caching, command routing, autocomplete, modal responses, and interaction builders.
jorgerosal/wordpress-skills
WordPress plugin architecture review and WordPress.org submission standards.
anthropics/claude-plugins-official
Explains how to write Claude Code plugin hooks, both prompt-based checks and bash commands, for events such as PreToolUse, Stop and SessionStart.
anthropics/claude-plugins-official
Explains how to write agents for Claude Code plugins: the markdown file with YAML frontmatter, trigger descriptions, model and color settings, and system prompt design.
diet103/claude-code-infrastructure-showcase
A guide to creating and managing Claude Code skills with auto-activation: skill-rules.json triggers, hooks, enforcement levels, YAML frontmatter and progressive disclosure.
baserproject/basercms
baserCMS のリポジトリセキュリティアドバイザリ(GHSA・triage含む)対応を、一覧取得→指摘検証→課題別の修正→プライベートフォーク/ブランチ/PR作成→ローカル検証まで一気通貫で扱う手順とスクリプト。「セキュリティアドバイザリを確認」「triageの脆弱性を検証」「アドバイザリごとにフォークとPRを作って」「脆弱性修正をプルリクにまとめて」等のときに使う。Copilot/GHAは…
baserproject/basercms
baserCMS の「通常プラグイン(サードパーティ/単体配布)」を monorepo の「コアプラグイン」に昇格させる手順。「コアプラグインに変更」「コアプラグイン化」「通常プラグインをコアに昇格」「monorepo に取り込む」等のときに参照する。プラグイン名の規約変更(bc- プレフィックス付与・CamelCase→ハイフン区切り)、.git/シンボリックリンク/standalone…
baserproject/basercms
baserCMS プラグインを 5.2系 から 5.3系(PHP 8.5 / CakePHP 5.2.x ベース、開発中)へ移行する際の baserCMS 固有の破壊的変更・非推奨・テスト基盤対応のレシピ集。「プラグインを5.3に対応」「baserCMS 5.3 マイグレーション」「PluginCollection::create(): $config null given」「Plugin…
baserproject/basercms
baserCMS の plugins/baser-core/VERSION.txt に、リリース分の変更履歴(NEW/CHG/BUG)をコミットログから生成して追記する手順。「VERSION.txt を更新して」「リリースノートを作って」「変更履歴をまとめて」「今回のリリース分の変更点を書き出して」「前回リリースからの差分を VERSION.txt…
baserproject/basercms
baserCMS(CakePHP5 / PHPUnit)のユニットテストをローカル Docker 環境で実行・調査する手順。「ユニットテストを実行して」「全テストを走らせて」「このテストだけ流して」「テスト失敗を調べて」「プラグイン単体でテストを動かしたい」「プラグインにテスト環境を導入したい」等のときに参照する。コンテナ名・実行コマンド・権限自動承認のためのコマンド整形・失敗の集計と切り分け方…
baserproject/basercms
baserCMS 4系(CakePHP 2.10ベース)+ jQuery プロジェクトの開発ルール集。「baserCMS 4 で開発」「4系のプラグインを修正」「CakePHP 2系のコードを書く」「app/Plugin 配下の Controller/Model/View」「テーマの…
Works with
Categories
baserCMS 5系(CakePHP 5ベース)のプラグインを新規開発・改修する際の正本パターン集。「プラグインを作成」「bcplugin で bake」「管理画面を追加」「Table/Entity の書き方」「initialize でアソシエーション宣言」「validationDefault」「fetchTable と TableRegistry の使い分け」「BcAdminForm /…. Basercms5 Plugin Development is an agent skill from baserproject/basercms.
Basercms5 Plugin Development fits situations like: tasks that involve Hooks and plugins.
Run `npx skills add baserproject/basercms --skill basercms5-plugin-development -a claude-code`. Or copy the skill folder (.agents/skills/basercms5-plugin-development in baserproject/basercms) into .claude/skills/basercms5-plugin-development in your project. Claude Code loads it when a task matches its description.
Run `npx skills add baserproject/basercms --skill basercms5-plugin-development -a codex`. Or copy the skill folder (.agents/skills/basercms5-plugin-development in baserproject/basercms) into .agents/skills/basercms5-plugin-development in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add baserproject/basercms --skill basercms5-plugin-development -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/basercms5-plugin-development, .gemini/skills/basercms5-plugin-development, .github/skills/basercms5-plugin-development and .opencode/skills/basercms5-plugin-development in your project.
Going by SKILL.md and its folder, Basercms5 Plugin Development needs the command-line tools its instructions call (composer, npm and npx).
SKILL.md contains no URLs. Its commands use npm and npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Basercms5 Plugin Development is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.9k tokens (SKILL.md is roughly 19k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Basercms5 Plugin Development: Discord Php Interactions (discord-php/DiscordPHP, 1.1k stars), Interaction Flow Keeper (discord-php/DiscordPHP, 1.1k stars), Wp Plugin Development (jorgerosal/wordpress-skills, 100 stars) and Hook Development for Claude Code Plugins (anthropics/claude-plugins-official, 37k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
baserproject (a GitHub organization) maintains it in baserproject/basercms, which has 190 GitHub stars. The repository holds 15 skills in this directory. The repository was last updated on October 5, 2026.
Source: baserproject/basercms on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.