zoukankan      html  css  js  c++  java
  • UUIDs in Laravel 7

    UUIDs in Laravel 7

    cverster profile imageCornel VersterMay 16 Updated on Jul 07, 2020 ・4 min read

    Recently I had to implement Universally unique identifiers (UUIDs) in Laravel 7, and ran into some problems that I hope this post clears up for others who are doing the same.

    High-level reasons for using UUIDs

    A) They remove numbered IDs from your URLs, so users cannot see how many of a certain object your app has created. E.g.

    https://myapp.com/api/users/5 
    

    vs.

    https://myapp.com/api/users/0892b118-856e-4a15-af0c-66a3a4a28eed
    

    B) They make IDs a lot harder to guess. This is good for security, but we probably should be implementing other techniques to guard against this.

    Implementing UUIDs as primary keys

    How to change your database migrations

    Firstly, you replace your current auto-incrementing integer ID fields with UUIDs in your database migrations. You could also follow the route of keeping auto-incrementing IDs and implementing UUIDs as an additional field on your tables that will be used when exposing URLs to users (in which case you make the ID field hidden in your models), but that is not what we are doing here. Let's see what this would look like for a hypothetical employees table.

        public function up()
        {
            Schema::create('employees', function (Blueprint $table) {
                $table->uuid('id')->primary();
                $table->string('name');
                $table->string('email')->unique();
                $table->string('work_location')->nullable();
                $table->timestamps();
            });
        }
    

    Here, notice we replaced the normal id(); declaration with uuid(); and made it the primary key.

    Let's make that a Trait

    Next, we can implement a Laravel lifecycle hook to make sure that a UUID is assigned when a new instance of this model is created. We could code this directly in the model, but if you're going to use UUIDs on more than one model, I suggest using a Trait instead (Kudos to Wilbur Powery who I learned this from in this Dev post). A trait basically allows you to create functionality, and use that functionality in more than one model by calling it with the use keyword.

    To create a new Trait, create a AppHttpTraits folder (only my preference, you can put it somewhere else too), and also a new file for the Trait. We will call the file UsesUuid.php.

    FilePath

    Here is the code for the trait:

    <?php
    
    namespace AppHttpTraits;
    
    use IlluminateSupportStr;
    
    trait UsesUuid
    {
      protected static function bootUsesUuid() {
        static::creating(function ($model) {
          if (! $model->getKey()) {
            $model->{$model->getKeyName()} = (string) Str::uuid();
          }
        });
      }
    
      public function getIncrementing()
      {
          return false;
      }
    
      public function getKeyType()
      {
          return 'string';
      }
    }
    

    Here, we use the IlluminateSupportStr class to easily generate UUIDs. The getIncrementing() method tells Laravel that the IDs on this model will not be incrementing (as we are returning false), and the getKeyType() method tells Laravel the primary key will be of type string. The bootUsesUuid() method allows us to tap the power of Laravel lifecycle hooks. You can learn more about those here. Basically, our code is telling Laravel that when a new instance of this model is being created, generate a UUID primary key for it!

    Now, we can easily implement this trait on a model with the use keyword.

    <?php
    
    namespace App;
    
    use IlluminateDatabaseEloquentModel;
    ...
    
    class Employee extends Model
    {
        ...
        use AppHttpTraitsUsesUuid;
        ...
    }
    

    Referencing UUIDs as foreign keys

    To reference a UUID on a table as a foreign key, you simply change the type of the foreign key field on your table. For example, this...

     Schema::create('another_table', function(Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('employee_id');
            $table->string('some_field');
    
            $table->foreign('employee_id')
                ->references('id')
                ->on('shifts')
                ->onDelete('cascade');
        });
    

    ... where we created a unsignedBigInteger to reference the employee_id foreign key, changes to this:

     Schema::create('another_table', function(Blueprint $table) {
            $table->id();
            $table->uuid('employee_id');
            $table->string('some_field');
    
            $table->foreign('employee_id')
                ->references('id')
                ->on('shifts')
                ->onDelete('cascade');
        });
    

    Easy as that! One more thing though...

    UUIDs and polymorphic relationships

    You might find that your model gets referenced in polymorphic relationships, either by your own doing or by a package that you are pulling in. The table might look something like this in the migration:

        public function up()
        {
            Schema::create('some_package_table', function (Blueprint $table) 
            {
                $table->bigIncrements('id');
                $table->morphs('model');
                ...
            }
        }
    

    Here, the morphs() method is going to create two fields in your database, namely model_id of type unsignedBigInteger and model_type of type string. The problem is that our model is now using a UUID instead of the incrementing integer ID, so this is going to give you and error that says something like:

    Data truncated for column 'model_id' at row 1
    

    We need the model_id field to now support our new UUID which is of type CHAR(36). Not to worry! Laravel makes this super easy, and you don't have to do that manually. Simply change the migration to this:

        public function up()
        {
            Schema::create('some_package_table', function (Blueprint $table) 
            {
                $table->bigIncrements('id');
                $table->uuidMorphs('model');
                ...
            }
        }
    

    Another reason to love Laravel! Happy coding!

  • 相关阅读:
    Eclipse常用快捷键
    Kali Linux安装Google中文输入法(只需5步)
    Kali Linux 更新源 操作完整版教程
    Oracle存储过程的异常处理
    Eclipse调试DEBUG时快速查看某个变量的值的快捷键、快速跳转到某行的快捷键
    oracle listagg和wm_concat函数
    ORACLE分页查询SQL语法——最高效的分页
    Mock拦截请求URL返回模板数据
    前端安全之XSS攻击及防御
    Sublime Text3注册码,亲测可用
  • 原文地址:https://www.cnblogs.com/mouseleo/p/13904944.html
Copyright © 2011-2022 走看看