framework: Laravel 5.5/5.6 Changing Columns Not Working

  • Laravel Version: 5.4.x/5.5.x
  • PHP Version: 7.1
  • Database Driver & Version: Postgres

Description:

I have multiple Laravel Schemas on which i want to migrate some migrations. One of my migrations is as following:

    <?php
    
    use Illuminate\Support\Facades\Schema;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Database\Migrations\Migration;
    
    class EditColumnPaymentMethodLengthOnRecurringPaymentsTable extends Migration
    {
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            Schema::table('recurring_payments', function (Blueprint $table) {
                $table->string('payment_method', 150)->nullable()->change();
                $table->text('test')->nullable();
            });
        }
    
        /**
         * Reverse the migrations.
         *
         * @return void
         */
        public function down()
        {
            Schema::table('recurring_payments', function (Blueprint $table) {
                $table->string('payment_method', 18)->nullable()->change();
                $table->dropColumn('test');
            });
        }
    }

What happens is that the new column is added to the database (and dropped if rolledBack) but the column ‘payment_method’ always has the length of 18 characters. Except for the first Schema this one works fine.

This is the command i migrate with:

    <?php
    
    namespace App\Console\Commands;
    
    use App\Account;
    use App\Support\Schema;
    use Illuminate\Console\Command;
    
    class MigrateTenantsCommand extends Command
    {
        /**
         * The name and signature of the console command.
         *
         * @var string
         */
        protected $signature = 'tenant:migrate {--force : Force the operation to run when in production.}
                    {--pretend : Dump the SQL queries that would be run.}
                    {--seed : Indicates if the seed task should be re-run.}
                    {--step : Force the migrations to be run so they can be rolled back individually.}';
    
        /**
         * The console command description.
         *
         * @var string
         */
        protected $description = 'Migrate all tenants';
    
        /**
         * Create a new command instance.
         *
         * @return void
         */
        public function __construct()
        {
            parent::__construct();
        }
    
        /**
         * Execute the console command.
         *
         * @return mixed
         */
        public function handle()
        {
            $tenants = Account::all();
            foreach($tenants as $tenant)
            {
                $schema = new Schema;
    
                // Migrate into the new schema
                $schema->migrate(
                    $tenant->schema,
                    $this->getOptionsFromArgs()
                );
            }
        }
    
        private function getOptionsFromArgs()
        {
            $options = [
                '--path' => 'database/migrations/tenants/schema'
            ];
    
            if($this->option('force'))
            {
                $options['--force'] = true;
            }
            if($this->option('pretend'))
            {
                $options['--pretend'] = true;
            }
            if($this->option('seed'))
            {
                $options['--seed'] = true;
            }
            if($this->option('step'))
            {
                $options['--step'] = true;
            }
            return $options;
        }
    }

someone pointed out to run the command with --pretend. When i did this i got an exception: [Doctrine\DBAL\Schema\SchemaException] There is no column with name 'payment_method' on table 'recurring_payments'.

It is not a problem with the table being there or not. It is probably a problem with Doctrine not finding the right Schema Config and therefor using the public Schema config. In the public schema the table is not present but i don’t want to use the public schema. What i’m doing wrong here, how can I tell Doctrine to use the right Schema config? How is it that Doctrine is finding the right config the first time at least that is wat it looks like.

The Schema/Schema Class of Doctrine:

    public function __construct(
            array $tables = array(),
            array $sequences = array(),
            SchemaConfig $schemaConfig = null,
            array $namespaces = array()
        ) {
            if ($schemaConfig == null) {
                $schemaConfig = new SchemaConfig();
            }
            $this->_schemaConfig = $schemaConfig;

            $this->_setName($schemaConfig->getName() ?: 'public');
    
            foreach ($namespaces as $namespace) {
                $this->createNamespace($namespace);
            }
    
            foreach ($tables as $table) {
                $this->_addTable($table);
            }
    
            foreach ($sequences as $sequence) {
                $this->_addSequence($sequence);
            }
        }

Steps To Reproduce:

  1. add change() to one of your migrations
  2. switch between multiple schema’s

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 27 (10 by maintainers)

Most upvoted comments

I’m using 5.6.24. This problem still exists in this version.

@BasMulders Your issue is not related to this one.

PostgreSQL doesn’t allow inserting columns at a specific position. You can only insert the new column(s) at the end or recreate the whole table.

I came to this issue with the same problem, using Laravel 5.6, where a column I’d changed to nullable was showing as not null in DataGrip.

However after some playing around I realised even though it shows as not null in DataGrip and I can’t change the column to <null> in DataGrip, if I added a new row it would in fact show as nullable.

If you right-click on the column in the sidebar and hit Synchronize it may solve the problem for you.