Native UUID support in Laravel has arrived

In a recent addition native UUID support (and native ULID support) is added by Dries Vints. It’s a great addition for me, as in many applications I tend to favor UUIDs over incremental IDs. I won’t bother you with the discussion of UUIDs vs. incremental IDs in this blog post, but just take a look at the UUID implementation in Laravel.

UUID in Eloquent

As with a lot of functionality in Laravel, the UUID support is really easy to add to any model. Just add the HasUuids trait:

use Illuminate\\Database\\Eloquent\\Concerns\\HasUuids;
use Illuminate\\Database\\Eloquent\\Model;

class Post extends Model 
{
    use HasUuids;
}

When you create a model, it will automatically contain a UUID as a key. The trait will automatically set the keyType property to string and the getIncremeting method to return false.

By default, Laravel generates an ordered UUID with this trait.

For more information about those ordered UUID’s, read this blog by Italo Baeza Cabera. There’s currently a draft about new UUID types, which also contains a time ordered version.

Change the UUID type

As stated above, Laravel uses ordered UUIDs by default. If your application requires UUID V4 or even UUID V1, you’re able to achieve that with a small addition.

When you want to change the type of UUID used, you should override the newUniqueId method from the trait with your own version:

public function newUniqueId()
{
    return (string)Str::uuid();
}

This method can be added to the model. When you need this in all your models, you could create an abstract Model class:

abstract class AppModel 
{
    use HasUuids;

    public function newUniqueId()
    {
        return (string)Str::uuid();
    }
}

class Post extends AppModel
{

}

Issue with saving without events

With incremental IDs, the ID is generated by the database. So you will be able to save a model without providing an ID and the database will take care of that.

Some databases aren’t able to generate UUIDs by default (or not easily). That’s why this implementation uses the creating Eloquent model event in the trait boot. This catches the event and sets the UUID for the unique ids. So the main difference is that the IDs are generated in the application instead of in the database.

Read this blog post of Simon Archer to learn more about booting traits with Eloquent.

A side effect of using the creating model event is that it depends on these events. Laravel also offers functionality to save a model without triggering the events, with for example the saveQuietly method. That method doesn’t trigger the model events. In this case, that would result in a model without a generated UUID.

So the code below will most likely result in a database error saying the id field has no default value:

$post = new Post();
$post->title = 'UUID test';
$post->saveQuietly();

If you need to save a model without triggering the events, the solution is to provide the UUID yourself:

$post = new Post();
$post->id = (string)Str::orderedUuid();
$post->title = 'UUID test';
$post->saveQuietly();

When using mass assignment, this could mean you need to unguard the model or add the id field to the $fillable array.

You usually shouldn’t want to use the saveQuietly methods, but in seeders for example, it could be handy.

TLDR

UUID support works as easily as possible, by just adding the HasUuids trait to your models. Be aware that it requires the model events to be fired so saving the model quietly doesn’t provide a UUID to your model.