Eloquent 는 관련된 모델을 삽입하는 편리한 메소드를 제공합니다.

 

참조키 자동 삽입

예를 들어, 새로운 task 를 등록할 때 project_id attribute 를 수동으로 설정하는 대신 Project 모델의 save() 메소드를 통해 자동으로 project_id 가 설정된 Task 모델을 삽입할 수 있습니다.

$task = new App\Task(['name' => 'example task']);

$prj = App\Project::find(7);

$task = $prj->tasks()->save($task);
PHP

project id 가 7 인 project 모델을 찾아 온 후에 save() 를 호출했으므로 task 모델의 project_id 를 자동으로 7 로 설정한 후에 tasks 테이블에 삽입합니다.

 

만약 여러 개의 관련된 모델을 한 번에 삽입해야 한다면 saveMany() 메소드를 사용하면 됩니다.

$tasks = [
	new App\Task(['name' => 'example task 1']),
	new App\Task(['name' => 'example task 2']),
	new App\Task(['name' => 'example task 3']),
];

$prj = App\Project::find(7);

$tasks = $prj->tasks()->saveMany($tasks);
CODE

위 예제는 3 개의 Task 모델의 참조키를 7 로 설정한 후에 삽입하며 task 모델의 배열을 리턴합니다.

독자들도 위 코드를 tinker 나 테스트 컨트롤러에서 실행한 후에 데이타베이스를 조회해서 삽입 여부를 확인해 보기 바랍니다.

Updating "Belongs To" Relationships

belongsTo 관계를 업데이트 할 때 Model associate( Model | int $model) 메소드를 사용하면 됩니다. 다음처럼 id가 100 인 task 모델이 project_id 가 2인 project 에 속하는데 이를 project_id 5 로 변경하려고 합니다.

>>> $task = App\Task::find(100)
=> <App\Task #000000002d6af4a5000000005d8a5c81> {
       id: 100,
       project_id: 2,
CODE

 

먼저 $task 모델을 얻은 후에 새로 속할 project 모델을 조회합니다.

$task = App\Task::find(100);
$prj =  App\Project::find(5);
CODE

 

이제 task 모델의 project() 메소드를 호출한 후에 associate() 로 새로운 project 를 설정해 주고 save() 하면 project_id 가 변경됩니다.

$task->project()->associate($prj);
$task->save()
CODE

이제 id 가 100인 task 모델을 조회해 보면 project_id 가 5 로 변경된 것을 확인할 수 있습니다.

>>> $task = App\Task::find(100)
=> <App\Task #000000002d6af4a5000000005d8a5c81> {
       id: 100,
       project_id: 5,
CODE

만약 참조키를 null 로 만들어서 관계를 끊을 경우 dissociate() 를 사용하면 되며 다음은 tinker 에서 task 모델의 관계를 끊는 예제입니다.

>>> $task = App\Task::find(100)
=> <App\Task #000000002d6af495000000005d8a5c81> {
       id: 100,
       project_id: 5,
>>> $task->project()->dissociate()
=> <App\Task #000000002d6af495000000005d8a5c81> {
       id: 100,
       project_id: null,
>>> $task->save()
true
CODE

 

다대다 관계 삽입

Eloquent 는 다대다 관계에서도 사용할 수 있는 편리한 헬퍼 함수를 제공합니다. 전 절에서 설명한 다대다 관계인 user와 role 모델에서 id가 3 인 사용자에게 role id 가 7인 역할을 부여한다고 가정해 봅시다.

먼저 User 모델을 조회한 후에 void attach( mixed $id, array $attributes = array(), bool $touch = true) 메소드로 새로운 역할 id 를 부여해 주면 됩니다.

$user = App\User::find(3);
$user->roles()->attach(7);
CODE

 

실제 동작 방식을 보기 위해 Orm 컨트롤러에 getManyAttach() 메소드를 추가하겠습니다.

public function getManyAttach($userId)
{		
    $user = User::find($userId);
    // 현재 권한 출력
    $role_users = $user->roles()->get()->toArray();		
    dump($role_users);

    // 새로운 역할 모델 조회
    $role = Role::where('name', 'like', 'devel%')->first();

    // 사용자에게 역할 부여
    $user->roles()->attach($role->id);

    // 변경된 권한 출력
    dump(User::find($userId)->roles()->get()->toArray());
}
CODE

브라우저로 http://homestead.app/orm/many-attach/2 에 연결하면 id 가 2인 User 모델을 조회한 후에 현재 역할을 배열로 출력하고 새로운 역할을 부여한 후에 다시 사용자의 roles() 를 조회하면 새로운 역할이 하나 추가된 것을 알 수 있습니다.

만약 역할을 제거할 경우 int detach( int|array $ids = array(), bool $touch = true) 메소드를 사용하면 되며 다음은 id 가 2인 사용자로부터 role_id 가 3 인 역할을 제거하는 예제입니다.

User::find(2)->roles()->detach(3);
CODE

 

부모 모델의 타임스탬프 갱신

모델이 다른 모델에 포함될 경우 자식 모델이 변경되면 부모 모델의 타임스탬프(Time Stamp)를 갱신하는게 필요할 경우가 있습니다. 예를 들어 새로운 Task 가 추가되면 Project 모델의 updated_at 컬럼이 변경되야 할 수 있습니다.

Eloquent 는 아주 쉽고 편리하게 이 작업을 할 수 있게 해주며 자식 모델에 touches 프로퍼티에 부모 모델을 설정해 주면 됩니다. 

 

class Task extends Model
{
    /** * All of the relationships to be touched. * * @var array */
    protected $touches = ['project'];

    /** * Get the post that the comment belongs to. */
    public function project()
    {
        return $this->belongsTo('App\Project');
    }
}
CODE

이제 Task 모델을 업데이트할 경우 해당 Task 를 소유하고 있는 Project 모델의 updated_at 컬럼은 자동으로 갱신됩니다.

$task = App\Task::find(1);

$task->name = 'new task';

$task->save();
CODE

동작 여부를 간단하게 확인해 보기 위해 tinker 를 구동하고 id 1 인 task 모델을 가져와 봅시다.

>>> $task = App\Task::find(1)
=> <App\Task #000000002508d81c0000000009594498> {
       id: 1,
       project_id: 2,
CODE

해당 task 를 소유하는 project는 2 이므로 find 로 조회한 후에 현재 updated_at 시간을 기억해 둡니다.

>>> $prj = App\Project::find(2)
=> <App\Project #000000002508d81f0000000009594498> {
       id: 2,
       user_id: 2,
       updated_at: "2015-05-16 22:30:26"
CODE

이제 task 모델의 값을 변경하고 저장합니다.

>>> $task->name = 'new task'
=> "new task"
>>> $task->save()
=> true
CODE

Project 모델의 타임스탬프 변경을 확인하기 위해 Project 모델을 조회하면 자동으로 부모의 updated_at 컬럼이 현재 시간으로 변경된 것을 확인할 수 있습니다.

>>> $prj = App\Project::find(2)
=> <App\Project #000000003f8c94a20000000037392ce9> {
       id: 2,
       user_id: 2,
       updated_at: "2015-07-26 01:28:44"
   }
CODE