Last modified 4 years ago
MetaBBS의 데이터 액세스 구조
(아래 내용은 아직 구현되지 않은 것도 포함합니다. 그리고 나중에 바뀔 수도 있습니다.)
- 모델 객체: 컨트롤러에서는 모델 객체만을 사용하여 데이터에 접근합니다. Model 클래스를 상속하여 모델 클래스를 선언합니다. 모델 객체 내부에서는 쿼리 API를 사용합니다.
- 관계 객체: 모델 간의 관계를 나타내는 객체로, 1:1, 1:N, M:N 구조를 표현합니다.
- 쿼리 API: SELECT, INSERT, UPDATE, DELETE 등의 SQL 쿼리문을 간단하게 추상화합니다. 데이터베이스 추상화 레이어를 사용하여 구현합니다.
- 스키마(마이그레이션?) API: DB 구조의 생성 및 변경을 지원하는 API입니다. 이 또한 데이터베이스 추상화 레이어를 사용하여 구현합니다.
- 데이터베이스 추상화 레이어: PHP의 DB 확장 함수 (mysql_*, sqlite_*, ...)를 공통 인터페이스로 사용할 수 있도록 추상화합니다. 또한 DBMS에 따라 달라질 수 있는 일부 SQL 문도 처리합니다. (LIMIT이나 escaping/quoting, 테이블 생성 등)
모델 객체의 사용 예
<?php class Post extends Model { // Post 모델을 선언합니다. var $model = 'post'; // 이 모델이 post라는 것을 명시적으로 선언합니다. // 모델의 속성과 기본값을 지정합니다. var $title; var $body; var $notice = FALSE; // PHP 5.2 이하 버전에서는 Late Static Binding을 지원하지 않는 관계로, 스태틱 메소드를 다시 구현해야 합니다. // static 키워드에 주석 처리를 한 이유는 PHP 4에서 지원하지 않기 때문입니다. /*static*/ function find($id) { return Model::find('post', $id); } // create, update, delete 메소드는 Model 클래스로부터 상속되어 내려오므로 다시 구현할 필요가 없습니다. 필요한 경우 덮어 씌울 수 있습니다. } print_r(Post::find(42)); // ID를 42로 가지는 Post 객체의 구조를 표시합니다. ?>
관계 예제
<?php class Board extends Model { function Board() { // 1:N association mapping $this->posts = $this->has_many('post'); } function get_posts() { return $this->posts->find_all(); } function get_post_count() { return $this->posts->count(); } } ?>
쿼리 API
- find($model, $id)
- $id를 ID로 가지는 모델 객체를 돌려줍니다.
- find_by($model, $key, $value)
- $key 필드가 $value인 모델 객체를 돌려줍니다.
- find_all($model[, $condition[, $order[, $limit[, $offset]]]])
- 모델 객체의 배열을 돌려줍니다. $condition은 WHERE 절에 붙는 조건, $order는 ORDER BY 절에 붙는 정렬 조건, $limit은 레코드 개수, $offset은 시작 위치입니다.
- count_all($model[, $condition])
- $condition을 만족하는 행 개수를 돌려줍니다. 조건을 지정하지 않으면, 전체 행의 개수를 돌려줍니다.
- delete_all($model[, $condition])
- $condition을 만족하는 모든 행을 삭제합니다. 조건이 없을 때는 모든 행이 삭제되므로 조심해서 사용해야 합니다.
- insert($model, $data)
- $data를 가지고 행을 만듭니다.
- update_all($model, $data[, $condition])
- $data를 가지고 $condition을 만족하는 모든 행을 갱신합니다. 조건이 없으면 모든 행에 적용됩니다.
여러 행이 영향을 받을 수 있는 경우 함수 이름 뒤에 _all을 붙였습니다. count_all, delete_all의 경우 내장 함수와 충돌하기 때문에 붙인 것이기도 합니다.
첫번째 인자로 오는 모델 이름으로부터 테이블 이름을 알아냅니다.
스키마 API
테이블 생성 예제
<?php $t = new Table('post'); $t->string('title', 255); $t->text('body'); $t->timestamp('date'); $t->boolean('notice'); $t->index('notice'); $t->create(); ?>
DB 추상화 레이어
DB 엔진 등록
register_driver($id, $class, $description)
<?php class MySQLConnection extends BaseConnection { // ... } register_driver('mysql', 'MySQLConnection', 'MySQL Database'); ?>
연결 클래스
BaseConnection? 클래스를 상속하여 구현합니다.
- open($info)
- 데이터베이스 연결 정보의 배열을 인자로 받고 DB 핸들을 엽니다.
- close()
- 데이터베이스 핸들을 닫습니다.
- execute($query[, $params])
- 쿼리를 실행합니다. 오류가 발생하면 오류를 표시하고 스크립트 실행을 중단합니다. $params가 지정되어 있으면 쿼리에 bind_params 메소드를 적용하여 실행합니다.
- query($query[, $params])
- 쿼리를 실행한 뒤 결과 객체를 돌려줍니다. 오류가 발생하면 오류를 표시하고 스크립트 실행을 중단합니다. $params가 지정되어 있으면 쿼리에 bind_params 메소드를 적용하여 실행합니다.
- last_insert_id($sequence_name)
- 가장 최근 실행된 INSERT 쿼리에서의 시퀀스 ID를 돌려줍니다. $sequence_name은 사용하지 않더라도 반드시 적어줘야 합니다 (PostgreSQL을 위해서.)
- bind_params($query, $params)
- $query의 모든 물음표('?')를 $params 배열의 각 원소로 치환합니다. 이 때 $params 배열의 각 원소는 quote 메소드로 처리해야 합니다.
- escape($string)
- 문자열을 이스케이프 합니다.
- quote($value)
- 주어진 값을 타입에 따라 SQL 리터럴(?)로 변환합니다.
- quote_identifier($id)
- 식별자를 이스케이프 합니다. 식별자는 테이블이나 필드 이름이 될 수 있습니다.
결과 클래스
BaseResultSet? 클래스를 상속하여 구현합니다.
- fetch()
- 현재 행을 연관 배열로 돌려주고 커서 위치를 다음 행으로 옮깁니다.
- fetch_column()
- 현재 행의 첫 열을 돌려주고 커서 위치를 다음 행으로 옮깁니다.
- count()
- 행 개수를 돌려줍니다.
