一键导入
goravel-crud-request
Generate create and update request validators for a Goravel entity. Handles validation rules, field mapping, and carbon.DateTime conversion.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Generate create and update request validators for a Goravel entity. Handles validation rules, field mapping, and carbon.DateTime conversion.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Create a broadcast notification system that sends notifications and messages to eligible users based on entity-specific criteria. Use when adding a new entity type that needs to notify users when records are created, updated, or published.
Guide for building non-CRUD pages with consistent design. Use when creating portal pages, custom views, detail modals, sidebar widgets, notification drawers, or any page that is not a standard CRUD table. Covers fullscreen modals, minimal text patterns, calendar widgets, doorbell notifications, optimistic updates, and CrudPage read-only integration.
Guide for building dashboards, charts, KPI cards, and data visualizations. Use when creating dashboard pages, adding charts to features, building stat displays, aggregating data for visual presentation, or implementing export (CSV/PNG/fullscreen) for charts. Based on the Books dashboard implementation using Recharts and shadcn/ui chart components.
Deploy the application to staging or production. Validates, builds, pushes Docker image, deploys via Helm, and runs smoke tests.
Run a comprehensive E2E browser test suite for a newly scaffolded Goravel entity. Tests navigation, CRUD operations, search, filters, row actions, form validation, FK dropdowns, and cross-entity integration using Playwright MCP.
Create a Go database seeder for a Goravel entity with 25+ realistic records. Covers all status/enum values, diverse data for sorting/pagination testing, and proper nullable field handling.
| name | goravel-crud-request |
| description | Generate create and update request validators for a Goravel entity. Handles validation rules, field mapping, and carbon.DateTime conversion. |
| argument-hint | [entity_name] |
| allowed-tools | Bash, Read, Write, Edit, Grep, Glob |
Generate request validators for $ARGUMENTS.
go run . artisan make:req --model=<entity_name> <entity_name>
This creates:
app/http/requests/<entity_name>_create_request.goapp/http/requests/<entity_name>_update_request.goAll form and json tags MUST use snake_case for Goravel's ctx.Request().Bind() to work:
// CORRECT — Bind() populates fields from JSON payloads
FirstName string `form:"first_name" json:"first_name"`
BirthDate *string `form:"birth_date" json:"birth_date"`
PhotoURL *string `form:"photo_url" json:"photo_url"`
// WRONG — Bind() will NOT populate these fields
FirstName string `form:"firstName" json:"firstName"`
string, float64, bool*string, *float64, *boolstring (not carbon.DateTime)[]string or []intfunc (r *EntityCreateRequest) Rules(ctx http.Context) map[string]string {
return map[string]string{
"title": "required|max_len:255",
"description": "required",
"email": "required|email",
"amount": "required", // NO |numeric for float64
"date": "", // NO |date for *string - validate in PrepareForValidation
"status": "required|in:ACTIVE,INACTIVE,PENDING",
}
}
| Field Type | Wrong | Correct |
|---|---|---|
float64 | "required|numeric" | "required" (numeric validation breaks Go float64) |
*string date | "date" | Custom validation in PrepareForValidation() |
| Custom string type | "required|string" | "required|max_len:255" (remove |string) |
The generic CrudController validates the data map from ToCreateData() / ToUpdateData(), NOT the struct fields. Therefore:
Rules() keys MUST match ToCreateData() output keys (camelCase)Rules() keys MUST match ToUpdateData() output keys (snake_case)Messages() and Attributes() methods// CREATE Rules — camelCase keys to match ToCreateData() output
func (r *EntityCreateRequest) Rules(ctx http.Context) map[string]string {
return map[string]string{
"firstName": "required|max_len:100", // camelCase
"lastName": "required|max_len:100", // camelCase
"status": "in:ACTIVE,INACTIVE",
}
}
// UPDATE Rules — snake_case keys to match ToUpdateData() output
func (r *EntityUpdateRequest) Rules(ctx http.Context) map[string]string {
rules := map[string]string{}
if r.FirstName != nil {
rules["first_name"] = "required|max_len:100" // snake_case
}
return rules
}
Keys MUST use camelCase to match model json:"..." tags. The generic service's setFieldsRecursively() matches data map keys against model json tags during creation.
func (r *EntityCreateRequest) ToCreateData() map[string]interface{} {
data := map[string]interface{}{
"firstName": r.FirstName, // camelCase — matches model json:"firstName"
"lastName": r.LastName, // camelCase
"description": r.Description,
}
// Handle optional fields
if r.Notes != nil {
data["notes"] = *r.Notes
}
// Handle multi-word optional fields (camelCase)
if r.BirthDate != nil && *r.BirthDate != "" {
data["birthDate"] = *r.BirthDate // camelCase
}
// Handle array fields
if r.Tags != nil {
data["tags"] = r.Tags
} else {
data["tags"] = []string{} // Default empty array
}
return data
}
// If model uses NON-POINTER carbon.DateTime:
// Date carbon.DateTime `json:"date"`
if r.Date != "" {
parsedDate := carbon.Parse(r.Date)
if parsedDate.Error == nil {
data["date"] = *carbon.NewDateTime(parsedDate) // DEREFERENCE with *
}
}
// If model uses POINTER *carbon.DateTime:
// DateOfBirth *carbon.DateTime `json:"date_of_birth"`
if r.DateOfBirth != nil && *r.DateOfBirth != "" {
parsedDate := carbon.Parse(*r.DateOfBirth)
if parsedDate.Error == nil {
data["date_of_birth"] = carbon.NewDateTime(parsedDate) // NO dereference
}
}
Rule: carbon.NewDateTime() returns *carbon.DateTime. Dereference with * only if model field is non-pointer.
Same structure but ALL fields should be pointers (partial updates):
type EntityUpdateRequest struct {
Title *string `json:"title"`
Description *string `json:"description"`
Tags *[]string `json:"tags"`
}
Keys MUST use snake_case to match DB column names. The generic service's Update() passes the data map directly to GORM's Update(), which needs DB column names.
func (r *EntityUpdateRequest) ToUpdateData() map[string]interface{} {
data := map[string]interface{}{}
if r.FirstName != nil {
data["first_name"] = *r.FirstName // snake_case — matches DB column
}
if r.LastName != nil {
data["last_name"] = *r.LastName // snake_case
}
if r.Description != nil {
data["description"] = *r.Description
}
if r.BirthDate != nil {
data["birth_date"] = *r.BirthDate // snake_case
}
if r.Tags != nil {
data["tags"] = *r.Tags
}
return data
}
| Method | Key Format | Reason |
|---|---|---|
ToCreateData() | camelCase | setFieldsRecursively() matches model json:"..." tags |
ToUpdateData() | snake_case | GORM's Update() matches DB column names directly |
## Step 4: Exclude Read-Only Fields
Fields that are calculated, aggregated, or system-managed should NOT appear in either request struct. Examples:
- Scores, totals, aggregates
- `created_by`, `updated_by` (set by framework)
- `created_at`, `updated_at` (set by framework)
## Verify
After fixing both request files:
```bash
# Vet the requests package
go vet ./app/http/requests/...
# Confirm full project compiles
go build ./...
Run /goravel-crud-controller to generate the API controller.