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
paypal.me/strauven
Requires
- php: ^8.3
- illuminate/contracts: ^12.0
- illuminate/support: ^12.19
- nesbot/carbon: ^3.10
- symfony/yaml: ^7.3
Requires (Dev)
- doctrine/dbal: ^4.2
- larastan/larastan: ^3.4
- laravel/pint: ^1.22
- orchestra/testbench: ^10.0
- pestphp/pest: ^3.8
- pestphp/pest-plugin-laravel: ^3.2
- rector/rector: ^2.0
This package is auto-updated.
Last update: 2025-08-03 18:37:29 UTC
README
A foundational Laravel package for schema-driven development. Parse YAML schemas, generate insertable fragments for models, migrations, requests, resources, factories, and seeders. Built to power Laravel TurboMaker, Arc, and other schema-based packages.
[](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
- ๏ฟฝ 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- 8 Specialized Generators - Model, Migration, Request, Resource, Factory, Seeder, Controller, Test, Policy
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: {...}'] // ]
๐ง 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
- ๐ ๏ธ 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)