一键导入
models
Eloquent model conventions for mass assignment, casts, relationship naming, activity logging, and mandatory model tests (CRUD + relations).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Eloquent model conventions for mass assignment, casts, relationship naming, activity logging, and mandatory model tests (CRUD + relations).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Readonly data containers with typed factory methods (`fromArray`, `fromModel`, `fromCollection`, `fromRequest`) used to pass structured data between application layers — especially for external API responses, Eloquent models, and service boundaries. Use this skill whenever creating, reviewing, or refactoring DTOs, Data Transfer Objects, value objects for inter-layer communication, or mapping payloads from APIs, models, or collections into typed PHP objects. Also trigger when the user mentions spatie/laravel-data alternatives, data mapping, or payload normalization in a Laravel context.
Single-purpose business logic classes that encapsulate one well-defined business operation. Actions are the primary location for business logic in Laravel applications, invoked from controllers, commands, or jobs.
Albatros accounting API integration via Saloon. Use when working with app/Services/Albatros/, AlbatrosConnector, or Albatros DTOs.
Laravel Blade template conventions covering components, output escaping, security, structure, and formatting.
Artisan console command classes that serve as the CLI entry point for operations. Commands validate input and delegate all business logic to Actions or Services.
Thin HTTP entry points that validate input, delegate to Actions or Services, and return a response. Controllers contain no business logic.
| name | models |
| description | Eloquent model conventions for mass assignment, casts, relationship naming, activity logging, and mandatory model tests (CRUD + relations). |
| compatible_agents | ["architect","implement","refactor","review"] |
app/Models/.spatie/laravel-activitylog is installed and configured for activity logging.LogsActivity to these models by default.protected $guarded = []; on all business models; do not use $fillable.casts() method instead of a $casts property.casts(), configure:
decimal:2).LogsActivity trait on all business models that should be audited.getActivitylogOptions() to:
logAll().logOnlyDirty().dontSubmitEmptyLogs().HasMany, BelongsTo, etc.).belongsTo, hasOne, morphOne).hasMany, belongsToMany, morphMany).camelCase based on the related model name (for example, pipelineSteps() for PipelineStep).steps(), runs(), items(), or attachments() when they hide model intent.// --- Relationships ---// --- Status Helpers ---// --- Activity Log ---isDraft(), isPaid()).All relationship renames follow this convention: method name = camelCase(RelatedModelName) with singular/plural matching relation cardinality.
| Model | Old Method | New Method |
|---|---|---|
| Pipeline | steps() | pipelineSteps() |
| Pipeline | runs() | pipelineRuns() |
| PipelineStep | stepRuns() | pipelineStepRuns() |
| PipelineRun | stepRuns() | pipelineStepRuns() |
| PipelineTemplate | steps() | pipelineSteps() |
| Inbox | items() | inboxItems() |
| Inbox | serviceUsers() | inboxServiceUsers() |
| Inbox | importConfigs() | inboxImportConfigs() |
| InboxItem | importConfig() | inboxImportConfig() |
| InboxItem | sections() | inboxItemSections() |
| ProviderType | templates() | providerTypeTemplates() |
| Prompt | attachments() | promptAttachments() |
database/factories/.->draft(), ->paid(), ->archived()) to match model helpers.tests/Unit/Models/ (or the project-standard model-test location).HasMany, BelongsTo, etc.).isDraft() and enum/date casts).namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
class Invoice extends Model
{
use LogsActivity;
protected $guarded = [];
protected function casts(): array
{
return [
'status' => Status::class,
'due_date' => 'date',
'amount' => 'decimal:2',
];
}
// --- Relationships ---
public function invoiceLines(): HasMany
{
return $this->hasMany(InvoiceLine::class);
}
// --- Status Helpers ---
public function isDraft(): bool
{
return $this->status === Status::Draft;
}
public function isPaid(): bool
{
return $this->status === Status::Paid;
}
// --- Activity Log ---
public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()
->logAll()
->logOnlyDirty()
->dontSubmitEmptyLogs();
}
}
// tests/Unit/Models/InvoiceTest.php
use App\Enums\Status;
use App\Models\Invoice;
use App\Models\InvoiceLine;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
it('supports invoice CRUD operations', function () {
// Create
$invoice = Invoice::factory()->create([
'status' => Status::Draft,
'amount' => '100.00',
]);
expect($invoice->exists)->toBeTrue();
$this->assertDatabaseHas('invoices', ['id' => $invoice->id, 'amount' => '100.00']);
// Read + cast/helper checks
$fresh = Invoice::query()->findOrFail($invoice->id);
expect($fresh->status)->toBe(Status::Draft)
->and($fresh->isDraft())->toBeTrue();
// Update
$fresh->update(['amount' => '250.00']);
$this->assertDatabaseHas('invoices', ['id' => $fresh->id, 'amount' => '250.00']);
// Delete (supports soft deletes)
$fresh->delete();
$this->assertSoftDeleted('invoices', ['id' => $fresh->id]);
// For hard-deleting models, use instead:
// $this->assertDatabaseMissing('invoices', ['id' => $fresh->id]);
});
it('defines and resolves invoiceLines relation', function () {
$invoice = Invoice::factory()->create();
// Relation shape
expect($invoice->invoiceLines())->toBeInstanceOf(HasMany::class);
// Relation behavior
InvoiceLine::factory()->count(2)->create(['invoice_id' => $invoice->id]);
expect($invoice->invoiceLines)->toHaveCount(2)
->and($invoice->invoiceLines->first())->toBeInstanceOf(InvoiceLine::class);
});
$guarded = [] and does not define $fillable.casts() method, not a $casts property.LogsActivity trait is added where auditing is required.getActivitylogOptions() is configured with logAll(), logOnlyDirty(), and dontSubmitEmptyLogs().camelCase(RelatedModelName) with correct singular/plural form.steps() -> pipelineSteps()).database/factories/.$fillable arrays instead of $guarded = [].$casts as a property instead of a casts() method.LogsActivity trait on business models that should be audited.protected array $fillable = ['name']; and protected array $casts = ['status' => 'string']; instead of $guarded = [] and casts()Enums/SKILL.md — enums are cast in casts()Migrations/SKILL.md — migrations define the model's schemaPestTesting/SKILL.md — preferred style for model testsPHPUnit/SKILL.md — class-based alternative where required