Laravel migration package publishing order

341 views Asked by At

I'm building a Laravel Package. I need to publish my custom migrations. One migration need another one to be run because it has a foreign key constraint.

In my service provider I'm doing this:

public function boot(Filesystem $filesystem)
    {
        $this->loadMigrationsFrom(dirname(__DIR__).'/migrations');
        $this->publishMigrations($filesystem);    
    }


private function publishMigrations(Filesystem $filesystem)
    {
        if (! class_exists('CreateReferencedTable')) {
            $this->publishes([
                __DIR__ . '/../database/migrations/create_referenced_table.php.stub' => $this->getMigrationFileName($filesystem, 'referenced')              
            ], 'migrations');
        }
        if (! class_exists('CreateExampleTable')) {
            $this->publishes([
                __DIR__ . '/../database/migrations/create_example_table.php.stub' => $this->getMigrationFileName($filesystem, 'example')           
            ], 'migrations');
        }
    }

    protected function getMigrationFileName(Filesystem $filesystem, string $table_name): string
    {
        $timestamp = date('Y_m_d_His');
        return Collection::make($this->app->databasePath().DIRECTORY_SEPARATOR.'migrations'.DIRECTORY_SEPARATOR)
            ->flatMap(function ($path, $table_name) use ($filesystem) {
                return $filesystem->glob($path.'*_create_'.$table_name.'_table.php');
            })->push($this->app->databasePath()."/migrations/{$timestamp}_create_{$table_name}_table.php")
            ->first();
    }

And then I run

php artisan vendor:publish --provider="FedericoArona\MyPackage\Providers\MyServiceProvider" --tag="migrations"

The problem is that the tables are being created with the exact same timestamp so they will be ordered by their name. This means that "Example" migration will be created before "Referenced" migration.

Obviously this means that when I run my migrations, they will fail because "Example" migration need to be run after "Referenced".

How can I solve? Thanks.

1

There are 1 answers

0
instance On

The only approach I've made work is a hack: adjust the timestamps. I put the number of migrations into a property in the provider

$this->migrationCount

and then decrement the timestamp (so if the tick counter increments in the middle of execution it still is different):

    private function migratePath(string $file): string
    {
        $timeKludge = date('Y_m_d_His', time() - --$this->migrationCount);
        return database_path(
            'migrations/' . $timeKludge . "_$file.php"
        );
    }

It's not pretty but it works.