cycle/schema-migrations-generator
## Getting Started
### Minimal Setup
1. **Installation**
```bash
composer require cycle/schema-migrations-generator
Add the service provider to config/app.php:
Cycle\ORM\Migrations\Generator\GeneratorServiceProvider::class,
Basic Usage Generate migrations from an existing database schema:
php artisan cycle:generate-migrations
database/migrations/.config/cycle.php.First Use Case
ChangesCountNameGenerator (default in 2.3.0) for migrations named by the number of changes (e.g., 2023_05_15_000001_create_users_table_with_5_changes).Schema-First Development
Generate migrations from a schema.xml or schema.json (Cycle ORM schema definition) instead of a live DB:
php artisan cycle:generate-migrations --schema=path/to/schema.xml
Incremental Adoption Generate migrations for specific tables:
php artisan cycle:generate-migrations --tables=users,posts
CI/CD Pipeline Use in a pre-commit hook to auto-generate migrations from schema changes:
# .github/workflows/schema-check.yml
- name: Generate Migrations
run: php artisan cycle:generate-migrations --schema=schema.xml
Change-Based Naming (Default in 2.3.0)
The ChangesCountNameGenerator is now the default naming strategy. Customize via config:
// config/cycle.php (optional; default is now ChangesCountNameGenerator)
'migration_naming' => \Cycle\ORM\Migrations\Generator\Generators\ChangesCountNameGenerator::class,
2023_05_15_000001_create_users_table_with_3_changes.Custom Naming Conventions
Override the default naming (now ChangesCountNameGenerator) or revert to timestamp-based:
'migration_naming' => \Cycle\ORM\Migrations\Generator\Generators\TimestampNameGenerator::class,
Post-Generation Hooks Extend the generator via events (e.g., modify generated SQL before writing):
// EventServiceProvider
protected $listen = [
'Cycle\ORM\Migrations\Generator\Events\MigrationGenerated' => [
\App\Listeners\ModifyGeneratedMigration::class,
],
];
Schema Versioning Generate migrations for a specific schema version:
php artisan cycle:generate-migrations --schema=schema_v2.xml
Foreign Key Constraints
Generated migrations may not handle ON DELETE/UPDATE clauses optimally. Review and adjust manually:
-- Generated (may need tweaking)
ALTER TABLE posts ADD CONSTRAINT posts_user_id_foreign FOREIGN KEY (user_id) REFERENCES users(id);
Data Type Mismatches
Cycle ORM’s text maps to SQL TEXT, but some databases (e.g., MySQL) may need LONGTEXT. Override in schema:
<column name="description" type="text" dbType="LONGTEXT"/>
Transaction Handling Generated migrations lack transactions by default. Wrap in a transaction in your migration class:
public function up()
{
DB::transaction(function () {
// Generated SQL here
});
}
ChangesCountNameGenerator Quirks (Default in 2.3.0)
with_1_change). Review generated names for clarity.'migration_naming' => \Cycle\ORM\Migrations\Generator\Generators\TimestampNameGenerator::class,
Dry Run Mode Preview SQL without writing files:
php artisan cycle:generate-migrations --dry-run
Schema Validation Validate your schema before generation:
php artisan cycle:validate-schema
Logging Enable verbose output for debugging:
php artisan cycle:generate-migrations -vvv
Naming Generator Debugging
Inspect why a migration has an unexpected name with ChangesCountNameGenerator:
php artisan cycle:generate-migrations --dry-run -vvv
Custom Generators
Extend ChangesCountNameGenerator or create a new naming strategy:
use Cycle\ORM\Migrations\Generator\Generators\ChangesCountNameGenerator;
class CustomChangesCountGenerator extends ChangesCountNameGenerator
{
protected function getChangeDescription(int $changeCount): string
{
return $changeCount > 1 ? "changes" : "change";
}
}
Register in GeneratorServiceProvider.
Database-Specific Dialects Override dialect-specific SQL generation (e.g., for PostgreSQL vs. MySQL):
'dialect' => \App\Cycle\Dialects\PostgresDialect::class,
Pre/Post-Processors
Use the MigrationProcessor interface to transform generated SQL:
class AddIndexProcessor implements MigrationProcessor
{
public function process(string $sql): string
{
return preg_replace('/CREATE TABLE/', 'CREATE TABLE IF NOT EXISTS', $sql);
}
}
NO_UPDATE_NEEDED was incorrect—this assessment has been **updated** to reflect the new default `ChangesCountNameGenerator` in 2.3.0 and clarify its implications.
How can I help you explore Laravel packages today?