framework: Schema Builder: Error when changing a column to a tinyInteger
When modifying a column to be a tinyint like so (previously a VARCHAR(10) )
Schema::table('graphic_megapacks', function($table) {
$table->tinyInteger('game_id')->change();
});
The following error is given:
DBALException in DBALException.php line 228: Unknown column type “tinyinteger” 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.
“getTypesMap()” returns the following:
array:19 [▼ “array” => “Doctrine\DBAL\Types\ArrayType” “simple_array” => “Doctrine\DBAL\Types\SimpleArrayType” “json_array” => “Doctrine\DBAL\Types\JsonArrayType” “object” => “Doctrine\DBAL\Types\ObjectType” “boolean” => “Doctrine\DBAL\Types\BooleanType” “integer” => “Doctrine\DBAL\Types\IntegerType” “smallint” => “Doctrine\DBAL\Types\SmallIntType” “bigint” => “Doctrine\DBAL\Types\BigIntType” “string” => “Doctrine\DBAL\Types\StringType” “text” => “Doctrine\DBAL\Types\TextType” “datetime” => “Doctrine\DBAL\Types\DateTimeType” “datetimetz” => “Doctrine\DBAL\Types\DateTimeTzType” “date” => “Doctrine\DBAL\Types\DateType” “time” => “Doctrine\DBAL\Types\TimeType” “decimal” => “Doctrine\DBAL\Types\DecimalType” “float” => “Doctrine\DBAL\Types\FloatType” “binary” => “Doctrine\DBAL\Types\BinaryType” “blob” => “Doctrine\DBAL\Types\BlobType” “guid” => “Doctrine\DBAL\Types\GuidType” ]
Creating a tinyInteger column works fine, it’s only when modifying a column that the error occurs
//This works fine
Schema::table('graphic_megapacks', function($table) {
$table->tinyInteger('test');
});
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 28
- Comments: 74 (36 by maintainers)
Links to this issue
Commits related to this issue
- pkp/pkp-lib#2493 Use smallInteger or boolean instead of tinyInt (https://github.com/laravel/framework/issues/8840) — committed to pkp/pkp-lib by asmecher 4 years ago
- pkp/pkp-lib#2493 Use smallInteger or boolean instead of tinyInt (https://github.com/laravel/framework/issues/8840) — committed to pkp/ojs by asmecher 4 years ago
- pkp/pkp-lib#2493 Use smallInteger or boolean instead of tinyInt (https://github.com/laravel/framework/issues/8840) — committed to pkp/usageStats by asmecher 4 years ago
- pkp/pkp-lib#2493 Use smallInteger or boolean instead of tinyInt (https://github.com/laravel/framework/issues/8840) — committed to pkp/omp by asmecher 4 years ago
+1
Tried to convert
FLOAT
to unsignedTINYINT
.My solution was to convert it to
SMALLINT
first:You didn’t need me to tell you that.
It was not closed without comment. The comment is here:
Wow Google a problem and its my own issue from 4 years ago!
The above conversation is all very confusing and at times contradictory, so here’s documentation on what to actually do…
The
TinyInteger
class is not bundled and you must write your own.Here is an example from a test https://github.com/laravel/framework/blob/841a28067b03979603e41dd80729cb8581a91e95/tests/Integration/Database/Fixtures/TinyInteger.php
I placed it in App\Doctrine\TinyInteger.php but you can place it anywhere.
Then use this is in your migration file.
@JacksonIV what is the thinking behind not making the TinyInteger class available within the Laravel Framework itself?
That’s not your comment. How are we supposed to know you’ve chosen that comment out of the 40 in this thread, as the reason to close? Even so, this whole thread is full of people disagreeing with that notion… can you not do what @lucasvscn said and make a Doctrine plugin?
Solution:
public function up() { DB::statement('ALTER TABLE application_activities CHANGE application_status application_status TINYINT(3) UNSIGNED NULL DEFAULT NULL;'); }
It’s annoying that Laravel and Doctrine are now both saying ‘it’s not our fault, won’t fix’.
Doctrine has this page on RTD if it’s any use as a starting point? http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/cookbook/mysql-enums.html
Custom types can then be registered to handle tiny-ints, medium-ints, enums & more across different DB types?
GrahamCampbell wrote:
ganey wrote:
The problem is certainly solvable on the Laravel side, since Doctrine provides an api to register custom types. Laravel migrations should make use of that. I don’t see a reason, why they shouldn’t. See https://blog.intelligentbee.com/2017/06/26/add-tinyint-mysql-doctrine-symfony-2-8/.
@GrahamCampbell Please comment on why this was closed? At least give us an idea here so people can figure out how to fix the problem otherwise. Closing an issue with this many active people still commenting on it, without at least an explanation, isn’t helpful at all.
@GrahamCampbell I’d like to know why this issue was closed as well. Simply using
boolean()
instead does not work if you want theTINYINT
to beUNSIGNED
.To solve problem with foreign key you need to create UnsignedTinyInteger class
And add it to your migration
See that’s helpful. This could’ve been done three months ago.
+1. I ran into this today while writing a migration to convert a boolean column into a tinyint.
@GrahamCampbell, why was this issue closed?
Secondly, Laravel provides means to solve this problem, below is complete solution for MySQL for both
TINYINT
andTINYINT UNSIGNED
. I’m using Laravel 10 and PHP 8.1 here, probably works for other versions.app/Doctrine/TinyInteger.php
:config/database.php
:That is enough, now your Laravel project knows TINYINT, no special code needed in migrations in contradistinction to other solutions above. This approach is tested and should be good enough for single type of database. You may rewrite method
getSQLDeclaration
for your database of choice. If you want to support multiple types of databases, you will need to refactorgetSQLDeclaration
: it is better to move all real logic to separate Grammar classes (MysqlGrammar, PostgresqlGrammar, etc.) and choose appropriate one using condition$platform instanceof
.Inspired by
Doctrine\DBAL\Types\SmallIntType
and Laravel documentation https://laravel.com/docs/10.x/migrations#modifying-columns-on-sqliteHope it helps to someone.
I’m having the same issue with mediumInteger().
While I agree that this is a Doctrine issue/inconsistency; they just confirmed that they won’t be fixing it.
Could this please be reconsidered to be added to Laravel to avoid a mess in migrations just to set an initial (non-default) value to new, non-nullable columns. (docs & implementation example)
It is not a laravel bug. Please take it up with doctrine.
I agree. I think it can be solved on Laravel’s side, however this seems to have been going on a long time so for now I’ve created a simple trait that maps missing Laravel data types to the (hopefully) most appropriate SQLite types. It also handles the
Cannot add a NOT NULL column with default value NULL
when you try to add a non-nullable column to an existing table. Let me know if it helps and whether something like this makes sense as a PR.After so much, still, it didn’t work. So, I used raw query.
Going to re-open this here to prevent duplicate issues coming up (if possible).
@sergey-rud Comment Link
Perfect. It hasn’t been fixed for years.This is the best way.
Confirmed the above solution works great.
I come from JavaScript land, so PHP isn’t my strong suit. For others like me:
In Laravel 5.8, the folder is
app
, so you can place the file inapp\Doctrine\TinyInteger.php
, and you will have to create the Doctrine folder because it likely won’t exist.Don’t forget to put
<? php
at the top of that TinyInteger.php file or you won’t have any syntax highlighting in the file, and you will also experience some haywire behaviour when you try to run the migration (lol)Make sure you do
composer require doctrine/dbal
to install DBAL before attempting to run the migration.Besides those points, you should be able to copy/paste the
TinyInteger.php
code and use it as is, including the import declarations. I am currently uncertain how those two extra methods are being used:getSQLDeclaration
, andgetName
, but I assume DBAL is using them. Otherwise they are cruft in the context of this example code.How come this is still open ??? Is there not a solution to this ?
This work Schema::table(‘graphic_megapacks’, function($table) { $table->boolean(‘game_id’)->change(); });
As a workaround you may be able to use boolean, which at least in MySQL seems to be functionally identical to tinyint.
see: http://dev.mysql.com/doc/refman/5.0/en/numeric-type-overview.html
So after 7 years this still hasn’t been fixed? I’ve just run into the issue.
When I add both
TINYINT
andTINYINT UNSIGNED
custom mapping, only the first one is ever used.Just want to clarify that #28214 actually already implements tinyInteger as a custom class… for MySQL (notably SQLite & SQL Server are still missing at this point)
@GrahamCampbell Why was this closed yet again without comment?
@srmklive since Laravel Schema/Blueprint does implement a tinyInteger column type, it should provide a plugin for Doctrine/DBAL that makes framework run as expected in both situations: placing a new column, or changing it.
That’s for requests, not bugs.
Take a look at this comprehensive list of types available in
doctrine/dbal
: Types reference.Tinyint is only mentioned there as an implementation of the boolean type in the mapping matrix. Quickly skimming through the source code doesn’t show
doctrine/dbal
working with tinyint other than as tinyint(1) for a boolean implementation.It’s hard to read through their issues because they are being imported via/from JIRA, but this looks closest to describing the issue at hand but has been closed by a bot for whatever reason:
https://github.com/doctrine/dbal/issues/2011 - notably the last comment
So summarized:
doctrine/dbal
doesn’t seem to have support fortinyint
other thantinyint(1)
.I do think that currently this is a flaw in the Laravel Schema component as it erroneously assumes that
doctrine/dbal
can create correctly sizedtinyint
fields (and other*int
fields too, according to comments here). So options are replacingdoctrine/dbal
with a proper dbal, waiting fordoctrine/dbal
to be fixed, band-aid fixing it by disablingtinyInteger()
methods and the like or add ad hoc fixes to the schema component generating the correct database platform queries.2c
+1
Laravel 5.2.19 My column NOT NULL, now I want to make it nullable:
$table->unsignedTinyInteger('application_status')->nullable()->change();
Doesn’t work, throws error:
@taylorotwell We have a legitimate bug here; but I believe the worst problem is the fact that it was closed by @GrahamCampbell without any comment whatsoever.
@GrahamCampbell this is a reproducible bug. I hit it with mediumInteger(). Can you clarify why this issue was closed? Are you seeing something we are not?
Edit: The workaround did not work for me. I did not get an error, but after the migrations run the database does not show a mediumInt.
+1 having the same issue. Why has the issues being closed?