Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

MichaelLake's avatar

Migrations: Configure a default string length? (utf8mb4)

For forward-compatibilty with emoji and such, I'm configuring my database to use utf8mb4 throughout. I have updated my config/database.php to use utf8mb4:

'mysql' => [
    ...
    'charset'   => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    ...
]

And now my migrations now create tables with utf8mb4 encoding. Awesome! The only problem is that string columns are still set to a length of 255 when they should be only 191.

I know that I can specify a max VARCHAR length in the migration itself:

$table->string('name', 191);

...but I dislike the idea hard-coding fixed numbers for every string colum in the database. I feel like the size argument should only be used for ad hoc overrides, but maybe that's just me.

I'd like to set a default VARCHAR size somewhere and have the migrations use that instead, but I'm not sure where to look. Is there a preferred place for such a configuration to go? Should I just shim it in somehow?

0 likes
7 replies
willvincent's avatar
Level 54

Default values are defined in /vendor/laravel/framework/src/Illuminate/Database/Schema/Blueprint.php as defaults to method params. So the only way you could change that would probably be to make your own implementation of that class, and force eloquent to use it instead. Seems like a lot of work for no real gain. Are you really that concerned about the extra 64 characters? Why not, instead, just either define it in the migration, as it's designed, or implement validation rules to prevent longer values being stored?

willvincent's avatar

Here's another way to think about it -- if you were manually creating these tables in the DB, you'd have to specify their length when writing the SQL queries, it's really no different when writing a migration. I guess I don't see the issue here.

MichaelLake's avatar

You answered my question; I certainly don't want to go mucking around inside Blueprint.php, so I'll just make the field lengths explicit. The reasoning was that I didn't want to have a bunch of repeated code if there was a simpler way to do it that I just didn't know about. :)

From the MySQL Documentation:

InnoDB has a maximum index length of 767 bytes, so for utf8 or utf8mb4 columns, you can index a maximum of 255 or 191 characters, respectively. If you currently have utf8 columns with indexes longer than 191 characters, you will need to index a smaller number of characters.

Having an extra 64 characters actually is important because of the above issue. If the index is unique, then the entire field needs to be indexed, meaning that in this situation, 191 is the max length (and should be enforced by the db, even if we have business logic filtering input). Laravel assumes utf8, so it sets the columns to 255 by default, but this convention needs to be overridden with utf8mb4.

londoh's avatar

@MichaelLake

I've just being looking at utf8mb4 and also came across this problem. I also kinda felt that laravel should cater for utf8mb4, and not just assume the possibly incorrect 255 char length.

I reference some other info here for anybody else coming along:

I found this post on a related github issue:

https://github.com/laravel/framework/issues/2823#issuecomment-172971309

the solution there is pretty much same as @willvincent gives - so I guess thats the way to go then

here's an article as to why utf8mb4 might be important:

https://mathiasbynens.be/notes/mysql-utf8mb4

And apparently its undocumented, but you can set collation at column level using collation() function within migrations:

https://github.com/laravel/framework/issues/8857#issuecomment-136704544

regards

l.

willvincent's avatar

Maybe the best option is to submit a pull request to the laravel codebase that exposes the field length default as a config option...

2 likes

Please or to participate in this conversation.