laravel10 主キーをuuidに変更したテーブルで設定ミスでfactoryでデータ作っても主キーがuuidで生成されない

# 概要

- 主キーをuuidに変更したverify_emailsテーブルに、テストの最にfactoryでデータを作成しようと試みた。factory内部ではuuidが生成されているのに、factoryの戻り値であるモデルクラスではなぜかuuid文字列ではなく、intの0が返される。この問題の原因と解消方法をまとめる。

# 問題までの経緯

### テーブル作成

- 下記のようなスキーマのverify_emailsテーブルを作成した。

    | No | カラム名 | タイプ | キー |
    | --- | --- | --- | --- |
    | 1 | verify_code | uuid | PK |
    | 2 | email | varchar(255) |  |
    | 3 | created_at | timestamp |  |

- マイグレーションのupメソッドを下記に抜粋

    ```php
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('verify_emails', function (Blueprint $table) {
            $table->uuid('verify_code')->primary()->comment('認証用コード');
            $table->string('email')->comment('メールアドレス');
            $table->timestamps();
        });
    }
    ```

### モデルの記載

- verify_emailsテーブルにリンクするモデルクラスを下記のように記載した。

    ```php
    <?php
    
    declare(strict_types=1);
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    
    class VerifyEmail extends Model
    {
        use HasFactory;
    
        /**
         * 主キー
         *
         * @var string
         */
        protected $primaryKey = 'verify_code';
    
        /**
         * 一括代入の許可
         *
         * @var array<int, string>
         */
        protected $fillable = [
            'verify_code',
            'email',
        ];
    }
    ```

### ファクトリの記載

- ファクトリを下記のように記載した。

    ```php
    <?php
    
    declare(strict_types=1);
    
    namespace Database\Factories;
    
    use Illuminate\Database\Eloquent\Factories\Factory;
    use App\Models\Auth\VerifyEmail;
    
    /**
     * @extends \Illuminate\Database\Eloquent\Factories\Factory<VerifyEmail>
     */
    class VerifyEmailFactory extends Factory
    {
        /**
         * Define the model's default state.
         *
         * @return array<string, string>
         */
        public function definition(): array
        {
            return [
                'verify_code' => $this->faker->uuid(),
                'email' => $this->faker->unique()->safeEmail(),
            ];
        }
    }
    ```

### テストコード

- テストコードにて下記のようにファクトリを呼び出しテストデータを作成した。

    ```php
    $this->verifyEmailModel = VerifyEmailModel::factory()->createOne();
    ```

# 問題

- 下記のようにファクトリで作成した情報のverify_codeが`0`になってしまう。（$this->verifyEmailModelをddして確認）

    ```php
    #original: array:4 [
        "verify_code" => 0
        "email" => "emil.kirlin@example.com"
        "updated_at" => "2023-06-03 04:50:07"
        "created_at" => "2023-06-03 04:50:07"
    ]
    ```

# 問題解消までの経緯

- モデルクラスで`$keyType`と`$incrementing`の変数をオーバーライドすることを忘れていた。
- 下記のようにモデルクラスを修正すると無事動作した。

    ```php
    <?php
    
    declare(strict_types=1);
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    
    class VerifyEmail extends Model
    {
        use HasFactory;
    
        /**
         * 主キー
         *
         * @var string
         */
        protected $primaryKey = 'verify_code';
    
        /**
         * 主キーの型
         *
         * @var string
         */
        protected $keyType = 'string';
    
        /**
         * 主キーのインクリメント設定
         *
         * @var boolean
         */
        public $incrementing = false;
    
        /**
         * 一括代入の許可
         *
         * @var array<int, string>
         */
        protected $fillable = [
            'verify_code',
            'email',
        ];
    }
    ```


# 参考文献

https://www.hypertextcandy.com/laravel-primary-key-uuid

https://qiita.com/shir01earn/items/0abd790438824bae9fc5

https://qiita.com/ucan-lab/items/a8374ba421fe7828dcb9