dinist

[Laravel] - Eloquent에서 Enum 활용 본문

Web/PHP

[Laravel] - Eloquent에서 Enum 활용

dinist 2023. 5. 24. 18:02

PHP 8.1 버전부터 Enum을 사용할 수 있어서 이를 활용해 보고 싶었습니다.

 

테스트용 DB 테이블과 더미데이터, 그리고 Eloquent를 활용한 select 테스트까지 진행해 보겠습니다.

 

PHP - 8.2.5

Laravel  -  10.12

php artisan make:model -fms	// model, factory, migration, seeder

artisan 명령으로 모델, 팩토리, 마이그레이션, 시더를 모두 만듭니다.

 

- Migration

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('phones', function (Blueprint $table) {
            $table->id('idx');
            $table->char('grade');
            $table->string('model');
            $table->string('description');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('phones');
    }
};

이후 php artisan migrate 해줍니다.

 

- Enum

phones 테이블에 grade 컬럼과 매칭될 Enum을 만듭니다.

<?php

namespace App\Enum;

enum PhoneGrade: string
{
    case Excellent = 'A';
    case Normal = 'B';
    case Bad = 'C';
    case Poor = 'D';

    public static function getRandomPhoneGrade() : PhoneGrade
    {
        $cases = PhoneGrade::cases();
        return $cases[array_rand($cases)];
    }
}

 

- Model

phone 모델을 수정합니다. (enum으로 캐스팅할 컬럼과, timestamp가 없으므로 timestamp false 설정을 해야합니다.)

<?php

namespace App\Models;

use App\Enum\PhoneGrade;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Phone extends Model
{
    use HasFactory;

    public $timestamps = false;
    
    protected $casts = [
        'grade' => PhoneGrade::class
    ];
}

 

- Factory

<?php

namespace Database\Factories;

use App\Enum\PhoneGrade;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Phone>
 */
class PhoneFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'grade' => PhoneGrade::getRandomPhoneGrade(),
            'model' => fake()->word(),
            'description' => fake()->realText(50),
        ];
    }
}

 

- Seeder

시딩은 10개만 합니다!

<?php

namespace Database\Seeders;

use App\Models\Phone;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class PhoneSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        Phone::factory()->count(10)->create();
    }
}

 

php artisan db:seed --class=PhoneSeeder 로 시딩을 진행합니다.

 

더미 데이터들이 입력되었습니다. 이제 select를 테스트 해봅시다.

php artisan make:test PhoneDBTest 로 테스트 파일을 만듭니다.

 

<?php

namespace Tests\Feature;

use App\Models\Phone;
use Tests\TestCase;

class PhoneDBTest extends TestCase
{
    public function test(){
        $firstData = Phone::all()->get(0);
        dd($firstData->grade,$firstData->attributesToArray());
    }
}

 

grade 컬럼 값은 PhoneGrade Enum을 가져온 것을 확인할 수 있습니다.

App\Enum\PhoneGrade {#1866 // tests\Feature\PhoneDBTest.php:15
  +name: "Excellent"
  +value: "A"
}

array:4 [ // tests\Feature\PhoneDBTest.php:15
  "idx" => 1
  "grade" => "A"
  "model" => "dolorum"
  "description" => "Majesty must cross-examine the next witness!'."
]