Home > Mobile >  Laravel: Stop using UUID as foreign key
Laravel: Stop using UUID as foreign key

Time:11-14

Laravel is trying to use uuid field as foreign key. And I want to use foreign key with the field id. Is there any option there?

Using this trait on Model. And then it is trying to use the uuid as foreign key. But still I want to use id as foreign key.

<?php

namespace App\Library;

use Ramsey\Uuid\Uuid;

trait UsesUuid
{
    /**
     * @return string
     */
    public function getKeyName()
    {
        return 'uuid';
    }

    /**
     * @return string
     */
    public function getKeyType()
    {
        return 'string';
    }

    /**
     * @return false
     */
    public function getIncrementing()
    {
        return false;
    }

    /**
     * @param $query
     * @param $uuid
     * @return mixed
     */
    public function scopeUuid($query, $uuid)
    {
        return $query->where($this->getUuidName(), $uuid);
    }

    /**
     * @return string
     */
    public function getUuidName()
    {
        return property_exists($this, 'uuidName') ? $this->uuidName : 'uuid';
    }

    /**
     * @return string
     */
    public function getRouteKeyName()
    {
        return property_exists($this, 'uuidName') ? $this->uuidName : 'uuid';
    }

    /**
     *
     */
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            $model->{$model->getUuidName()} = Uuid::uuid4()->toString();
        });
    }
}

CodePudding user response:

There is nothing special about this trait. You can make your own trait with id instead of uuid and everything will work fine.

CodePudding user response:

The issue came from methods getIncrementing() and getKeyName(). Laravel calls getKeyName() in amount of built-in functions to interacts with relationships, also other actions like delete(), route bindings, etc.

You should allow any models which uses this trait to custom the Primary key (PK), so that uuid is only common column at all.

Your trait definition is force PK column as uuid.

Below is my recommended for the trait

<?php

namespace App\Library;

use Ramsey\Uuid\Uuid;

trait UsesUuid
{
    /* Override this method to set `uuid` as PK */
    public function isUuidAsPrimaryKey()
    {
        return false;
    }

    /**
     * @return string
     */
    public function getKeyName()
    {
        return $this->isUuidAsPrimaryKey() ? $this->getUuidName() : $this->primaryKey;
    }

    /**
     * @return string
     */
    public function getKeyType()
    {
        return $this->isUuidAsPrimaryKey() ? 'string' : $this->keyType;
    }

    /**
     * @return false
     */
    public function getIncrementing()
    {
        return !$this->isUuidAsPrimaryKey();
    }

    /**
     * @param $query
     * @param $uuid
     * @return mixed
     */
    public function scopeUuid($query, $uuid)
    {
        return $query->where($this->getUuidName(), $uuid);
    }

    /**
     * @return string
     */
    public function getUuidName()
    {
        return property_exists($this, 'uuidName') ? $this->uuidName : 'uuid';
    }

    /**
     * @return string
     */
    public function getRouteKeyName()
    {
        return property_exists($this, 'uuidName') ? $this->uuidName : 'uuid';
    }

    /**
     *
     */
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            $model->{$model->getUuidName()} = Uuid::uuid4()->toString();
        });
    }
}

If a model need to have uuid as PK, for example Book model

class Book extends Model
{
    use UsesUuid;

    public function isUuidAsPrimaryKey()
    {
        return true;
    }
}

Please recheck the method isUuidAsPrimaryKey. If it may not be overridden (due to conflict), then use a property instead.

  • Related