skip to Main Content

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 AppLibrary;

use RamseyUuidUuid;

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();
        });
    }
}

2

Answers


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

    Login or Signup to reply.
  2. 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 AppLibrary;
    
    use RamseyUuidUuid;
    
    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search