grazulex / laravel-modelschema
Generate and manage Laravel model schemas with automatic validation, documentation, and migration helpers for better data structure management.
Fund package maintenance!
Grazulex
Buy Me A Coffee
paypal.me/strauven
Requires
- php: ^8.3
- illuminate/contracts: ^11.0|^12.0
- illuminate/support: ^11.0|^12.0
- nesbot/carbon: ^3.10
- symfony/yaml: ^7.3
Requires (Dev)
- doctrine/dbal: ^4.2
- larastan/larastan: ^3.4
- laravel/pint: ^1.22
- orchestra/testbench: ^9.0|^10.0
- pestphp/pest: ^3.8
- pestphp/pest-plugin-laravel: ^3.2
- rector/rector: ^2.0
README
A foundational Laravel package for schema-driven development. Parse YAML schemas, generate insertable fragments for models, migrations, requests, resources, factories, seeders, controllers, tests, policies, observers, services, actions, and validation rules. Built to power Laravel TurboMaker, Arc, and other schema-based packages.
[
- ๐ Migration Guide - Upgrading from previous versions
- ๐ Fragment Examples - Understanding generated fragmentsocs/FIELD_TYPES.md)** - Complete field types reference
- ๐ Field Type Plugins - Creating custom field type plugins
- โจ Custom Attributes Examples - Practical examples of custom attributes usage
- โ
Custom Field Validation - Validating custom field types.io/packagist/v/grazulex/laravel-modelschema.svg?style=flat-square)](https://packagist.org/packages/grazulex/laravel-modelschema)
Overview
Laravel ModelSchema provides schema parsing, validation, and fragment generation for Laravel applications. Instead of generating complete files, it produces insertable JSON/YAML fragments that parent applications can integrate into their own generation workflows.
๐ฏ Core Purpose: Enable schema-driven development with clean separation between core schema logic and application-specific generation.
๐ Key Features
- ๐ Schema Parsing & Validation - Parse YAML schemas with core/extension separation
- ๐งฉ Fragment Generation - Generate insertable JSON/YAML fragments for Laravel artifacts
- ๐๏ธ Clean Architecture - Separate core schema responsibilities from app-specific generation
- ๐ Multi-Generator Support - Models, Migrations, Requests, Resources, Factories, Seeders, Controllers, Tests, Policies, Observers, Services, Actions, Rules
- ๐ Schema Analysis - Advanced schema comparison, optimization, and performance analysis
- ๐ Plugin System - Extensible field type plugins for custom functionality
- ๐ Integration API - Complete workflow for external packages (TurboMaker, Arc, etc.)
- โจ Extensible Design - Custom field types, generators, and validation rules
๏ฟฝ Installation
composer require grazulex/laravel-modelschema
๐๏ธ Architecture
Core Services
SchemaService
- Main API for parsing, validation, and core/extension separationGenerationService
- Coordinates all generators to produce insertable fragmentsYamlOptimizationService
- Advanced YAML parsing with lazy loading, streaming, and intelligent cachingSchemaDiffService
- Advanced schema comparison and difference analysisSchemaOptimizationService
- Performance analysis and optimization recommendations- 13 Specialized Generators - Model, Migration, Request, Resource, Factory, Seeder, Controller, Test, Policy, Observer, Service, Action, Rule
FieldTypePluginManager
- Manages extensible field type plugins for custom functionality
Schema Structure
The package uses a "core" structure to clearly separate core schema data from application extensions:
core: model: User table: users fields: name: type: string nullable: false email: type: string unique: true relations: posts: type: hasMany model: App\Models\Post options: timestamps: true soft_deletes: false # Extensions added by parent applications turbomaker: views: ['index', 'create', 'edit'] routes: ['api', 'web'] arc: permissions: ['view', 'create', 'edit', 'delete']
๐ Quick Start
1. Basic Schema Parsing
use Grazulex\LaravelModelschema\Services\SchemaService; $schemaService = new SchemaService(); // Parse and separate core from extensions $result = $schemaService->parseAndSeparateSchema($yamlContent); // Returns: ['core' => [...], 'extensions' => [...]] // Validate only the core schema $errors = $schemaService->validateCoreSchema($yamlContent); // Extract structured data for generation $data = $schemaService->extractCoreContentForGeneration($yamlContent);
2. Complete Integration Workflow
// 1. Generate complete YAML from stub + app data $completeYaml = $schemaService->generateCompleteYamlFromStub( 'user.schema.stub', ['MODEL_NAME' => 'User', 'TABLE_NAME' => 'users'], $appExtensionData ); // 2. Validate the complete YAML (focuses on core section) $errors = $schemaService->validateFromCompleteAppYaml($completeYaml); // 3. Extract all generation data as insertable fragments $generationData = $schemaService->getGenerationDataFromCompleteYaml($completeYaml); // 4. Use fragments in your application $modelFragment = json_decode($generationData['generation_data']['model']['json'], true); $migrationFragment = json_decode($generationData['generation_data']['migration']['json'], true);
3. Fragment-Based Generation
use Grazulex\LaravelModelschema\Services\GenerationService; $generationService = new GenerationService(); // Generate all fragments for a schema $fragments = $generationService->generateAll($schema); // Result structure: // [ // 'model' => ['json' => '{"model": {...}}', 'yaml' => 'model: {...}'], // 'migration' => ['json' => '{"migration": {...}}', 'yaml' => 'migration: {...}'], // 'requests' => ['json' => '{"requests": {...}}', 'yaml' => 'requests: {...}'], // 'resources' => ['json' => '{"resources": {...}}', 'yaml' => 'resources: {...}'], // 'factory' => ['json' => '{"factory": {...}}', 'yaml' => 'factory: {...}'], // 'seeder' => ['json' => '{"seeder": {...}}', 'yaml' => 'seeder: {...}'], // 'controllers' => ['json' => '{"controllers": {...}}', 'yaml' => 'controllers: {...}'], // 'tests' => ['json' => '{"tests": {...}}', 'yaml' => 'tests: {...}'], // 'policies' => ['json' => '{"policies": {...}}', 'yaml' => 'policies: {...}'], // 'observers' => ['json' => '{"observers": {...}}', 'yaml' => 'observers: {...}'], // 'services' => ['json' => '{"services": {...}}', 'yaml' => 'services: {...}'], // 'actions' => ['json' => '{"actions": {...}}', 'yaml' => 'actions: {...}'], // 'rules' => ['json' => '{"rules": {...}}', 'yaml' => 'rules: {...}'] // ]
๐๏ธ Available Generators
Laravel ModelSchema provides 13 specialized generators, each producing insertable JSON/YAML fragments:
Core Laravel Components
Generator | Description | Output Fragment |
---|---|---|
Model | Eloquent model with relationships, casts, and configurations | model: {class_name, table, fields, relations, casts, ...} |
Migration | Database migration with fields, indexes, and foreign keys | migration: {table, fields, indexes, foreign_keys, ...} |
Request | Form Request classes for validation (Store/Update) | requests: {store: {...}, update: {...}} |
Resource | API Resource classes for data transformation | resources: {main_resource: {...}, collection_resource: {...}} |
Factory | Model Factory for testing and seeding | factory: {class_name, definition, states, ...} |
Seeder | Database Seeder for data population | seeder: {class_name, model, count, relationships, ...} |
Advanced Components
Generator | Description | Output Fragment |
---|---|---|
Controller | API and Web Controllers with CRUD operations | controllers: {api_controller: {...}, web_controller: {...}} |
Test | PHPUnit test classes (Feature and Unit) | tests: {feature_tests: [...], unit_tests: [...]} |
Policy | Authorization Policy classes | policies: {class_name, methods, gates, ...} |
Business Logic Components (New in v2.0)
Generator | Description | Output Fragment |
---|---|---|
Observer | Eloquent Observer with model event handlers | observers: {class_name, events, methods, ...} |
Service | Business logic Service classes with CRUD operations | services: {class_name, methods, dependencies, ...} |
Action | Single-responsibility Action classes | actions: {crud_actions: [...], business_actions: [...]} |
Rule | Custom Validation Rule classes | rules: {business_rules: [...], foreign_key_rules: [...]} |
Usage Examples
// Generate specific components $observerFragment = $generationService->generateObservers($schema); $serviceFragment = $generationService->generateServices($schema); $actionFragment = $generationService->generateActions($schema); $ruleFragment = $generationService->generateRules($schema); // Generate multiple new components $fragments = $generationService->generateMultiple($schema, [ 'observers', 'services', 'actions', 'rules' ]); // Generate everything including new components $allFragments = $generationService->generateAll($schema, [ 'model' => true, 'migration' => true, 'requests' => true, 'resources' => true, 'factory' => true, 'seeder' => true, 'controllers' => true, 'tests' => true, 'policies' => true, 'observers' => true, // New 'services' => true, // New 'actions' => true, // New 'rules' => true, // New ]);
๐ง API Reference
SchemaService
Method | Description | Returns |
---|---|---|
parseAndSeparateSchema() |
Parse YAML and separate core/extensions | ['core' => array, 'extensions' => array] |
validateCoreSchema() |
Validate only core schema section | array (errors) |
extractCoreContentForGeneration() |
Extract structured core data | array |
generateCompleteYamlFromStub() |
Generate complete YAML from stub | string |
getGenerationDataFromCompleteYaml() |
Extract all generation fragments | array |
GenerationService
Method | Description | Returns |
---|---|---|
generateAll() |
Generate all fragments for schema | array |
generateSingle() |
Generate single generator fragment | array |
getAvailableGenerators() |
List available generators | array |
๐ Trait-Based Field Type Plugin System
Laravel ModelSchema features an extensible plugin system using a trait-based architecture for custom field types. This modern approach provides powerful customization through traits and configuration objects.
Plugin Manager
use Grazulex\LaravelModelschema\Support\FieldTypePluginManager; $manager = new FieldTypePluginManager(); // Register a custom plugin $manager->registerPlugin(new CustomFieldTypePlugin()); // Auto-discover plugins in specific paths $manager->discoverPlugins([ 'App\\FieldTypes\\*Plugin', 'Custom\\Packages\\*FieldTypePlugin' ]); // Get all registered plugins $plugins = $manager->getAllPlugins();
Creating Custom Plugins with Traits
The new trait-based approach allows you to define field options through configuration arrays rather than hardcoded properties:
use Grazulex\LaravelModelschema\Support\FieldTypePlugin; class UrlFieldTypePlugin extends FieldTypePlugin { protected string $version = '1.0.0'; protected string $author = 'Your Name'; protected string $description = 'Advanced URL field with validation traits'; public function __construct() { // Define custom attributes using trait-based configuration $this->customAttributes = [ 'schemes', 'verify_ssl', 'timeout', 'domain_whitelist', 'max_redirects' ]; // Configure each attribute with validation traits $this->customAttributeConfig = [ 'schemes' => [ 'type' => 'array', 'default' => ['http', 'https'], 'enum' => ['http', 'https', 'ftp', 'ftps'], 'description' => 'Allowed URL schemes for validation' ], 'verify_ssl' => [ 'type' => 'boolean', 'default' => true, 'description' => 'Enable SSL certificate verification' ], 'timeout' => [ 'type' => 'integer', 'min' => 1, 'max' => 300, 'default' => 30, 'description' => 'Connection timeout in seconds' ], 'domain_whitelist' => [ 'type' => 'array', 'required' => false, 'validator' => function ($value): array { // Custom validation trait for domain lists if (!is_array($value)) return ['must be an array']; foreach ($value as $domain) { if (!filter_var("http://{$domain}", FILTER_VALIDATE_URL)) { return ["Invalid domain: {$domain}"]; } } return []; } ] ]; } public function getType(): string { return 'url'; } public function getAliases(): array { return ['website', 'link', 'uri']; } }
Trait-Based Custom Attributes System
The trait-based plugin system supports sophisticated custom attributes through configuration objects:
- Type validation traits:
string
,int
,boolean
,array
, etc. - Constraint traits:
min
,max
,required
,enum
values - Default value traits: Automatically applied if not provided
- Custom validator traits: Callback functions for complex validation logic
- Transformation traits: Custom value transformation before storage
- Integration traits: Seamlessly merged with Laravel's standard attributes
Advanced Trait Examples
// Numeric validation traits 'timeout' => [ 'type' => 'integer', 'min' => 1, 'max' => 300, 'default' => 30, 'transform' => fn($value) => (int) $value // Type transformation trait ], // Array validation traits with enum constraints 'schemes' => [ 'type' => 'array', 'enum' => ['http', 'https', 'ftp', 'ftps'], 'default' => ['http', 'https'], 'validator' => function($schemes): array { // Custom validation trait return array_filter($schemes, fn($s) => in_array($s, ['http', 'https'])); } ], // Complex custom validator traits 'domain_pattern' => [ 'type' => 'string', 'validator' => function($pattern): array { if (!preg_match('/^\/.*\/[gimxs]*$/', $pattern)) { return ['Domain pattern must be a valid regex']; } return []; } ]
๐ See Field Type Plugins Documentation for complete trait-based implementation guide.
๐ Example Schema Files
Basic User Schema
core: model: User table: users fields: name: type: string nullable: false rules: ['required', 'string', 'max:255'] email: type: string unique: true rules: ['required', 'email', 'unique:users'] email_verified_at: type: timestamp nullable: true password: type: string rules: ['required', 'string', 'min:8'] options: timestamps: true soft_deletes: false
Blog Post Schema with Relations
core: model: Post table: posts fields: title: type: string rules: ['required', 'string', 'max:255'] slug: type: string unique: true rules: ['required', 'string', 'unique:posts'] content: type: text rules: ['required'] published_at: type: timestamp nullable: true user_id: type: foreignId rules: ['required', 'exists:users,id'] relations: user: type: belongsTo model: App\Models\User comments: type: hasMany model: App\Models\Comment tags: type: belongsToMany model: App\Models\Tag pivot_table: post_tags options: timestamps: true soft_deletes: true
๏ฟฝ Integration with Parent Applications
This package is designed to be consumed by larger Laravel packages like TurboMaker and Arc. Here's the typical integration pattern:
Parent Application Workflow
// 1. Parent app generates complete YAML $yaml = $schemaService->generateCompleteYamlFromStub('user.schema.stub', [ 'MODEL_NAME' => 'User', 'TABLE_NAME' => 'users' ], $parentAppData); // 2. Parent app validates the schema $errors = $schemaService->validateFromCompleteAppYaml($yaml); if (!empty($errors)) { throw new ValidationException($errors); } // 3. Parent app extracts generation fragments $data = $schemaService->getGenerationDataFromCompleteYaml($yaml); // 4. Parent app integrates fragments into its own files $parentAppGenerator->generateModelFile($data['generation_data']['model']['json']); $parentAppGenerator->generateMigrationFile($data['generation_data']['migration']['json']); // ... etc for requests, resources, factory, seeder
Fragment Structure
Each generator produces insertable fragments with this structure:
{ "model": { "class_name": "User", "table": "users", "fields": [...], "relations": [...], "casts": {...}, "options": {...} } }
The parent application receives these fragments and inserts them into its own generation templates.
๐งช Testing
# Run all tests composer test # Run with coverage composer test-coverage # Run specific test file ./vendor/bin/pest tests/Unit/SchemaServiceTest.php
๐ง Requirements
- PHP: ^8.3
- Laravel: ^12.19 (optional, used in service provider)
- Symfony YAML: ^7.3 (for YAML parsing)
๐ Documentation
Core Documentation
- ๐๏ธ Architecture Guide - Understanding the package structure and design
- ๏ฟฝ Migration Guide - Upgrading from previous versions
- ๐ Fragment Examples - Understanding generated fragments
Field Types & Extensions
- ๏ฟฝ Field Types Guide - Complete field types reference
- ๐ Field Type Plugins - Creating custom field type plugins
- โ Custom Field Validation - Validating custom field types
Advanced Features
- ๐ Logging System - Comprehensive logging and debugging
- โก Enhanced Features - Advanced capabilities overview
- ๏ฟฝ YAML Optimization - High-performance YAML parsing with intelligent caching and streaming
- ๏ฟฝ๐ Schema Optimization - Schema analysis and optimization tools
- ๐ Security Features - Comprehensive security validation and protection
Integration Examples
- ๐ Integration Example - Complete integration workflow
- โจ New Generators Example - Observer, Service, Action, Rule generators demo
- ๐ ๏ธ Schema Service API - API usage examples
- ๐ API Extensions - Extended API implementations
- ๐ YAML Optimization Examples - Performance optimization usage and examples
- โก Schema Optimization Usage - Advanced schema analysis examples
- ๐ Security Usage Examples - Security validation and protection examples
๐ค Contributing
We welcome contributions! Please see our Contributing Guide for details.
๐ Security
Please review our Security Policy for reporting vulnerabilities.
๐ License
Laravel ModelSchema is open-sourced software licensed under the MIT license.
Made with โค๏ธ by Jean-Marc Strauven (https://github.com/Grazulex)