code is better than words
/**
* Setup: Laravel 5.0, MySQL driver
**/
// Step 1
Schema::table('test_abcd', function(Blueprint $table)
{
// Create a double(8,2), not a float
$table->float('float_test');
// Create a double
$table->double('double_test');
});
// Step 2
Schema::table('test_abcd', function(Blueprint $table)
{
// FATAL Error, see log **1**
$table->float('float_test', 6, 2)->change();
// FATAL Error, too
$table->double('double_test')->change();
});
Log 1
> php.exe X:\xxx\artisan migrate
exception 'Doctrine\DBAL\DBALException' with message 'Unknown column type "double(6, 2)" requested. Any Doctrine type that you use has to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the known types with \Doctrine\DBAL\Types\Type::getTypesMap(). If this error occurs during database introspection then you might have forgot to register all database types for a Doctrine Type. Use AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement Type#getMappedDatabaseTypes(). If the type name is empty you might have a problem with the cache or forgot some mapping information.' in X:\xxx\vendor\doctrine\dbal\lib\Doctrine\DBAL\DBALException.php:228
Stack trace:
#0 X:\xxx\vendor\doctrine\dbal\lib\Doctrine\DBAL\Types\Type.php(172): Doctrine\DBAL\DBALException::unknownColumnType('double(6, 2)')
#1 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Schema\Grammars\Grammar.php(361): Doctrine\DBAL\Types\Type::getType('double(6, 2)')
#2 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Schema\Grammars\Grammar.php(349): Illuminate\Database\Schema\Grammars\Grammar->getDoctrineColumnChangeOptions(Object(Illuminate\Support\Fluent))
#3 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Schema\Grammars\Grammar.php(319): Illuminate\Database\Schema\Grammars\Grammar->getDoctrineColumnForChange(Object(Doctrine\DBAL\Schema\Table), Object(Illuminate\Support\Fluent))
#4 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Schema\Grammars\Grammar.php(303): Illuminate\Database\Schema\Grammars\Grammar->getTableWithColumnChanges(Object(Illuminate\Database\Schema\Blueprint), Object(Doctrine\DBAL\Schema\Table))
#5 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Schema\Grammars\Grammar.php(282): Illuminate\Database\Schema\Grammars\Grammar->getChangedDiff(Object(Illuminate\Database\Schema\Blueprint), Object(Doctrine\DBAL\Schema\MySqlSchemaManager))
#6 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Schema\Blueprint.php(89): Illuminate\Database\Schema\Grammars\Grammar->compileChange(Object(Illuminate\Database\Schema\Blueprint), Object(Illuminate\Support\Fluent), Object(Illuminate\Database\MySqlConnection))
#7 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Schema\Blueprint.php(61): Illuminate\Database\Schema\Blueprint->toSql(Object(Illuminate\Database\MySqlConnection), Object(Illuminate\Database\Schema\Grammars\MySqlGrammar))
#8 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Schema\Builder.php(169): Illuminate\Database\Schema\Blueprint->build(Object(Illuminate\Database\MySqlConnection), Object(Illuminate\Database\Schema\Grammars\MySqlGrammar))
#9 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Schema\Builder.php(94): Illuminate\Database\Schema\Builder->build(Object(Illuminate\Database\Schema\Blueprint))
#10 X:\xxx\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php(213): Illuminate\Database\Schema\Builder->table('manufacturers', Object(Closure))
#11 X:\xxx\database\migrations\2015_02_06_112008_add_test2_to_manufacturers_table.php(19): Illuminate\Support\Facades\Facade::__callStatic('table', Array)
#12 X:\xxx\database\migrations\2015_02_06_112008_add_test2_to_manufacturers_table.php(19): Illuminate\Support\Facades\Schema::table('manufacturers', Object(Closure))
#13 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Migrations\Migrator.php(135): AddTest2ToManufacturersTable->up()
#14 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Migrations\Migrator.php(111): Illuminate\Database\Migrations\Migrator->runUp('2015_02_06_1120...', 3, false)
#15 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Migrations\Migrator.php(82): Illuminate\Database\Migrations\Migrator->runMigrationList(Array, false)
#16 X:\xxx\vendor\laravel\framework\src\Illuminate\Database\Console\Migrations\MigrateCommand.php(73): Illuminate\Database\Migrations\Migrator->run('X:\xxx...', false)
#17 [internal function]: Illuminate\Database\Console\Migrations\MigrateCommand->fire()
#18 X:\xxx\vendor\laravel\framework\src\Illuminate\Container\Container.php(523): call_user_func_array(Array, Array)
#19 X:\xxx\vendor\laravel\framework\src\Illuminate\Console\Command.php(115): Illuminate\Container\Container->call(Array)
#20 X:\xxx\vendor\symfony\console\Symfony\Component\Console\Command\Command.php(253): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#21 X:\xxx\vendor\laravel\framework\src\Illuminate\Console\Command.php(101): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#22 X:\xxx\vendor\symfony\console\Symfony\Component\Console\Application.php(874): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#23 X:\xxx\vendor\symfony\console\Symfony\Component\Console\Application.php(195): Symfony\Component\Console\Application->doRunCommand(Object(Illuminate\Database\Console\Migrations\MigrateCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#24 X:\xxx\vendor\symfony\console\Symfony\Component\Console\Application.php(126): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#25 X:\xxx\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php(91): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#26 X:\xxx\artisan(34): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#27 {main}
Process finished with exit code 1 at 12:26:41.
Execution time: 505 ms.
According to the documentation it should work
It may be worth noting that the decision for a $table->float()
to create a double
in MySQL databases was a deliberate one by Taylor in September.
IlluminateDatabase\Schema\Grammars\MySqlGrammar#L389
I don't know the exact reasons for this.
As for your fatal on ->change()
this obviously shouldn't be happening. Although the documentation doesn't explicitly state that ->change()
should be used to change a column type, I see no reason why it shouldn't be used. I will have a dig later unless someone else takes a look first.
+1 I am having strange errors when using ->change()
in my migrations.
exception 'Doctrine\DBAL\DBALException' with message 'Unknown column type "varchar(255)" requested. Any Doctrine type that you use has to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the known types with \Doctrine\DBAL\Types\Type::getTypesMap(). If this error occurs during database introspection then you might have forgot to register all database types for a Doctrine Type. Use AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement Type#getMappedDatabaseTypes(). If the type name is empty you might have a problem with the cache or forgot some mapping information.' in /home/youanden/projects/aws3/ninjagift/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php:228
From doing this: $t->string('paykey')->change();
which was a integer type column before.
So I had a closer look at this and there are a number of issues at play here.
For ->change()
functionality, doctrine/dbal
is utilised to create a diff between your current table definition and the definition created by your calls to ->change()
before executing the necessary SQL to bring the diffs inline.
At IlluminateDatabase\Schema\Grammars\Grammar#L361, a Doctrine\DBAL\Types\Type
object is instantiated with the illuminate column type. However, ->getType()
on an illuminate column (see Illuminate\Schema\Grammars\MySqlGrammar) for certain column types such as a float will return double(3, 5)
as opposed to float
which is what the DBAL type is expecting. Note that the actual column type is different plus the lack of parameters in the string.
On top of this, the actual comparison diff is generated using Doctrine\DBAL\Schema\Comparator
which only checks precision and scale for DecimalType
columns, not FloatType
columns. So even if the first issue didn't exist and the DBAL type could be instantiated, the diff would come back negative if you had only updated the float precision as in the example from @xeno010.
So in summary, illuminate/database
has an issue with types that are incompatible with Doctrine\DBAL\Types\Type
and doctrine/dbal
has an issue in not checking scale and precision for FloatType
column types in the diff comparator.
I will open a pull request with doctrine for the second issue now. However, I don't have enough knowledge around illuminate/database
to attempt a PR in that department.
@GrahamCampbell I think it would be a good idea to reopen this issue?
I would suggest renaming to Illuminate Grammar types incompatible with Doctrine DBAL types or something similar.
So it turns out that doctrine/dbal
only defines scales and precision for decimal types and doesn't consider them at all for float types (not just in the comparator). This must be for a good reason as it appears to have been a conscious choice.
I'm out of my depth in DBAL land I'm afraid.
Here's hoping that the information above will help towards getting a fix implemented.
It's still happening to me.
Exact same issue here with Laravel 5.6
Will there be any fix for this issue?
@mtaiyabm, try this
use Doctrine\DBAL\Types\FloatType;
use Doctrine\DBAL\Types\Type;
public function up() {
if (!Type::hasType('double')) {
Type::addType('double', FloatType::class);
}
// ...
}
@LastDragon-ru that allows the data type to be set to double - but when looking at the structure after migrating, the number of digits and precision are both set to 0 even when providing params.
@LastDragon-ru, indeed when I try:
$table->double('price')->nullable()->change();
I get:
Doctrine\DBAL\DBALException : Unknown column type "double" requested.
When I add:
use Doctrine\DBAL\Types\FloatType;
use Doctrine\DBAL\Types\Type;
public function up() {
if (!Type::hasType('double')) {
Type::addType('double', FloatType::class);
}
Schema::table('product_options', function($table) {
$table->double('price', 8, 2)->nullable()->change();
});
}
It changes the defaults to null, but it does not set the precision.
The only way I was able to change the precision trough migration was with RAW SQL inside the migration. Still it is so awkward that you can define a double column on creation but can't change it to NULLABLE DOUBLE with the ->change()
. And this is actually on purpose? I am still headbanging why...
PS: For those wondering how to change double column trough RAW SQL:
ALTER TABLE YourTableNameHere MODIFY COLUMN YourColumnNameHere double(8,2) null
Most helpful comment
@mtaiyabm, try this