From filament-ai-skills
Verifies and fixes direct static calls on Eloquent models, ensuring they always go through ::query() before methods like find, where, create, all, etc. Activate when: query(), Model::find, Model::create, Model::where, Model::all, eloquent query, static model call, model without query, fix model.
How this skill is triggered — by the user, by Claude, or both
Slash command
/filament-ai-skills:eloquent-query-checkThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
All data access via Eloquent model **must go through `::query()`** before any method.
All data access via Eloquent model must go through ::query() before any method.
// ❌ Wrong
Product::find($id)
Product::create([...])
Product::where('tenant_id', $id)->get()
Product::all()
Product::count()
Product::pluck('name', 'id')
Product::first()
Product::firstOrCreate([...])
Product::updateOrCreate([...])
Product::exists()
// ✅ Correct
Product::query()->find($id)
Product::query()->create([...])
Product::query()->where('tenant_id', $id)->get()
Product::query()->get()
Product::query()->count()
Product::query()->pluck('name', 'id')
Product::query()->first()
Product::query()->firstOrCreate([...])
Product::query()->updateOrCreate([...])
Product::query()->exists()
Builder with correct type hints — PHPStan and IDEs infer the model type// Keep as-is — these are not database queries
Model::factory() // Test factories
Model::query() // Already correct
Model::class // Class constant
Model::make(...) // Filament Action, not Eloquent
Model::observe(...) // Observer registration
Model::getSelectComponent() // Custom static method
Model::from(...) // Rarely, accepted
new Model() // Direct instantiation
# Staged files (pre-commit)
git diff --name-only --cached | grep '\.php$'
# Modified files (working tree)
git diff --name-only | grep '\.php$'
Run for each identified PHP file:
# Direct calls without ::query()
::(find|findOrFail|findMany|where|whereIn|whereNotIn|whereHas|with|all|count|create|first|firstOrCreate|firstOrNew|updateOrCreate|pluck|exists|sum|avg|min|max|get|paginate|simplePaginate|cursor|chunk|each|latest|oldest|orderBy|select|groupBy|having|join|leftJoin|rightJoin|insert|upsert)\(
Use the Grep tool with output_mode: "content" to see the exact lines.
Additional filter: Ignore lines where the pattern is already preceded by ::query().
For each line found, confirm:
Model::method()::query() before it? (e.g. Model::query()->where( — OK)static)// Substitution pattern:
// Model::method( → Model::query()->method(
// Examples:
Contact::where('tenant_id', $id) → Contact::query()->where('tenant_id', $id)
Account::create([...]) → Account::query()->create([...])
Order::find($orderId) → Order::query()->find($orderId)
Product::all() → Product::query()->get()
vendor/bin/pint --dirty
Model::(find|create|where|all|count|first|pluck) in modified PHP files::query()?Model::query()->method()vendor/bin/pint --dirty executed// ❌ Frequent in Actions and Forms
->options(fn () => User::pluck('name', 'id'))
->options(fn () => Category::all()->pluck('name', 'id'))
$product = Product::find($productId);
// ✅ Correct
->options(fn () => User::query()->pluck('name', 'id'))
->options(fn () => Category::query()->pluck('name', 'id'))
$product = Product::query()->find($productId);
// ❌
$count = Order::count();
$total = Account::where('type', 'payables')->sum('amount');
// ✅
$count = Order::query()->count();
$total = Account::query()->where('type', 'payables')->sum('amount');
// ❌
$existing = Product::where('barcode', $barcode)->first();
// ✅
$existing = Product::query()->where('barcode', $barcode)->first();
Model::factory() — test factories are not queriesModel::class — it is a PHP constant, not a method::query() correctlynpx claudepluginhub felipearnold/filament-ai-skills --plugin filament-ai-skillsProvides a checklist for code reviews covering functionality, security, performance, maintainability, tests, and quality. Use for pull requests, audits, team standards, and developer training.