laravel-schema-attributes maintained by liar88828
Laravel Schema Attributes
PHP 8 attribute-driven schema compiler for Laravel. One schema class drives everything — migrations, models, factories, controllers, and tests with no duplication.
Reverse Engineering Existing Migrations
Already have a Laravel project with migrations? Import them as schemas with one command:
# Scan all migrations → generate schema classes in app/Schema/
php artisan schema:scan
# Scan a specific table
php artisan schema:scan create_orders_table
# Generate migration-only schemas (no EloquentModel)
php artisan schema:scan --migration
# Generate full schemas with EloquentModel
php artisan schema:scan --model
# Print to console instead of writing files
php artisan schema:scan --print
# Overwrite existing schemas
php artisan schema:scan --force
Example — given this migration:
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('status', 20)->default('pending')->index();
$table->decimal('total', 10, 2);
$table->timestamps();
$table->softDeletes();
});
Generated OrderSchema.php:
#[EloquentModel(model: Order::class)]
#[Table(name: 'orders', timestamps: true, softDeletes: true)]
class OrderSchema
{
#[PrimaryKey(type: 'bigIncrements')]
public int $id;
#[Column(type: 'unsignedBigInteger', index: true)]
#[ForeignKey(references: 'id', on: 'users', onDelete: 'cascade')]
// #[BelongsTo(related: UserSchema::class)] ← set the related schema
// #[Fillable]
public int $user_id;
#[Column(type: 'string', length: 20, default: 'pending', index: true)]
// #[Fillable]
public string $status;
#[Column(type: 'decimal', precision: 10, scale: 2)]
// #[Fillable]
public float $total;
}
After scanning, review the generated schemas and uncomment/add
#[Fillable],#[Required],#[Hidden],#[Cast]as needed.
Concept
#[EloquentModel(model: Article::class)]
#[Table(name: 'articles', timestamps: true, softDeletes: true)]
class ArticleSchema
{
#[PrimaryKey(type: 'bigIncrements')]
public int $id;
#[Column(type: 'string', length: 191)]
#[Fillable] #[Required] #[Min(2)] #[Max(191)]
public string $title;
#[Column(type: 'unsignedBigInteger')]
#[ForeignKey(references: 'id', on: 'users', onDelete: 'cascade')]
#[BelongsTo(related: UserSchema::class)]
public int $user_id;
}
Then run one command to generate everything:
php artisan schema:refresh ArticleSchema
This generates:
- ✅ Migration
- ✅ Eloquent model with
$fillable,$hidden,$casts, relations - ✅ Factory with correct Faker calls
- ✅ PHPUnit test covering migration, model wiring, validation, persistence
- ✅ API controller with validation, Auth injection, soft delete & restore
Installation
composer require liar88828/laravel-schema-attributes
Laravel auto-discovers the service provider. No manual registration needed.
Artisan Commands
| Command | Description |
|---|---|
schema:make ArticleSchema |
Create a new schema class |
schema:scan |
Reverse-engineer existing migrations → schema classes |
schema:migrate ArticleSchema |
Generate migration |
schema:model ArticleSchema |
Generate Eloquent model |
schema:relations ArticleSchema |
Generate relation methods |
schema:factory ArticleSchema |
Generate factory |
schema:service ArticleSchema |
Generate Service layer class |
schema:controller ArticleSchema |
Generate API controller |
schema:test ArticleSchema |
Generate PHPUnit test |
schema:refresh ArticleSchema |
Generate all of the above |
Available Attributes
Migration
#[Table] #[Column] #[PrimaryKey] #[ForeignKey] #[ForeignSchema]
#[HasOne] #[HasMany] #[BelongsTo] #[BelongsToMany]
Model
#[EloquentModel] #[Fillable] #[Hidden] #[Cast] #[Appended] #[UsesSchema]
Validation
#[Required] #[Email] #[Min] #[Max] #[In] #[Unique] #[Uuid]
#[Confirmed] #[Regex] #[Numeric]
Auth Model Example
use Illuminate\Foundation\Auth\User;
use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\TwoFactorAuthenticatable;
#[EloquentModel(
model: UserModel::class,
extend: User::class,
traits: [Notifiable::class, TwoFactorAuthenticatable::class],
)]
#[Table(name: 'users', timestamps: true, softDeletes: true)]
class UserSchema
{
#[Column(type: 'string', length: 191, unique: true)]
#[Fillable] #[Required] #[Email] #[Unique(table: 'users', column: 'email')]
public string $email;
#[Column(type: 'string')]
#[Fillable] #[Hidden] #[Cast('hashed')] #[Required] #[Confirmed]
public string $password;
#[Column(type: 'rememberToken')]
#[Hidden]
public ?string $remember_token = null;
}
HasSchema Trait
Adding use HasSchema to your model gives you:
// Schema-driven validation
User::schemaValidateOrFail($request->all());
// Update validation (ignores own unique fields)
$user->schemaValidateForUpdate($request->all(), ignoreUniqueFor: ['email' => $user->id]);
// Auto $fillable, $hidden, $casts, $table from schema
// UUID primary key auto-generation
// Relation resolution from schema annotations
Authors & Credits
This package was entirely created by AI.
| Role | AI |
|---|---|
| Code & Architecture | Claude (Anthropic) |
| Helper & Consultation | ChatGPT (OpenAI) |
| Human Supervisor | liar88828 |
💡 This is an experiment in AI-driven open source development. Every line of code, architecture decision, bug fix, and this README was written by AI assistants guided by a human developer.
- PHP 8.2+
- Laravel 11 or 12
- spatie/laravel-route-attributes — installed automatically
spatie/laravel-route-attributes is a lightweight package (~50KB) that only depends on illuminate/routing which Laravel already includes. If your project already has any Spatie package installed, there is zero additional cost.
License
MIT — see LICENSE.