phinx icon indicating copy to clipboard operation
phinx copied to clipboard

Non-set keys should not be altered

Open dereuromark opened this issue 8 years ago • 3 comments

Moved https://github.com/cakephp/migrations/issues/330 over to here.

Currently

		$table->changeColumn('status', 'string', [
			'encoding' => 'utf8mb4',
			'collation' => 'utf8mb4_unicode_ci',
		]);

Kills most other settings like

			'null' => true,
			'default' => null,

Silently changing the other table field properties here now makes inserts impossible without specifying these now non-null-default values.

One always needs to check and add all those into every changeColumn, instead of just altering what is defined here in the migration file. This leads to some really dangerous DB regressions. Maybe we can merge with existing scheme before applying?

dereuromark avatar Oct 20 '17 12:10 dereuromark

Merging with existing schema would be great. I created a migration that picks a column from the result of getColumns(), set some options and cal changeColumn. It works, but adding this feature to the core might have to much impact. Implementing #1400 would be an intermediate step.

martijngastkemper avatar Jul 05 '18 10:07 martijngastkemper

For what's its worth, it's fairly easy to create a helper method to do this, which I've added here in case it helps someone:

use Phinx\Db\Table\Column;

class PhinxColumnHelper extends Column
{
    public function change_options(Column $column, Array $new_options): array {

        $valid_options = $this->getValidOptions();

        $options = [];

        foreach ($valid_options as $option) {
            $method = 'get' . ucfirst($option);
            $result = $column->$method();
            if (!is_null($result)) {
                $options[$option] = $column->$method();
            }
        }

        return array_merge($options, $new_options);

    }
}

Example within a change() method in a migration:


public function change(): void
 {
    $column_helper = new PhinxColumnHelper();

    $this->table('table_name')
      ->changeColumn(
        'column_name',
        $this->table('table_name')->getColumn('column_name')->getType(),
        $column_helper->change_options(
          $this->table('table_name')->getColumn('column_name'),
          ['comment' => 'New comment']
        )
      )
      ->update();
}

By the way, I see you cannot reverse a changeColumn command (ProxyAdaptor::getInvertedCommands()). It would be great if this could be documented on the commands page (https://book.cakephp.org/phinx/0/en/commands.html#the-rollback-command).

neilt1700 avatar Oct 18 '23 13:10 neilt1700