박유성의 라라벨 블로그

Eloquent ORM - Relationships (1부) 본문

라라벨 기본 파헤치기

Eloquent ORM - Relationships (1부)

Matt.park 2020. 9. 27. 22:46

Eloquent의 Relationship 처리는 심플한 코드와 더불어 여러 타입의 관계를 지원한다. Relationship 조작 시 생략 가능한 Primary Key 혹은 Foreign Key명으로 테이블이 만들어져 있다면 사용이 훨씬 간편해질 것이다.

 

하지만 대부분의 테이블들은 내 마음처럼 만들어져 있지 않다.

 

이처럼 내 맘 같지 않은 테이블들의 정보를 가지고 Eloquent의 Relationship의 각각의 타입별로 옵션 인자들을 예제와 함께 공부해 보는 시간을 가지려고 한다.

 

테스트 환경

시나리오

총 3개의 테이블을 생성하여 다양한 형태의 relatoinship을 표현해 줄 것이다.

  • Users ( 회원 )

  • Cars ( 자동차 )

  • CarUser ( 회원이 보유한 자동차 )

마이그레이션 파일 생성

총 3개의 테이블을 생성해 보자

$ php artisan make:migration create_users_table

$ php artisan make:migration create_cars_table

$ php artisan make:migration create_car_user_table

모든 테이블의 컬럼명들은 사용하면 욕먹을 것 같은 이름들로 지어준다.

<?php

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

/**
 * Class CreateUsersTable
 */
class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create(
            'users',
            function (Blueprint $table) {
                $table->id('user_id');
                $table->string('name');
                $table->timestamps();
            }
        );
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}
<?php

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

/**
 * Class CreateCarsTable
 */
class CreateCarsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create(
            'cars',
            function (Blueprint $table) {
                $table->id('card_id');
                $table->string('car_name');
                $table->integer('price');
                $table->timestamp('release_date')->nullable();
                $table->timestamps();
            }
        );
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('cars');
    }
}
<?php

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

/**
 * Class CreateCarUserTable
 */
class CreateCarUserTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create(
            'car_user',
            function (Blueprint $table) {
                $table->id('user_car_id');
                $table->bigInteger('user_pk_id');
                $table->bigInteger('car_pk_id');
                $table->string('note');
                $table->timestamps();
            }
        );
    }

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

마이그레이션 실행

$ php artisan migrate

Model 생성

$ php artisan make:model User

$ php artisan make:model Car

$ php artisan make:model UserCar
// app/Models/Car.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

/**
 * Class Car
 * @package App\Models
 */
class Car extends Model
{
    use HasFactory;

    /**
     * @var string
     */
    protected $primaryKey = 'car_id';
    /**
     * @var string[]
     */
    protected $guarded = ['car_id'];

}
// app/Models/User.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

/**
 * Class User
 * @package App\Models
 */
class User extends Model
{
    use HasFactory;

    /**
     * @var string
     */
    protected $primaryKey = 'user_id';
    /**
     * @var string[]
     */
    protected $guarded = ['user_id'];
}
// app/Models/CarUser.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

/**
 * Class CarUser
 * @package App\Models
 */
class CarUser extends Model
{
    use HasFactory;

    /**
     * @var string
     */
    protected $table = 'car_user';
    /**
     * @var string[]
     */
    protected $guarded = ['car_user_id'];
}

테스트 데이터 생성

seeder 생성

$ php artisan make:seeder UserSeeder

$ php artisan make:seeder CarSeeder

$ php artisan make:seeder CarUserSeeder
// database/seeders/UserSeeder.php

<?php

namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Seeder;

/**
 * Class UserSeeder
 * @package Database\Seeders
 */
class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        User::factory()->count(5)->create();
    }
}
// database/seeders/CarSeeder.php

<?php

namespace Database\Seeders;

use App\Models\Car;
use Illuminate\Database\Seeder;

/**
 * Class CarSeeder
 * @package Database\Seeders
 */
class CarSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Car::factory()->count(5)->create();
    }
}

pivot테이블의 데이터는 아래와 같이 가져온다. ( 더 좋은 방법이 있다면 코멘트 부탁드립니다 )

// database/seeders/CarUserSeeder.php

<?php

namespace Database\Seeders;

use App\Models\Car;
use App\Models\CarUser;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;

/**
 * Class CarUserSeeder
 * @package Database\Seeders
 */
class CarUserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        foreach (range(1, 30) as $index) {
            $user = User::find(rand(1, 5));
            $car = Car::find(rand(1, 5));
            CarUser::create(
                [
                    'user_pk_id' => $user->user_id,
                    'car_pk_id' => $car->car_id,
                    'note' => Str::random(15),
                ]
            );
        }
    }
}
// database/seeders/DatabaseSeeder.php

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

/**
 * Class DatabaseSeeder
 * @package Database\Seeders
 */
class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(
            [
                UserSeeder::class,
                CarSeeder::class,
                CarUserSeeder::class,
            ]
        );
    }
}

Factory 생성

// 자동자 faker data

$ composer require pelmered/fake-car
$ php artisan make:factory UserFactory

$ php artisan make:factory CarFactory
<?php

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

/**
 * Class UserFactory
 * @package Database\Factories
 */
class UserFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = User::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name,
        ];
    }
}
<?php

namespace Database\Factories;

use App\Models\Car;
use Illuminate\Database\Eloquent\Factories\Factory;
use Faker\Generator as Faker;


/**
 * Class CarFactory
 * @package Database\Factories
 */
class CarFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Car::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        $faker = (new \Faker\Factory())::create();
        $faker->addProvider(new \Faker\Provider\Fakecar($faker));
        return [
            'car_name' => $faker->vehicleBrand.' '.$faker->vehicleModel,
            'price' => $faker->numberBetween(30000000, 500000000),
            'release_date' => $faker->dateTime,
        ];
    }
}
$ php artisan db:seed 

seed를 통해 데이터가 삽입된 것을 확인할 수 있다.

 

2부에서는 생성된 데이터를 활용하여 본격적으로 relationship에 대해 실습해 보겠다.

 

- 1부 끝

 

Comments