Analyze model
Deep analysis of a Laravel Eloquent model - relationships, scopes, casts, fillable, observers, keepers, actions.From its SKILL.md
npx -y skills add edulazaro/laraclaude --skill analyze-modelAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 12 stars12 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
8.2 KB, as published. Nobody here has run it
Analyze Model
Perform a comprehensive analysis of a Laravel Eloquent model, extracting all relevant information about its structure, relationships, behaviors, and potential issues.
Subcommands
| Subcommand | Description |
|---|---|
| (no argument) | List all models and ask which to analyze. Read-only report. |
fix | Analyze all models and auto-fix common issues (missing fillable, broken casts, etc.) with confirmation before each change. |
fix --dry-run | Show what fixes would be applied across all models without changing anything. |
[ModelName] | Analyze a specific model. Read-only report. |
fix [ModelName] | Analyze and fix issues in a specific model, with confirmation before each change. |
Analysis Process
Step 1: Locate the Model
- If a
[ModelName]argument is provided:- Search for the model in
app/Models/{ModelName}.phpusingGlob. - If not found, try case-insensitive search across
app/Models/directory. - If still not found, search the entire
app/directory for a class with that name.
- Search for the model in
- If no argument is provided:
- Use
Globto list all files inapp/Models/*.php. - Display the list of available models and ask the user which one to analyze.
- Use
Step 2: Read and Parse the Model
Use Read to load the full model file. Extract the following sections:
A. Class Metadata
- Namespace and class name
- Parent class (Model, Authenticatable, Pivot, etc.)
- Traits used (HasFactory, SoftDeletes, HasKeepers, HasActions, HasSources, etc.)
- Class-level attributes (
#[KeptBy(...)],#[UsesOrigin(...)], etc.) - Table name (explicit
$tableproperty or conventional) - Primary key (if customized)
- Timestamps (if disabled)
- Connection (if non-default)
B. Mass Assignment
- $fillable array -- list all fields
- $guarded array -- list all fields
- If neither is defined, flag as a potential security issue
C. Attribute Casting
- $casts array or
casts()method -- list all casts with their types - Note any enum casts and identify the enum class
D. Relationships
For each relationship method, extract:
- Method name
- Relationship type (belongsTo, hasMany, hasOne, belongsToMany, morphTo, morphMany, morphOne, morphToMany, hasManyThrough, hasOneThrough)
- Related model class
- Foreign key (explicit or conventional)
- For belongsToMany: pivot table, pivot columns, withTimestamps
- For morphTo/morphMany: morph name
Display as a structured list:
RELATIONSHIPS
==============
belongsTo:
- organization() -> Organization::class (FK: organization_id)
- office() -> Office::class (FK: office_id)
- user() -> User::class (FK: user_id)
hasMany:
- properties() -> Property::class (FK: client_id)
- operations() -> Operation::class (FK: client_seller_id)
belongsToMany:
- tags() -> Tag::class (pivot: client_tag, columns: [])
E. Scopes
- Local scopes (
scopeActive,scopeForUser, etc.) - Global scopes (applied in
booted()or via attributes) - Show the scope signature and a brief description of what it filters
F. Accessors and Mutators
- Laravel 9+ style:
Attribute::make(get: ..., set: ...) - Legacy style:
getXAttribute(),setXAttribute() - Appended attributes:
$appendsarray - For each accessor, note if it accesses relationships (potential N+1 risk)
G. Observers
- Search for an observer in
app/Observers/{ModelName}Observer.php - If found, list all observer methods (creating, created, updating, updated, deleting, deleted, etc.)
- Note what each observer method does (brief summary)
H. Larakeep Keepers
- Check for
#[KeptBy(KeeperClass::class)]attribute - If found, read the keeper class and list all
getX()methods - Show what attributes each keeper method populates
I. Laractions Actions
- Check for
$actionsarray property - List all registered actions with their class paths
- For each action, read the class and show:
- The
handle()method signature - Brief description of what it does
- The
J. Additional Features
- Boot methods:
boot(),booted()-- any event listeners or global scopes - Custom methods: Public methods that are not relationships, scopes, or accessors
- Constants: Any class constants defined
- Interfaces implemented: Check implements clause
Step 3: Cross-Reference with Migration
- Find the migration that creates this model's table using
Grepto search forSchema::create('{table_name}'. - Compare migration columns with model's
$fillable:- Columns in migration but NOT in
$fillable(and not in standard exclusions like id, timestamps, etc.) - Columns in
$fillablebut NOT in migration (possibly computed or from a different source)
- Columns in migration but NOT in
- Note column types from migration for reference.
Step 4: Detect Potential Issues
Scan for these common problems:
- Missing fillable entries: Columns exist in migration but are not in
$fillableor$guarded. - Relationships without foreign keys: A
belongsTorelationship where the FK column doesn't have a foreign key constraint in the migration. - N+1 risk in accessors: Accessors that access
$this->relationshipwithout the relationship being commonly eager-loaded. - Missing casts: Date columns without date casts, JSON columns without array/json casts, boolean columns without boolean casts.
- Soft deletes mismatch: Model uses
SoftDeletestrait but migration doesn't havesoftDeletes(), or vice versa. - Missing observer registration: Observer file exists but may not be registered in a service provider.
Step 5: Generate Relationship Diagram
Create a text-based relationship diagram showing how this model connects to others:
+------------------+
| Organization |
+------------------+
|
belongsTo
|
+----------+ +-----------+ +----------+
| Office |<-------| Client |------->| User |
+----------+ +-----------+ +----------+
belongsTo | | belongsTo
hasMany belongsToMany
| |
+-----------+ +------+
| Property | | Tag |
+-----------+ +------+
Keep the diagram focused on direct relationships (1 level deep). For models with many relationships, group by relationship type.
Step 6: Present Results
Output all findings in a well-structured format with clear section headers. Use code blocks for code snippets and tables for tabular data.
End with a summary:
MODEL SUMMARY: Client
======================
Table: clients
Traits: 5 (HasFactory, SoftDeletes, HasActions, HasKeepers, Notifiable)
Fillable fields: 22
Relationships: 12 (4 belongsTo, 5 hasMany, 2 belongsToMany, 1 morphMany)
Scopes: 3
Accessors: 4
Actions: 3
Potential issues: 2
Fix Mode (fix or fix [ModelName])
When running in fix mode, automatically apply fixes for detected issues with confirmation before each change:
Fixable Issues:
- Missing $fillable entries: Add missing columns to the
$fillablearray (excluding id, timestamps, soft deletes, and auto-generated fields). - Missing $casts entries: Add appropriate casts for date, boolean, JSON, and enum columns.
- Missing relationship methods: Add
belongsTomethods for FK columns that lack corresponding relationship methods. - Broken relationship references: Fix incorrect model class references or foreign key names in relationship definitions.
- Soft deletes mismatch: Add
SoftDeletestrait if migration hassoftDeletes()but model lacks the trait, or vice versa.
Each fix requires explicit user confirmation before applying.
Dry Run Mode (fix --dry-run)
Show all the fixes that would be applied (same as fix mode) but do not write any changes. Display the before/after diff for each proposed change.