4

I'm trying to set an uuid as primary key in a Laravel Model. I've done it setting a boot method in my model as stablished here so I don't have to manually create it everytime I want to create and save the model. I have a controller that just creates the model and saves it in database.

It is saved correctly in database but when controller returns the value of the id is always returned with 0. How can I make it to actually return the value that it is creating in database?

Model

class UserPersona extends Model
{
    protected $guarded = [];

    protected $casts = [
        'id' => 'string'
    ];

    /**
     *  Setup model event hooks
     */
    public static function boot()
    {
        parent::boot();
        self::creating(function ($model) {
            $uuid = Uuid::uuid4();
            $model->id = $uuid->toString();
        });
    }
}

Controller

class UserPersonaController extends Controller
{
    public function new(Request $request)
    {
        return UserPersona::create();
    }
}
Alberto
  • 1,348
  • 2
  • 14
  • 28

2 Answers2

5

You need to change the keyType to string and incrementing to false. Since it's not incrementing.

public $incrementing = false;
protected $keyType = 'string';

Additionally I have an trait which I simply add to those models which have UUID keys. Which is pretty flexible. This comes originally from https://garrettstjohn.com/articles/using-uuid-laravel-eloquent-orm/ and I added some small adjustments to it for issues which I have discovered while using it intensively.

use Illuminate\Database\Eloquent\Model;
use Ramsey\Uuid\Uuid;

/**
 * Class Uuid.
 * Manages the usage of creating UUID values for primary keys. Drop into your models as
 * per normal to use this functionality. Works right out of the box.
 * Taken from: http://garrettstjohn.com/entry/using-uuids-laravel-eloquent-orm/
 */
trait UuidForKey
{

    /**
     * The "booting" method of the model.
     */
    public static function bootUuidForKey()
    {
        static::retrieved(function (Model $model) {
            $model->incrementing = false;  // this is used after instance is loaded from DB
        });

        static::creating(function (Model $model) {
            $model->incrementing = false; // this is used for new instances

            if (empty($model->{$model->getKeyName()})) { // if it's not empty, then we want to use a specific id
                $model->{$model->getKeyName()} = (string)Uuid::uuid4();
            }
        });
    }

    public function initializeUuidForKey()
    {
        $this->keyType = 'string';
    }
}

Hope this helps.

Christoph Kluge
  • 1,947
  • 8
  • 23
2

Since Laravel 9 you can use build-in traits HasUuids or HasUlids to support UUID or ULID for Eloquent.

This is sample of model class:

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

class ModelName extends Model
{
    use HasUuids;
    
    // ...
}
AnasSafi
  • 5,353
  • 1
  • 35
  • 38
  • 1
    In Laravel 9 using the built in `Illuminate\Database\Eloquent\Concerns\HasUuids` inside your Model also works. – Hmerman6006 Mar 29 '23 at 12:09