spatie/laravel-model-info
Inspect Laravel Eloquent models to discover their file name, table name, attributes (name/type) and relations (name/type/related model). Also includes a ModelFinder to automatically locate all models in your application.
Installation:
composer require spatie/laravel-model-info
No publisher required—just install and use.
First Use Case: Inspect a model’s structure dynamically without manually reading its class or migrations:
use Spatie\ModelInfo\ModelInfo;
$modelInfo = ModelInfo::forModel(App\Models\Post::class);
dd($modelInfo->attributes, $modelInfo->relations);
Key Starting Points:
ModelInfo::forModel(): Core entry point for any model.$modelInfo->fileName: Locate the model’s file path (useful for IDE navigation or refactoring).$modelInfo->tableName: Verify table names without opening migrations.$modelInfo->attributes/$modelInfo->relations: Iterate over collections of Attribute/Relation objects.Dynamic Form/Validation Generation:
$fields = collect($modelInfo->attributes)
->map(fn($attr) => [
'name' => $attr->name,
'type' => $attr->type,
'label' => ucfirst(str_replace('_', ' ', $attr->name)),
]);
Use case: Auto-generate CRUD forms or API schemas (e.g., OpenAPI) from models.
Relation-Aware Queries:
$relatedModels = $modelInfo->relations
->pluck('relatedModel')
->unique()
->map(fn($class) => new $class);
Use case: Preload related models or validate foreign keys.
Model Documentation:
$doc = "## {$modelInfo->className}\n";
$doc .= "**Table**: {$modelInfo->tableName}\n";
$doc .= "**Attributes**:\n";
$doc .= $modelInfo->attributes->map(fn($attr) => "- `$attr->name`: `$attr->type`")
->implode("\n");
Use case: Auto-generate Swagger docs or README snippets.
Migration Helpers:
$columns = $modelInfo->attributes->mapWithKeys(fn($attr) => [
$attr->name => "{$attr->type}" . ($attr->nullable ? '->nullable()' : ''),
]);
Use case: Reverse-engineer migrations or validate existing DB schemas.
Testing Utilities:
public function testModelStructure()
{
$modelInfo = ModelInfo::forModel(Post::class);
$this->assertEquals(['title', 'body'], $modelInfo->attributes->pluck('name'));
}
Use case: Assert model structure in PHPUnit tests.
ModelInfo instances for performance-critical paths:
$cacheKey = "model_info:{$modelClass}";
$modelInfo = Cache::remember($cacheKey, now()->addHours(1), fn() =>
ModelInfo::forModel($modelClass)
);
modelInfo->attributes to dynamically index searchable fields.Caching Quirks:
ModelInfo caches results per model class. Clear cache if models change:
php artisan cache:clear
ModelInfo::forModel($class, true) to force refresh.Relation Resolution:
hasManyThrough) may not resolve fully. Use ->relatedModel cautiously for direct relations only.getMorphClass() for polymorphic relations.Attribute Type Inference:
$attr->type. Use $attr->getType() for raw DB types.$attr->type; // Might return 'string' even if the DB column is `text`.
Model Events:
$fillable, $casts, or relations aren’t reflected in real-time. Re-fetch ModelInfo after updates.Global Scope Interference:
globalScope) don’t affect ModelInfo. Use Model::query()->get() for runtime data.Verify Model Paths:
dd(ModelInfo::forModel(Post::class)->fileName);
Use case: Debug if the package can’t locate a model (e.g., namespaced models).
Inspect Relation Types:
$relation = $modelInfo->relations->first();
dd($relation->type, $relation->relatedModel, $relation->foreignKey);
Use case: Troubleshoot mismatched relation configurations.
Check for Custom Logic:
Spatie\ModelInfo\Attribute or Relation classes if default behavior is insufficient.Custom Attribute Types:
// app/Providers/ModelInfoServiceProvider.php
use Spatie\ModelInfo\Attribute;
public function boot()
{
Attribute::macro('isEncrypted', function() {
return $this->type === 'string' && str_contains($this->name, 'encrypted_');
});
}
Relation Metadata:
// Extend Relation class to add custom properties
$modelInfo->relations->each(function($relation) {
$relation->setAttribute('isRequired', $relation->type === 'BelongsTo');
});
Event Listeners:
ModelInfoGenerated events to log or transform model metadata:
ModelInfo::macro('generate', function($class) {
event(new ModelGenerated($class, ModelInfo::forModel($class)));
});
How can I help you explore Laravel packages today?