06. 모델 (Models) - 업데이트중
- 역자주 : 현재 일부 섹션의 번역이 되어 있지 않습니다
6. 모델 (Models)#
6.1. 모델이란?#
모델은 어떤 일을 하는가? 도메인 로직을 표시 부분에서 분리하고, 애플리케이션의 로직만을 분리한다.
모델이란 일반적으로 데이터베이스를 나타낸다. 더 구체적으로 데이터베이스내의 특정 테이블을 나타낸다. 기본적으로 각각의 모델은 복수형의 이름이 붙은 테이블에 대응하는 단수형의 클래스가 된다. 예를 들면, 'User' 모델은 'Users' 테이블을 사용한다. 모델에는 또 데이터 검증 (validation) 을 위한 룰, 관련 (association) 정보, 테이블 특유의 메소드 등을 포함시킬 수 있다. 다음은 간단한 User 모델이 Cake 내에서 어떻게 되는지 보여준다.
예 6.1. User 모델의 예, /app/models/user.php 에 저장
- <?php
//AppModel 에서는 Cake 의 모델의 기능을 전부 제공하고 있다
class User extends AppModel
{
// 이 변수를 포함시는 것은 항상 좋은 습관이다
var $name = 'User';
// 이것은 검증 (validation) 에 사용된다, "자료 검증 (Data Validation)" 장을 보라.
var $validate = array();
// 관련 (association) 을 정의할 수 이다.
// 6.3 섹션에 자세히 나온다.
var $hasMany = array('Image' =>
array('className' => 'Image')
);
// 사용자 함수를 포함시킬 수 있다:
function makeInactive($uid)
{
// 자신 로직을 여기에...
}
}
?>
6.2. 모델 함수#
PHP 에서 보면, 모델은 AppModel 클래스를 확장 (extend) 한 클래스이다. 원래의 AppModel 클래스는 cake/ 디레토리에 선언되어 있지만, 직접 다시 만들 경우 app/app_model.php 에 둘 수 있다. 이 안에는 여러 모델을 공유하는 메소드를 넣는다. 이 클래스는 cake/libs/model/model.php 내에 선언되어 있는 표준 Cake 라이브러리의 하나인 모델 (Model) 클래스를 확장한 것이다.
이 섹션에서는 Cake 모델에 관해 자주 사용되는 함수에 대해 다루지만, 전체 레퍼런스는 http://api.cakephp.org 에 있는 것을 기억해 둬야 한다.
6.2.1. 사용자 함수#
모델내에 테이블 특유의 메소드를 쓰는 예로, 블로그의 포스트를 감추고/보이는 한쌍의 메소드를 보여준다
예 6.2. 모델 함수의 예
- <?php
class Post extends AppModel
{
var $name = 'Post';
function hide ($id=null)
{
if ($id)
{
$this->id = $id;
$this->saveField('hidden', '1');
}
}
function unhide ($id=null)
{
if ($id)
{
$this->id = $id;
$this->saveField('hidden', '0');
}
}
}
?>
6.2.2. 데이터 추출#
다음은 모델을 이용해 데이터를 추출하는 몇가지 표준적인 방법이다.
- findAll
- string $conditions
- array $fields
- string $order
- int $limit
- int $page
- int $recursive
지정된 필드에서 (만일 지정되어 있을 경우), $conditions 에 입력된 것을 $page (기본값은 1 페이지) 페이지에서 $limit 레코드까지 반환한다. $conditions 는 SQL 문에서 처럼 (예를 들면), $conditions = "race = 'wookie' AND thermal_detonators > 3" 라고 쓴다.
$recursive 옵션이 정수값 1 보다 크게 설정 되어 있는 경우, findAll() 동작은, findAll() 에서 발견된 관련 모델에 관하여도 결과를 반환한다. 만일, 속성에 여러 소유자가 있고, 그 각 소유자에 여러 종속관계가 있는 경우, 속성 모델상의 재귀함수 findAll()은 연관되는 모델을 반환한다.
- find
- string $conditions
- array $fields
- string $order
- int $recursive
$conditions 에 입력된 첫번째 레코드에서 지정된 필드(지정하지 않으면 모든 필드)를 반환한다.
$recursive 옵션이 정수값 1과 3 사이에 설정되면, find() 동작은, find() 에 발견된 모델에 관련되어 있는 모델도 반환한다. 재귀적 find 는, 3단계까지 진행할 수 있다. 만일, 속성에 여러 소유자가 있고, 그 각 소유자에 여러 종속관계가 있는 경우, 속성 모델상의 재귀함수 find() 는 연관되는 모델을 3단계까지 반환한다.
- findAllBy<fieldName>
- string $value
이 매직 함수는, 테이블의 특정 필드나 값을 빠르게 검색할 때 사용할 수 있다. 검색한 필드명을 낙타 표기법으로 추가한다. (컨트롤러내에서 사용할) 예제는 아래와 같다 :
- $this->Post->findByTitle('My First Blog Post');
$this->Author->findByLastName('Rogers');
$this->Property->findAllByState('AZ');
$this->Specimen->findAllByKingdom('Animalia');
결과는, find() 나 findAll() 과 같은 방법으로 형식화된 배열로 결과를 반환한다.
- findNeighbours
- string $conditions
- array $field
- string $value
$field 와 $value 에서 지정한 필드를, $conditions 의 SQL 의 조건으로 필터링하고, 인접한 모델(지정된 필드만)의 데이타를 배열로 반환한다.
이것은 모델의 엔트리를 특정 순서에 따라 정렬하여, '이전' 또는 '다음' 의 링크가 필요할 때 편리하다. 이 함수는 숫자 또는 날짜의 필드의 경우만 작동한다.
- class ImagesController extends AppController
{
function view($id)
{
// 이미지를 표시하고 싶다고 말한다...
$this->set('image', $this->Image->find("id = $id");
// 하지만, '이전'과 '다음' 이미지도 필요한 경우에는..
$this->set('neighbours', $this->Image->findNeighbours(null, 'id', $id);
}
}
이와 같이 하면, $ image['Image'] 배열 전체와, $neighbours['prev']['Image']['id'] 와 $ neighbours['next']['Image']['id'] 를 view 에서 사용할 수 있다.
- field
- string $name
- string $conditions
- string $order
$conditions 값에 입력되어 $order 로 정렬된 첫번째 레코드의 첫 필드를 문자열로 반환한다.
- findCount
- string $conditions
주어진 조건에 맞는 레코드의 수를 반환한다.
- generateList
- string $conditions
- string $order
- int $limit
- string $keyPath
- string $valuePath
이 함수는 키(key)/값(value) 한쌍으로 구성된 목록을 추출하는 바로가기이다. 특히, 모델의 목록으부터 html의 select 태그를 만들 때 편리하다. findAll() 과 같이, $conditions, $order, $limit 파라미터를 사용한다. $keyPath 와 $valuePath 에서 어떤 것을 key 와 value 로 할지 지정한다. 예를 들면, integer 의 id 를 key 라고 한 역할(role) 목록을 역할 모델로부터 만들고 싶은 경우에는 아래와 같이 하면 그만이다.
- $this->set(
'Roles',
$this->Role->generateList(null, 'role_name ASC', null, '{n}.Role.id', '{n}.Role.role_name')
);
// 이와 같이 반환될 것이다.
array(
'1' => 'Account Manager',
'2' => 'Account Viewer',
'3' => 'System Manager',
'4' => 'Site Visitor'
);
- read
- string $fields
- string $id
현재 로딩된 레코드, 또는 $id 로 지정한 레코드부터, 필드와 값을 얻고 싶은 경우에 이 함수를 사용한다.
read() 동작은 모델의 $recursive 에 관계 없이, 관련되어 있는 모델의 하나의 레벨만 가져오는 점에 주의한다. 그 이상의 레벨까지 가져 오려면, find() 나 findAll() 을 사용한다.
- query
- string $query
- execute
- string $query
모델의 query() 와 execute() 메소드를 사용하면, 커스텀 SQL 을 호출할 수 있다. 이 둘의 차이점은, query() 가 커스텀 SQL 쿼리(결과가 반환된다)을 만들때 사용되고, execute() 는 커스텀 SQL 의 실행(반환 값은 필요 없음)을 한다 점이다.
예 6.3. query() 를 이용한 커스텀 SQL 호출
- <?php
- class Post extends AppModel
- {
- var $name = 'Post';
- function posterFirstName()
- {
- $ret = $this->query("SELECT first_name FROM posters_table
- WHERE poster_id = 1");
- $firstName = $ret[0]['first_name'];
- return $firstName;
- }
- }
- ?>
6.2.3. 복합 조건 검색 (배열 이용)#
대부분의 모델의 find 호출은 하나 또는 다른 조건 전달을 수반한다. 이것의 가장 간단한 접근은 SQL 에 WHERE 절을 사용하는 것이지만, 더 많은 조작이 필요하다면, 배열을 사용할 수 있다. 배열을 사용하면 더욱 읽기 쉽고, 깔끔하며 게다가 쿼리 작성이 쉬워진다. 이 문법은 신중하고 잘 다룰 수 있는 부분 속으로 쿼리의 요소 (필드, 값, 조작자, 등) 를 분리해 준다. 이것은 Cake 가 매우 효율적인 쿼리를 생성할 수 있도록 허락하고, 올바른 SQL 문법을 보장하며, 쿼리의 개별적 부분을 올바르게 뽑는다.
매우 기본적으로, 배열 기반의 쿼리는 다음과 같이 보여진다 :
예 6.4. 기본적인 find 조건 배열 사용예 :
- $conditions = array("Post.title" => "This is a post");
//모델과 함께 사용한 예:
$this->Post->find($conditions);
The structure is fairly self-explanatory: it will find any post where the title matches the string "This is a post". Note that we could have used just "title" as the field name, but when building queries, it is good practice to always specify the model name, as it improves the clarity of the code, and helps prevent collisions in the future, should you choose to change your schema. What about other types of matches? These are equally simple. Let's say we wanted to find all the posts where the title is not "This is a post":
- array("Post.title" => "<> This is a post")
All that was added was '<>' before the expression. Cake can parse out any valid SQL comparison operator, including match expressions using LIKE, BETWEEN, or REGEX, as long as you leave a space between the operator an the expression or value. The one exception here is IN (...)-style matches. Let's say you wanted to find posts where the title was in a given set of values:
- array("Post.title" => array("First post", "Second post", "Third post"))
Adding additional filters to the conditions is as simple as adding additional key/value pairs to the array:
- array
(
"Post.title" => array("First post", "Second post", "Third post"),
"Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks"))
)
By default, Cake joins multiple conditions with boolean AND; which means, the snippet above would only match posts that have been created in the past two weeks, and have a title that matches one in the given set. However, we could just as easily find posts that match either condition:
- array
("or" =>
array
(
"Post.title" => array("First post", "Second post", "Third post"),
"Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks"))
)
)
Cake accepts all valid SQL boolean operations, including AND, OR, NOT, XOR, etc., and they can be upper or lower case, whichever you prefer. These conditions are also infinitely nestable. Let's say you had a hasMany/belongsTo relationship between Posts and Authors, which would result in a LEFT JOIN on the find done on Post. Let's say you wanted to find all the posts that contained a certain keyword or were created in the past two weeks, but you want to restrict your search to posts written by Bob:
- array
("Author.name" => "Bob", "or" => array
(
"Post.title" => "LIKE %magic%",
"Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks")
)
)
6.2.4. 데이터 저장#
모델에 데이터를 저장하려면, 저장하고 싶은 데이터를 준비한다. save() 메소드로 전달받은 데이터는 다음과 같은 형식으로 다뤄진다 :
- Array
(
[ModelName] => Array
(
[fieldname1] => 'value'
[fieldname2] => 'value'
)
)
컨트롤러에 POST 방식으로 전달되는 데이타를 이 형태로 하는 가장 간단한 방법은, HTML 헬퍼를 사용하는 것이다. HTML 헬퍼는 Cake 가 이해하는 방법으로 폼 요소의 이름을 생성한다. HTML 헬퍼를 사용하지 않는 것도 가능하지만, 폼 요소는 data[모델명][필드명] 과 같이 해야 한다. 하지만, $html->input('Model/fieldname') 를 사용하는 것이 가장 간단하다.
폼으로부터 포스트 방식으로 전달된 데이타는, 자동으로 이와 같은 포맷이 되고, 컨트롤러내의 $this->data 에 들어 갑니다. 따라서, 웹 폼의 데이터를 간단히 저장할 수 있다. 속성(property) 컨트롤러의 edit 함수는, 다음과 같은 형태가 될 것이다 :
- function edit($id)
{
// 주의 : 속성 모델은 $this->Property 에 자동으로 불러낸다
// 폼데이터가 존재하는지 검사...
if (empty($this->data))
{
$this->Property->id = $id;
$this->data = $this->Property->read();// 현재 지정된 열의 데이터를 폼 필드에 넣을 수 있다
}
else
{
// 데이터를 저장하는 부분이다. 자동으로 자료 검증(validation)을 한다.
if ($this->Property->save($this->data['Property']))
{
// 메시지를 표시(flash)하거나 리다이렉트한다.
$this->flash('Your information has been saved.',
'/properties/view/'.$this->data['Property']['id'], 2);
}
// 만일 잘못된 필드가 존재하거나 저장이 실패한 경우 이 형식이 표시된다
}
}
save 동작이 조건문 안에 위치하는 것에 주의한다. 모델에 데이타를 저장하려고 하는 경우, Cake 는 지정 되어 있는 룰에 기초하여 자동적으로 데이타가 올바른지 체크한다. 자료 검증과 관련된 상세 정보는 "12. 자료 검증(validation)"을 참조한다. save() 에 자료 검증을 할 필요가 없는 경우에는 save($data, false) 를 사용한다.
기타 유용한 함수 :
- del
- string $id
- boolean $cascade
$id 로 지정되었거나, 현재의 id 의 모델 데이타를 삭제한다.
이 모델에 다른 모델이 연관되어 있고, 연관(association)배열에 의존(dependent)키가 SET 되어 있는 경우, $cascade 가 true 로 설정되었 때, 이 메소드는 관련되는 모델 데이터도 삭제한다.
성공하면, true 를 반환한다.
- saveField
- string $name
- string $value
하나의 필드 값을 저장한다.
- getLastInsertId
가장 최근에 작성된 레코드의 ID 를 반환한다.
6.2.5. 모델 콜백#
모델의 동작 전후에 로직을 넣어을 때, 몇 모델에 콜백이 추가되었다. 애플리케이션 내에서 이 기능을 사용하려면 지정된 파라미터를 사용하고 Cake 의 모델의 이러한 함수를 오버라이드(override)한다.
- beforeFind
- string $conditions
beforeFind() 콜백은, 검색(find)동작이 시작되기 전에 실행된다. 검색 전에 실행하고 싶은 로직은 여기에 배치하도록 한다. 모델의 이 메소드를 오버라이드할 때에, 검색도 실행하고 싶으면 true 를, 검색을 중지하고 싶으면 false 를 반환하면 된다.
- afterFind
- array $results
검색(find)동작에 그 결과를 수정하고 싶은 경우나, 검색 후에 뭔가를 하고 싶은 경우에는 이 콜백을 사용한다. 이 함수의 파라미터는 모델의 검색 결과를 반환한다. 수정한 결과를 return value 로서 반환하면 된다.
- beforeValidate
자료 검증(validation)이 걸리기 전에 데이터를 수정하고 싶은 경우에는 이 콜백을 사용한다. Model::invalidate() 를 사용하고 추가 검증이나, 더 복잡한 검증 룰을 추가하는 것도 가능하다. 이 때에는, $this->data 에 의한 모델 데이터로 접근 가능하다. 또 이 함수는 true 를 반환해야한다. true 를 반환하지 않으면 save() 의 실행이 중지된다.
- beforeSave
저장 직전의 로직은 이 함수에 두면 된다. 모델 데이터의 자료 검증이 끝난 후 곧바로, (자료 검증에 save 호출이 중지된 경우에는, 이 콜백도 실행되지 않는다.) 데이터가 저장 되기 전에 이 함수가 실행된다. 이 함수도 저장 동작을 계속하고 싶은 경우에는 true 를 반환해야 한다. 중지하고 싶은 경우에는 false 를 반환한다.
beforeSave 의 사용 방법의 일례로, 특정 데이터베이스 엔진용 시간 데이터 포맷에 유용하다 :
- // HTML 헬퍼로 작성한 date/time :
// 이 코드는 view 에 있다.
$html->dayOptionTag('Event/start');
$html->monthOptionTag('Event/start');
$html->yearOptionTag('Event/start');
$html->hourOptionTag('Event/start');
$html->minuteOptionTag('Event/start');
- // 모델 콜백 함수는 날짜 데이터를 연결해 모두 저장한다
// 이 코드는 그 이벤트 모델에 있다 :
function beforeSave()
{
$this->data['Event']['start'] = $this->_getDate('Event', 'start');
return true;
}
function _getDate($model, $field)
{
return date('Y-m-d H:i:s', mktime(
intval($this->data[$model][$field . '_hour']),
intval($this->data[$model][$field . '_min']),
null,
intval($this->data[$model][$field . '_month']),
intval($this->data[$model][$field . '_day']),
intval($this->data[$model][$field . '_year'])));
}
- afterSave
저장 후에 실행하고 싶은 로직을 이 콜백에 둔다.
- beforeDelete
삭제 전에 실행하고 싶은 로직을 이 콜백에 둔다. 이 함수는 계속해서 삭재하고 싶은 경우에은 true 를 반환하면 된다. 중지하고자 할 경우 false 를 반환하면 된다.
- afterDelete
삭제 후에 실행하고 싶은 로직을 이 콜백에 둔다.
6.3. 모델의 변수#
모델을 작성할 때, 특별한 몇가지 변수를 설정하는 것으로 Cake 의 기능을 이용할 수 있다.
$primaryKey
모델이 데이터베이스의 테이블에 관련되어 있는 경우, 테이블의 primary key 명이 'id' 가 아닌 경우, 이 변수를 사용하여 어느 필드가 primary key 인지를 Cake 에 알린다.
$recursive
find() 와 findAll() 의 동작중에, 관련되어 있는 모델의 데이터를 몇 레벨까지 불러(fetch) 올 것인지를 설정한다.
Groups (그룹) 이 있고, 이 그룹에 Users (유저) 가 있고, 각 유저가 많은 Articles (게시물) 을 갖고 있다고 가정하자.
테이블 6.1. Model::recursive 옵션
| $recursive = 0 | Cake 는 Group 데이터를 불러 온다. |
| $recursive = 1 | Cake 는 Group 과 관련된 Users 를 불러 온다. |
| $recursive = 2 | Cake 는 Group 과 관련된 Users 와 그 User 애 관련된 Articels 를 불러온다 |
$transactional
이 모델로 트랜잭션 가능한지 아닌지 Cake 에 지시합니다 (begin/commit/rollback). boolean 값으로 설정한다. 트랜잭션을 지원하고 있는 데이터베이스만 사용할 수 있다.
$useTable
사용하고 싶은 테이블이 모델명의 복수형이 되어 있지 않은 경우 (그리고, 테이블명을 변경하기 싫은 경우), 이 변수로 사용하고 싶은데 테이블명을 설정한다.
$validate
이 모델에 전달받은 데이터를 발리 자료 검증하는 데 사용되는 배열이다. 상세한 것은 "자료 검증" 장을 참조한다.
$useDbConfig
데이터베이스의 설정은, /app/config/database.php 에서 설정하는 것을 기억는가? 그것을 바꾸기 위해서 이 변수를 사용한다. 작성한 데이터베이스 설정 파일에 있는 사용 가능한 데이타베이스 접속명을 쓴다. 기본값은, 'default' 이다.
6.4. 연관 (association)#
6.4.1. 소개#
CakePHP 대단히 강력한 기능중 하나는 모델에 의한 관계 매핑(relational mapping) 이다. CakePHP 에서는, 테이블의 관계를 연관(association)을 통해 다룬다. 연관은 논리적으로 관련되어 있는 유닛을 연결하는 접착제이다.
CakePHP 에는 네종류의 연관이 있다
-
hasOne
-
hasMany
-
belongsTo
-
hasAndBelongsToMany
모델간의 연관이 정의되면, Cake 에서는 작업하고 있는 모델에 관계된 모델에서 자동적으로 데이터를 가져 온다. 예를 들면, Post (투고) 모델이 Author (저자) 모델에 hasMany 를 사용해 연관이 설정 되고 있으며, 컨트롤러에 $this->Post->findAll() 로 불러내는 것으로, Post 레코드, 또 관련되어 있 Author 레코드의 데이터를 가져 온다.
자료 검증을 사용하려면, CakePHP 의 네이밍 규약(부록 "Cake 규약" 참조)에 따르는 것이 가장 좋다. CakePHP 의 네이밍 규약을 사용하는 경우, 스캐폴딩으로 애플리케이션의 데이타를 시각화하는 것이 가능하다. 스캐폴딩에서는, 모델간의 연관을 검출해 이용하기 때문이다. Cake 의 네이밍 규약에 따르지 않는 방법으로도 모델의 연관을 커스터마이징하는 것이 가능하다. 그러나, 그 팁에 관해서는 나중에 설명한다. 지금은 네이밍 규약에 따른 방법만 얘기한다. 외부키(foreign keys), 모델명, 테이블명에 관한 네이밍 규약을 염두에 둬야 한다.
다음에 설명하는 것은, 몇 가지의 요소의 이름에 관하여, Cake 가 기대하는 사항들의 복습이다. : (네이밍에 관한 상세한 정보는 부록 "Cake 규약" 참조)
- 외부키 : [모델명의 단수형]_id. 예를 들어, "authors" 테이블내의 외부키가 Post 일 경우, Author 에 속한 것은 "post_id" 가 된다.
- 테이블명 : [객체명의 복수형]. 블로그의 포스트(post)와 작성자(author)의 정보를 저장하고 싶기 때문에, 테이블 명은 각각, "posts" 와, "authors" 가 된다.
- 모델명 : [낙타표기법의 테이블 단수형]. "posts" 테이블에 대한 모델은 "Post", 그리고 "authors" 테이블에는 "Author".
CakePHP 의 스캐폴딩에서는, 연관(association)된 컬럼의 정렬이 같다고 예상한다. 따라서, 만일 Article 이 다른 3개의 모델(Author, Editor, Publisher)에 속해 있는 경우(belongsTo), author_id, editor_id, publisher_id 라는 3개의 키가 필요하게 된다. 스캐폴딩에서는, 테이블내의 연관도 같은 정렬이라고 예상한다 (첫번째 Author, 두번째 Editor, 마지막에 Publisher).
연관이 어떻게 동작하는지를 설명하기 위해, 계속해서 블로그 애플리케이션을 예로 든다. 블로그용으로 간단한 유저 관리 시스템을 만든다고 하자. 이때 당연히 Users 의 기록을 보관하고 싶을 것이다. 그런데, 또 각각의 유저가 연관된 하나의 Profile (프로필) 을 갖게 하고 싶다 (User hasOne Profile, 유저는 프로필을 "하나 갖는다"). 게다가, Users 는 Comment 를 만들 수 있고, 그들 자신과 관련지을 수 있다 (User hasMany Comments, 유저는 코멘트를 "여러개 갖는다"). 일단 유저 시스템이 작동하게 되면, Posts 를 hasAndBelongsToMany 관계를 사용하는 Tag 객체와 관계되도록 한다 ( Post hasAndBelongsToMany Tags, "포스트는 여러 태그를 갖고, 또 태그에 속한다").
6.4.2. hasOne 정의하기와 질의하기#
이 연관을 설정하기 위해, 이미 User 와 Profile 모델은 작성되어 있어야 한다. 이 두개 사이에 hasOne 연관을 정의하려면, 모델에 하나의 배열을 추가하고 Cake 에 관련 방법을 전달한다.
다음과 같이하면 된다.
예 6.4. /app/models/user.php hasOne
- <?php
class User extends AppModel
{
var $name = 'User';
var $hasOne = array('Profile' =>
array('className' => 'Profile',
'conditions' => '',
'order' => '',
'dependent' => true,
'foreignKey' => 'user_id'
)
);
}
?>
$hasOne 배열은 User 모델과 Profile 모델의 연관을 Cake 가 조립하는데 사용된다. 배열의 각 키에 의해 연관을 더욱 상세하게 설정할 수 있다 :
-
className (필수): 연관짓고 싶은 모델의 클래스명
위 예제에서는, 'Profile' 모델의 클래스명을 지정하고 있다.
-
conditions: 관계를 정의한 SQL 조건의 일부
필요하면 녹색의 헤더가 붙은 프로필만 관련 짓도록 Cake 에 명령할때, 다음과 같이 키를 설정하면 가능하다 : "Profile.header_color = 'green'".
-
order: 연관된 모델의 데이터 정렬
연관된 모델을 특정 순서로 정렬하고 싶은 경우, 이 키로 SQL 의 order 방법으로 값을 설정한다, 예를 들면 : "Profile.name ASC".
-
dependent: true 로 설정하면, 이 모델의 데이터 삭제시에 연관되어 있는 모델 측의 데이터도 삭제된다.
예를 들면, 프로필 "Cool Blue" 가 "Bob" 에 연관되어 있는 경우, "Bob" 라는 유저를 삭제하고, 프로필 "Cool Blue" 도 삭제된다.
-
foreignKey: 연관되어 있는 모델을 가리키고 있는 외부키의 이름
Cake 의 네이밍 규약에 따라서 없는 데이터베이스를 사용하고 있는 경우에 여기서 지정할 수 있다.
이제, User 모델로 find() 또는 findAll() 을 호출하면, 연관되어 있는 Profile 모델도 함께 볼 수 있다.
- $user = $this->User->read(null, '25');
print_r($user);
// 출력:
Array
(
[User] => Array
(
[id] => 25
[first_name] => John
[last_name] => Anderson
[username] => psychic
[password] => c4k3roxx
)
[Profile] => Array
(
[id] => 4
[name] => Cool Blue
[header_color] => aquamarine
[user_id] = 25
)
)
6.4.3. belongsTo 정의하기와 질의하기#
이제 User 는 Profile 을 볼 수 있다. 이번에는 Profile 이 User 를 보이도록 한다. Cake 에서는 belongsTo 연관을 사용하는 것으로 가능하게 된다. Profile 모델 내에서 다음과 같이 한다 :
예 6.5. /app/models/profile.php belongsTo
- <?php
class Profile extends AppModel
{
var $name = 'Profile';
var $belongsTo = array('User' =>
array('className' => 'User',
'conditions' => '',
'order' => '',
'foreignKey' => 'user_id'
)
);
}
?>
$belongsTo 배열은, Cake 가 User 모델과 Profile 모델 사이에 연관을 만들 때 사용한다. 배열 가각의 키에 연관을 더욱 상세하게 설정할 수 있다 :
-
className (필수): 연관짓고 싶은 모델의 클래스명
위 예제에서는, 'User' 모델의 클래스명을 지정하고 있다.
-
conditions: 관계를 정의한 SQL 조건의 일부
active 상태의 User 만을 연관 짓도록 Cake 에 명령할때, 다음과 같이 키를 설정하면 가능하다 : "User.active = '1'" 등.
-
order: 연관된 모델의 데이터 정렬
연관된 모델을 특정 순서로 정렬하고 싶은 경우, 이 키로 SQL 의 order 방법으로 값을 설정한다, 예를 들면 : "User.last_name ASC".
-
foreignKey: 연관되어 있는 모델을 가리키고 있는 외부키의 이름
Cake 의 네이밍 규약에 따라서 없는 데이터베이스를 사용하고 있는 경우에 여기서 지정할 수 있다.
이제, Profile 모델로 find() 또는 findAll() 을 호출하면, 연관되어 있는 User 모델도 함께 볼 수 이다 :
- $profile = $this->Profile->read(null, '4');
print_r($profile);
// 출력:
Array
(
[Profile] => Array
(
[id] => 4
[name] => Cool Blue
[header_color] => aquamarine
[user_id] = 25
)
[User] => Array
(
[id] => 25
[first_name] => John
[last_name] => Anderson
[username] => psychic
[password] => c4k3roxx
)
)
6.4.4. hasMany 정의 및 질의하기#
User 모델과 Profile 모델이 연관되고, 올바르게 작동하게 되었기 때문에, User 레코드를 Comment 레코드와 연관시켜 보도록 한다. 이것은, User 모델을 다음과 같이 하는 것으로 가능하다 :
예 6.6. /app/models/user.php hasMany
- <?php
class User extends AppModel
{
var $name = 'User';
var $hasMany = array('Comment' =>
array('className' => 'Comment',
'conditions' => 'Comment.moderated = 1',
'order' => 'Comment.created DESC',
'limit' => '5',
'foreignKey' => 'user_id',
'dependent' => true,
'exclusive' => false,
'finderQuery' => ''
)
);
// 방금전에 정의했던 hasOne 의 관계..
var $hasOne = array('Profile' =>
array('className' => 'Profile',
'conditions' => '',
'order' => '',
'dependent' => true,
'foreignKey' => 'user_id'
)
);
}
?>
$hasMany 배열은, Cake 가 User 모델과 Comment 모델 사이에 연관을 만들 때 사용한다. 배열 가각의 키에 연관을 더욱 상세하게 설정할 수 있다 :
-
className (필수): 연관짓고 싶은 모델의 클래스명
위 예제에서는, 'Comment' 모델의 클래스명을 지정하고 있다. -
conditions: 관계를 정의한 SQL 조건의 일부
조정된(moderated) Comment 만을 연관 짓도록 Cake 에 명령할때, 다음과 같이 키를 설정하면 가능하다 : "Comment.moderated = 1" 등.
-
order: 연관된 모델의 데이터 정렬
연관된 모델을 특정 순서로 정렬하고 싶은 경우, 이 키로 SQL 의 order 방법으로 값을 설정한다, 예를 들면 : "Comment.created DESC" 등.
-
limit: Cake 가 불러오는 관련 모델의 데이터의 최대 갯수
위 예에서는, 유저의 Comment 를 전부 불러오지 않고 5개만 불러온다.
-
foreignKey: 연관되어 있는 모델을 가리키고 있는 외부키의 이름
Cake 의 네이밍 규약에 따라서 없는 데이터베이스를 사용하고 있는 경우에 여기서 지정할 수 있다.
- dependent: true 로 설정하면, 이 모델의 데이터 삭제시에 연관되어 있는 모델 측의 데이터도 삭제된다.
예를 들면, 프로필 "Cool Blue" 가 "Bob" 에 연관되어 있는 경우, "Bob" 라는 유저를 삭제하고, 프로필 "Cool Blue" 도 삭제된다.
-
exclusive: true 로 설정하면, 연관된 모든 객체가 하나의 SQL 구문의로 삭제된다. beforeDelete 콜백은 실행되지 않는다.
빠르게 작동하기 때문에 간단한 연관에서 활용할 수 있다.
-
finderQuery: 연관을 불러오기 위해 완전한 SQL 구문을 지정한다.
여러 테이블에 의존하는 복잡한 연관의 경우에 활용할 수 있다. 만일 Cake 의 자동 연관을 사용할 수 없을 경우에, 이것으로 커스터마이징이 가능하다.
이제, User 모델로 find() 또는 findAll() 을 호출하면, 연관되어 있는 Comment 모델도 함께 볼 수 있다 :
- $user = $this->User->read(null, '25');
print_r($user);
//output:
Array
(
[User] => Array
(
[id] => 25
[first_name] => John
[last_name] => Anderson
[username] => psychic
[password] => c4k3roxx
)
[Profile] => Array
(
[id] => 4
[name] => Cool Blue
[header_color] => aquamarine
[user_id] = 25
)
[Comment] => Array
(
[0] => Array
(
[id] => 247
[user_id] => 25
[body] => The hasMany assocation is nice to have.
)
[1] => Array
(
[id] => 256
[user_id] => 25
[body] => The hasMany assocation is really nice to have.
)
[2] => Array
(
[id] => 269
[user_id] => 25
[body] => The hasMany assocation is really, really nice to have.
)
[3] => Array
(
[id] => 285
[user_id] => 25
[body] => The hasMany assocation is extremely nice to have.
)
[4] => Array
(
[id] => 286
[user_id] => 25
[body] => The hasMany assocation is super nice to have.
)
)
)
프로세스를 문서에 설명하는 것은 하지 않고 있지만, "Comment belongsTo User" 연관도 정의하고, 상호 모델로부터 상대가 보이도록 하는 것은 좋은 생각이다. 스캐폴딩을 사용하려 했을 때, 상호 모델로부터 연관을 정의하지 않는 것은 가끔 흔한 실수가 되기도 한다.
6.4.5. hasAndBelongToMany 정의 및 질의하기#
간단한 연관에 관해서는 이것으로 마스터 가능하다. 다음으로는, 마지막 연관 : hasAndBelongsToMany (또는 HABTM) 으로 이동하자. 이것은 간단히 이해되지는 않겠지만, 가장 유용한 것중 하나이다. HABTM 연관은, 두개의 테이블이 있고, 그 두개를 조인 테이블로 연결되어 때 유용하다. 조인 테이블은 다른 것과 관련하고 있는 개별적인 열의 정보를 갖는다.
hasMany 와 hasAndBelongsToMany 의 차이는, hasMany 의 경우, 관련되어 있는 모델의 데이타를 공유할 수 없다는 것이다. 만일 User hasMany Comments (User 가 여러 Comment 를 갖고 있다) 라면, Comment 와 관련되어 있는 것은, User *뿐*이다. HABTM 는, 관련된 모델 데이타를 공유할 수 있다. 이것은 다음 경우에 매우 탁월하다 : Post 모델을 Tag 모델에 연관시킬 때. Tag 는 Post 에 belongs to(속할) 의 관계이지만, 소모해 버리는 것은 바람직하지 않다, Tag 는 계속해서 다른 Post 부터도 연관시키고 싶기 때문이다.
그러기 위해서는, 이 연관를 위해서 테이블을 바르게 설정할 필요가 있다. 물론, Tag 모델을 위한 "tags" 테이블, 그리고 Post 모델을 위한 "posts" 테이블이 필요합니다. 그리고, 연관을 위해서, 새로 조인 테이블을 생성할 필요도 있다. HABTM 조인 테이블 네이밍 규약은 [복수형 모델명1]_[복수형 모델명2] 이다. 모델명은 알파벳 순서대로 정렬한다 :
예 6.7. HABTM 조인 테이블 : 샘플 모델과 조인 테이블명
-
Posts 와 Tags: posts_tags
-
Monkeys 와 ceCubes: ice_cubes_monkeys
-
Categories 와 Articles: articles_categories
HABTM 조인 테이블은 연결된 모델에 관해 최소 두개의 외부키로 구성되어 있다. 이 예에서는, "post_id" 와 "tag_id" 만이 필요하다
Post HABTM Tags 의 SQL 덤프 예이다 :
- --
-- Table structure for table `posts`
--
CREATE TABLE `posts` (
`id` int(10) unsigned NOT NULL auto_increment,
`user_id` int(10) default NULL,
`title` varchar(50) default NULL,
`body` text,
`created` datetime default NULL,
`modified` datetime default NULL,
`status` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`id`)
) TYPE=MyISAM;
-- --------------------------------------------------------
--
-- Table structure for table `posts_tags`
--
CREATE TABLE `posts_tags` (
`post_id` int(10) unsigned NOT NULL default '0',
`tag_id` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`post_id`,`tag_id`)
) TYPE=MyISAM;
-- --------------------------------------------------------
--
-- Table structure for table `tags`
--
CREATE TABLE `tags` (
`id` int(10) unsigned NOT NULL auto_increment,
`tag` varchar(100) default NULL,
PRIMARY KEY (`id`)
) TYPE=MyISAM;
테이블의 설정이 가능하면 Post 모델의 연관을 설정한다
예 6.8. /app/models/post.php hasAndBelongsToMany
- <?php
class Post extends AppModel
{
var $name = 'Post';
var $hasAndBelongsToMany = array('Tag' =>
array('className' => 'Tag',
'joinTable' => 'posts_tags',
'foreignKey' => 'post_id',
'associationForeignKey'=> 'tag_id',
'conditions' => '',
'order' => '',
'limit' => '',
'unique' => true,
'finderQuery' => '',
'deleteQuery' => '',
)
);
}
?>
$hasAndBelongsToMany 배열은, Cake 가 Post 모델과 Tag 모델의 사이에 연관을 만들 때 사용한다. 배열 가각의 키에 연관을 더욱 상세하게 설정할 수 있다 :
-
className (필수): 연관짓고 싶은 모델의 클래스명
위 예제에서는, 'Tag' 모델의 클래스명을 지정하고 있다. -
joinTable: Cake 의 네이밍 규약에 따라서 없는 데이터베이스의 경우는 여기에서 설정한다. [복수형 모델1]_[복수형 모델2] 의 사전적인 순서이 되어 있지 않은 경우에는, 테이블명은 여기에서 지정한다.
-
foreignKey: 현재의 모델을 가리키는 조인 테이블 내의 외부 키의 이름.
Cake 의 네이밍 규약에 따라서 없는 데이터베이스의 경우는 여기에서 설정한다.
-
associationForeignKey: 연관되어 있는 모델을 가리키는 외부 키의 이름.
-
conditions: 관계를 정의한 SQL 조건의 일부
입증된(approved) Tag 만을 연관 짓도록 Cake 에 명령할때, 다음과 같이 키를 설정하면 가능하다 : "Tag.approved = 1" 등
-
order: 연관된 모델의 데이터 정렬
연관된 모델을 특정 순서로 정렬하고 싶은 경우, 이 키로 SQL 의 order 방법으로 값을 설정한다, 예를 들면 : "Tag.tag DESC DESC" 등.
-
limit: Cake 가 불러오는 관련 모델의 데이터의 최대 갯수
불러올 연관된 Tags 의 갯수를 한정할 때 사용한다.
-
unique: true 로 설정하면, 액세스와 쿼리 메소드에서, 관련된 객체가 중복되는 경우에는 무시한다.
기본적으로, 관계가 별개로 되어 있는 경우에는, true 로 설정한다. 그렇다면, "Awesomeness" 이라는 tag는, Post 의 "Cake Model Associations" 에 한 번만 분배되고, 결과 배열 중에은, 한 번밖에 나타나지 않는다.
-
finderQuery: 연관을 불러오기 위해 완전한 SQL 구문을 지정한다.
여러 테이블에 의존하는 복잡한 연관의 경우에 활용할 수 있다. 만일 Cake 의 자동 연관을 사용할 수 없을 경우에, 이것으로 커스터마이징이 가능하다.
-
deleteQuery: HABTM 모델간의 연관 데이터를 없애는 완전한 SQL 구문이다.
Cake 의 삭제 방법이 바람직하지 않거나, 설정이 커스터마이징 되어 있는 경우에, 자신의 쿼리를 여기에 설정하여 삭제 동작 방법을 변경할 수 있다.
이제, Post 모델로 find() 또는 findAll() 을 호출하면, 연관되어 있는 Tag 모델도 함께 볼 수 있다 :
- $post = $this->Post->read(null, '2');
print_r($post);
//output:
Array
(
[Post] => Array
(
[id] => 2
[user_id] => 25
[title] => Cake Model Associations
[body] => Time saving, easy, and powerful.
[created] => 2006-04-15 09:33:24
[modified] => 2006-04-15 09:33:24
[status] => 1
)
[Tag] => Array
(
[0] => Array
(
[id] => 247
[tag] => CakePHP
)
[1] => Array
(
[id] => 256
[tag] => Powerful Software
)
)
)
6.4.6. 관련 데이터 저장#
관련된 모델로 작업할 때 기억해야할 중요한 주의사항 하나는, 모델 데이터의 저장은 언제나 대응하는 케이크 모델에 의해 행해져야 한다는 것이다. 만약 새로운 Post 하나와 이 Post 에 관련된 Comment 들을 저장한다면 저장 작업동안 Post 와 Comment 모두를 사용할 것이다.
만일 관련된 모델이 어느쪽도 아직 존재하지 않는다면 (예를 들어, 새로운 Post 와 관련된 Comment 를 동시에 저장하고 싶다), 먼저 주가되거나 부모의 모델을 먼저 저장할 필요가 있을 것이다. 이것이 어떻게 작동하는지 아이딩어를 얻으려면, 새로운 Post 와 관련된 Comment 의 저장을 다루는 PostsController 내의 액션을 갖고 있다고 상상하자. 아래 예로 든 액션은 하나의 Post 와 하나의 Comment 를 작성했다고 가정한다.
예 6.4.5 /app/controllers/posts_controller.php (일부)
- function add()
{
if (!empty($this->data))
{
//Post 데이터를 저장할 수 있다:
//이것은 $this->data['Post'] 속에 있을 것이다
$this->Post->save($this->data);
//자, Comment 데이터를 저장할 필요가 있다.
//하지만 먼저, 방금 저장한 Post 의 ID 를 알아 내야 한다...
$post_id = $this->Post->getLastInsertId();
//이제 데이터를 저장하고 comment 를 저장하기 위한 이 정보를 추가한다.
$this->data['Comment']['post_id'] = $post_id;
//Post hasMany Comments 관련 때문에
//Post 모델을 통해 Comment 모델에 접근할 수 있다 :
$this->Post->Comment->save($this->data);
}
}
그러나, 만약, 부모 모델이 시스템에 이미 존재할 경우 (예를 들어, 존재하는 Post 에 Comment 를 추가한다), 저장하기 전에 부모모델의 ID 를 알 필요가 있다. URL 파라미터 , 또는 폼의 hidden 요소로 ID 를 넘겨 받을 수 있다...
예 /app/controllers/posts_controller.php (일부)
- //이곳에서 URL 파라미터가 어떻게 사용되는지 볼 수 있다...
function addComment($post_id)
{
if (!empty($this->data))
{
//$post_id 를 더욱 안전하게 만들어 싶었을 지 모른다,
//하지만 이 작동 예제에서는 이것으로 족하다..
$this->data['Comment']['post_id'] = $post_id;
//Post hasMany Comments 관련 때문에
//Post 모델을 통해 Comment 모델에 접근할 수 있다 :
$this->Post->Comment->save($this->data);
}
}
만약 ID 가 폼의 hidden 요소로 넘겨졌다면, 필드 (만일 html 헬퍼를 사용하고 있다면) 의 네이밍을 하고 싶을 수 있다. 그러면 적절한 곳에 다음과 같이 넘겨진 데이터를 넣으면 끝이다 :
- 만약 Post 의 ID 가 $post['Post']['id'] 에 있다면...
<?php echo $html->hidden('Comment/post_id', array('value' => $post['Post']['id'])); ?>
이렇게 되면, 부모 Post 모델의 ID 는 $this->data['Comment']['post_id'] 로 접근할 수 있고, 간단한 $this->Post->Comment->save($this->data) 의 호출 준비가 완전히 끝난다.
이같은 기본적인 테크닉은 다수의 자식 모델을 저장할때, 단지 루프 (또한 Model::create() 를 사용하는 모델정보를 알고 있을 것을 기억하도록 한다) 내의 save() 의 호출을 넣는 것만으로 작동할것이다.
요약하면, 만일 관련된 데이터를 저장하고 있다면 (belongsTo, hasOne, hasMany 관련), 요점은 부모 모델의 ID 를 얻는 것과 그 ID 를 자식 모델에 저장하는 것이다.
6.4.7. hasAndBelongsToMany 의 저장#
hasOne, belongsTo, hasMany 로 연관되는 모델을 저장하는 것은 대단히 간단하다. 관련되는 모델의 ID 와, 외부 키의 필드를 설정하면 된다. 그 후 모델의 save() 메소드를 호출하면, 연결된 모든 것들이 바르게 조합된다.
hasAndBelongsToMany 는 좀더 막연하지만, 가능한 간단하게 해 보자. 예를 보는 동안, Tags 는 Posts 에 연관되어 있는 폼을 작성할 필요가 있다. posts 를 작성하는 폼을 작성하고, 이미 있는 Tags 의 목록과 연관시켜 본다.
실제로는 새로운 태그를 작성하고 그 자리에서 포스트와 연관짓게 하고 싶을지도 모른다. 그러나 이번에는 간단하게 하기위해, 어떻게 연관 짓고 불로내는 지 정도만 나타낸다.
Cake 에서 자신의 모델을 저장하고 싶은 경우, (HtmlHelper 를 사용하고 있으며) 태그명은 '모델/필드_이름' 과 같이 된다. 포스트를 작성하는 폼을 우선 만든다:
예 6.9. posts 작성을 위한 /app/views/posts/add.thtml 형식
- <h1>Write a New Post</h1>
- <table>
- <tr>
- <td>Title:</td>
- <td><?php echo $html->input('Post/title')?></td>
- </tr>
- <tr>
- <td>Body:<td>
- <td><?php echo $html->textarea('Post/body')?></td>
- </tr>
- <tr>
- <td colspan="2">
- <?php echo $html->hidden('Post/user_id', array('value'=>$this->controller->Session->read('User.id')))?>
- <?php echo $html->hidden('Post/status' , array('value'=>'0'))?>
- <?php echo $html->submit('Save Post')?>
- </td>
- </tr>
- </table>
이 폼은 Post 레코드를 작성할 수 있게 한다. 이번에는 하나 이상의 태그를 Post 에 지속시킬 수 있게 한다 :
예 6.10. /app/views/posts/add.thtml (tag 연관 코드를 추가)
- <h1>Write a New Post</h1>
<table>
<tr>
<td>Title:</td>
<td><?php echo $html->input('Post/title')?></td>
</tr>
<tr>
<td>Body:</td>
<td><?php echo $html->textarea('Post/body')?></td>
</tr>
<tr>
<td>Related Tags:</td>
<td><?php echo $html->selectTag('Tag/Tag', $tags, null, array('multiple' => 'multiple')) ?>
</td>
</tr>
<tr>
<td colspan="2">
<?php echo $html->hidden('Post/user_id', array('value'=>$this->controller->Session->read('User.id')))?>
<?php echo $html->hidden('Post/status' , array('value'=>'0'))?>
<?php echo $html->submit('Save Post')?>
</td>
</tr>
</table>
새로운 Post 와 게다가 관련된 Tags 를 저장하기 위해 컨트롤러에 $this->Post->save() 를 호출하려면, 필드명이 폼의 "Tag/Tag" 내에 없어선 안된다. 전송하는 데이터의 타입이 단일의 ID 나, 링크한 레코드의 ID 의 배열이어야 한다. 여기에는 multiple select 를 사용한 것이고, Tag/Tag 에 전송되는 데이타는 ID 의 배열이 된다.
6.4.8. 애플리이션 작동중 bindModel() 과 unbindModel() 이용하여 관련 변경하기#
애플리케이션을 구축할 때 이따금 예외적인 상황을 위해 모델의 관련을 변경하고 싶을 수 있다. 모델 파일의 관련 설정이 너무 많은 (또는 충분하지 않은) 정보를 주고 있다면, 다음의 find 작업전, 묶기 (bind) 와 풀기 (unbind) 이 두개의 모델 함수를 이용할 수 있다.
어떻게 bindModel() 과 unbindModel() 이 작동하는지 보기 위해 몇개의 모델을 설정해보자. 다음과 같이 두개의 모델로 시작할 것이다 :
예 6.14. leader.php 와 follower.php
- <?php
class Leader extends AppModel
{
var $name = 'Leader';
var $hasMany = array(
'Follower' => array(
'className' => 'Follower',
'order' => 'Follower.rank'
)
);
}
?>
<?php
class Follower extends AppModel
{
var $name = 'Follower';
}
?>
자, LeadersController, 에서 Leader (지도자) 모델의 find() 메쏘드를 이용하여 Follower (추종자) 와 관련된 Leader 를 불러 올 수 있다. 위에서 볼 수 있듯이, Leader 모델의 이 관련 배열은 "Leader hasMany Followers" 를 정의한다. 시험삼아 unbindModel() 을 이용하여 이 관련을 제거해보자.
예 6.15. leaders_controller.php (일부)
- function someAction()
{
//Leaders 와, 관련된 Followers 를 불러온다. - $this->Leader->findAll();
//hasMany 관련을 없애보자...
$this->Leader->unbindModel(array('hasMany' => array('Follower')));
//자 find 함수를 이용하면 Follower 없이 Leader 를 불러올 것이다. - $this->Leader->findAll();
//주의 : unbindModel 은 오직 바로 다음의 find 함수에만 유효하다.
//추가적인 find 함수 호출은 설정된 관련 정보를 이용하게된다.
//이미 unbindModel() 후에 findAll() 을 사용하였기 때문에, - //Leaders 와, 관련된 Followers 를 다시 불러온다...
$this->Leader->findAll();
}
unbindModel() 함수는 다른 관련 설정과 유사하게 작동한다 : 관련 타입의 모델 클래스 네임을 바꾼다. unbindModel() 의 기본적 사용예는 :
예 6.16. 일반적인 unbindModel() 예
- $this->Model->unbindModel(array('associationType' => array('associatedModelClassName')));
자 이제 애플리케이션 작동중에 성공적으로 관련을 제거했다. 이젠 추가를 해보자. 아직 '주의 (Principle)' 가 없는 지도자 (Leader) 는 어떤 '주의'와 관련될 필요가 있다. Principle 모델 파일은 var $name 구문을 제외하고 텅 비어 있다. 애플리케이션 작동중에 Leader 에 어떤 Principle 을 관련지어 보자 (오직 다음 find 함수 호출을 위해서다) :
예 6.17. leaders_controller.php (일부)
- funciton anotherAction()
{
//leader.php 모델 파일에는 Leader 에 Principle 이 hasMany 되어 있지 않다.
//find 하면 Leader 만을 불러온다.
$this->Leader->findAll();
//bindModel() 를 사용하여 Principle 에 새로운 관련을 추가하자 :
$this->Leader->bindModel(
array('hasMany' => array(
'Principle' => array(
'className' => 'Principle'
)
)
)
);
//자 이제 정확하게 관련지어 졌다. - //하나의 find 함수를 사용하여 Principle 과 관련지어진 Leader 를 불러 올 수 있다:
$this->Leader->findAll();
}
bindModel() 함수는 새로운 관련을 만들기 위해 조작된다. 하지만 애플리케이션 작동중에 설정된 관련 정보의 정렬 정보 또는 다른 파라미터를 변경할 때 유용한다.
자 해보자. bindModel 의 기본적인 사용예는 일반적인 관련 배열 내부의 배열 (만들고자 하는 배열의 타입 뒤에 지정된 키 값) 을 캡슐화하는 것이다 :
예 6.18. 일반적인 bindModel() 예
- $this->Model->bindModel(
array('associationName' => array(
'associatedModelClassName' => array(
// 일반적인 관련 키값은 여기에...
)
)
)
);
애플리케이션 작동중에 모델을 bind 하려면 테이블들은 정확하게 key 가 걸려 있어야 한다 (또는 관련 배열 속성의 설정) 는 점을 주의한다.
Tags
History
Last edited on 11/07/2007 19:20 by ainoai
Comments (0)