연관 모델 삽입
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);
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);
위 예제는 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,
먼저 $task 모델을 얻은 후에 새로 속할 project 모델을 조회합니다.
$task = App\Task::find(100);
$prj = App\Project::find(5);
이제 task 모델의 project() 메소드를 호출한 후에 associate() 로 새로운 project 를 설정해 주고 save() 하면 project_id 가 변경됩니다.
$task->project()->associate($prj);
$task->save()
이제 id 가 100인 task 모델을 조회해 보면 project_id 가 5 로 변경된 것을 확인할 수 있습니다.
>>> $task = App\Task::find(100)
=> <App\Task #000000002d6af4a5000000005d8a5c81> {
id: 100,
project_id: 5,
만약 참조키를 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
다대다 관계 삽입
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);
실제 동작 방식을 보기 위해 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());
}
브라우저로 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);
부모 모델의 타임스탬프 갱신
모델이 다른 모델에 포함될 경우 자식 모델이 변경되면 부모 모델의 타임스탬프(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');
}
}
이제 Task 모델을 업데이트할 경우 해당 Task 를 소유하고 있는 Project 모델의 updated_at 컬럼은 자동으로 갱신됩니다.
$task = App\Task::find(1);
$task->name = 'new task';
$task->save();
동작 여부를 간단하게 확인해 보기 위해 tinker 를 구동하고 id 1 인 task 모델을 가져와 봅시다.
>>> $task = App\Task::find(1)
=> <App\Task #000000002508d81c0000000009594498> {
id: 1,
project_id: 2,
해당 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"
이제 task 모델의 값을 변경하고 저장합니다.
>>> $task->name = 'new task'
=> "new task"
>>> $task->save()
=> true
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"
}