unopim-datagrid について
UnoPim の管理画面でデータグリッドや一覧ページを実装するためのリポジトリ向けスキルです。クエリ、列、操作、翻訳、Blade の規約と実例を示します。
主な機能
- 01データグリッド構成とクエリ規則
- 02列と操作の設定要件
- 03操作の権限チェック
- 04HTML エスケープとラベル翻訳
- 05コントローラーと一覧 Blade のパターン
活用シーン
- 01管理画面の一覧グリッド実装
- 02権限付き行操作や一括操作の追加
- 03モジュール一覧ページの作成
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ unopim/ agent-skills --skill unopim-datagridインストール後、Claude Code で/unopim-datagridを入力して読み込まれたか確認します。
詳細
UnoPim DataGrid
以下の実例に合わせてください。エンジン API を推測して作成しないでください。
- Grid クラス:
packages/Webkul/AiAgent/src/DataGrids/Credential/CredentialDataGrid.php - 一括アクション:
packages/Webkul/Admin/src/DataGrids/Catalog/ProductDataGrid.php - 一覧 Blade:
packages/Webkul/Webhook/src/Resources/views/webhooks/index.blade.php - プレフィックス付きの生 SQL:
packages/Webkul/Measurement/src/DataGrids/UnitDataGrid.php
ルール
- Grid はサブディレクトリ
src/DataGrids/{Section}/{Name}DataGrid.phpに配置し、Webkul\DataGrid\DataGridを継承します。 prepareQueryBuilder()では、プレーンなテーブル名(プレフィックスなし)を指定してDB::table()を使用する必要があります。Laravel がenv('DB_PREFIX', '')を適用します。ここで Eloquent モデルを使用してクエリを実行してはいけません。- テーブル名を指定する生のフラグメント(
selectRaw、whereRaw、orderByRaw、DB::raw)では、必ずDB::getTablePrefix()を先頭に付けてください。packages/Webkul/Measurement/src/DataGrids/UnitDataGrid.phpを参照してください。CI では MySQL と PostgreSQL の両方を実行するため、MySQL 専用 SQL(GROUP_CONCAT、バッククォート、DATE_FORMAT)は使用しないでください。 addColumn()では、index、label、type、searchable、filterable、sortableの6つすべてを設定する必要があります。エンジンは3つのフラグを null 合体なしで読み取るため、どれかを省略するとリクエスト時に「Undefined array key」が発生します。- フックのシグネチャ:抽象基底クラスでは
prepareColumns()/prepareActions()に型を宣言していないため、PHPDoc の@returnのみを付けた形式(古い Admin Grid)と: voidを付けた形式(Credential の実例を含む最新の Grid)のどちらもコンパイルできます。新しいコードでは: voidを使用し、既存コードを編集する場合は既存のスタイルに合わせてください。どちらのスタイルも違反として指摘してはいけません。 - アクションの
urlには任意の callable を指定できます。fn ($row): string => route(...)を優先してください。一括アクションのurlは通常のroute(...)文字列であり、callable ではありません。 - すべてのアクションと一括アクションに
bouncer()->hasPermission()による認可チェックを設定してください。一括アクションの ACL キーは、ルート名に合わせて snake_case({module-slug}.credentials.mass_delete)にします。ハイフン区切り(mass-delete)は使用してはいけません。 - Column の
closureの出力は生の HTML としてレンダリングされます。エンジンがstrip_tags()でサニタイズするのはプレーンな文字列セルのみです。closure の HTML にユーザー提供の値を埋め込む場合は、必ずe()でエスケープしてください。 - すべてのラベルとタイトルで
trans()を使用し、キーはまずen_USに追加してから、残り33のロケールにも追加してください。ブール値のバッジには、true の場合はlabel-active、false の場合はlabel-info text-gray-600 dark:text-gray-300を使用してください。 - メソッド本体や配列リテラル内にコメントを記述しないでください。メソッドの PHPDoc は1行の命令形の要約にし、ネイティブの戻り値型がない場合に限り
@returnを記述してください。
Grid クラス
<?php
namespace Webkul\{ModuleName}\DataGrids\Credential;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\DB;
use Webkul\DataGrid\DataGrid;
class CredentialDataGrid extends DataGrid
{
/**
* Prepare query builder.
*
* @return Builder
*/
public function prepareQueryBuilder()
{
return DB::table('{module}_credentials')
->select('id', 'label', 'status', 'created_at');
}
/**
* Prepare columns.
*/
public function prepareColumns(): void
{
$this->addColumn([
'index' => 'label',
'label' => trans('{module-name}::app.credentials.datagrid.label'),
'type' => 'string',
'searchable' => true,
'filterable' => true,
'sortable' => true,
]);
$this->addColumn([
'index' => 'status',
'label' => trans('{module-name}::app.credentials.datagrid.status'),
'type' => 'boolean',
'searchable' => false,
'filterable' => true,
'sortable' => true,
'closure' => fn ($row): string => $row->status
? '<span class="label-active">'.trans('admin::app.common.yes').'</span>'
: '<span class="label-info text-gray-600 dark:text-gray-300">'.trans('admin::app.common.no').'</span>',
]);
}
/**
* Prepare actions.
*/
public function prepareActions(): void
{
if (bouncer()->hasPermission('{module-slug}.credentials.edit')) {
$this->addAction([
'icon' => 'icon-edit',
'title' => trans('{module-name}::app.credentials.datagrid.edit'),
'method' => 'GET',
'url' => fn ($row): string => route('{module-slug}.credentials.edit', $row->id),
]);
}
if (bouncer()->hasPermission('{module-slug}.credentials.delete')) {
$this->addAction([
'icon' => 'icon-delete',
'title' => trans('{module-name}::app.credentials.datagrid.delete'),
'method' => 'DELETE',
'url' => fn ($row): string => route('{module-slug}.credentials.destroy', $row->id),
]);
}
}
/**
* Prepare mass actions.
*/
public function prepareMassActions(): void
{
if (bouncer()->hasPermission('{module-slug}.credentials.mass_delete')) {
$this->addMassAction([
'title' => trans('{module-name}::app.credentials.datagrid.delete'),
'url' => route('{module-slug}.credentials.mass_delete'),
'method' => 'POST',
'options' => ['actionType' => 'delete'],
]);
}
}
}
ステータスの一括更新では、packages/Webkul/Admin/src/DataGrids/Catalog/ProductDataGrid.php の catalog.products.mass_update ブロックから、ラベルと値のペアを含む options 配列をコピーしてください。
コントローラー
public function index()
{
if (request()->ajax()) {
return resolve(CredentialDataGrid::class)->toJson();
}
return view('{module-name}::credentials.index');
}
一覧 Blade
admin::layouts.master と @extends は存在しません。admin レイアウトはコンポーネントです。Create はインデックスページ上のモーダルであり、store() は編集ページへリダイレクトします(Webhook の実例から v-create-webhook-form をコピーしてください)。GET の create ページは追加しないでください。
<x-admin::layouts>
<x-slot:title>
@lang('{module-name}::app.credentials.index.title')
</x-slot>
<x-admin::layouts.page-header :title="trans('{module-name}::app.credentials.index.title')" />
<x-admin::datagrid :src="route('{module-slug}.credentials.index')" />
</x-admin::layouts>
コメント
Markdown 対応