PHP 기반 애플리케이션 개발 시 데이터베이스(DB) 레코드를 객체 지향적으로 다루기 위한 데이터 모델 클래스 패턴입니다. 싱글톤 패턴 응용 방식인 instance() 팩토리 메서드부터 PDO 기반 데이터 로딩(load), 목록 조회(retrieve) 메서드 구현 예제를 정리합니다.
📌 목차
- 1. 인스턴스 캐싱 (멀티턴 싱글톤 패턴)
- 2. 단일 데이터 로딩 (load)
- 3. 목록 데이터 페이징 조회 (retrieve)
- 4. 전체 클래스 구조 및 모범 사례
1. 인스턴스 캐싱 (멀티턴 싱글톤 패턴)
동일한 PK(Primary Key)를 가진 객체가 중복 생성되는 것을 방지하고 메모리를 절약하기 위해 정적 배열에 인스턴스를 캐싱하는 방식을 사용합니다.
// PK 기반 객체 인스턴스 재사용 (Multiton Pattern)
static public function instance($pk)
{
static $sInstance = array();
$pk = intval($pk);
if (isset($sInstance[$pk]) === false) {
$className = __CLASS__;
$obj = new $className($pk);
$sInstance[$pk] = $obj;
}
return $sInstance[$pk];
}
public function __construct($id = null)
{
$this->id = $id;
}
2. 단일 데이터 로딩 (load)
생성자에서 전달받은 식별자($this->id)를 기준으로 PDO 바인딩 처리를 수행하여 DB 데이터를 불러온 뒤 멤버 변수에 매핑합니다.
/**
* 데이터베이스에서 정보를 읽어와 멤버변수에 정의합니다.
* @return $this
*/
public function load()
{
if (!$this->id) {
return $this;
}
$pdo = PDO_Manage::getConnectDB();
$query = 'SELECT *
,(SELECT count(1)
FROM ' . self::moodlesjc . 'm_cdms_lecture
WHERE subjectid = t.id AND confirm = 2) as lectotal2
FROM ' . self::moodlesjc . 'm_cdms_subject t
WHERE id = :id';
$stmt = $pdo->prepare($query);
$stmt->bindValue(':id', $this->id, PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row) {
$this->loadByRowData($row);
}
return $this;
}
3. 목록 데이터 페이징 조회 (retrieve)
검색 조건 및 페이징 처리를 포함하여 조건에 부합하는 여러 레코드를 객체 배열(Array of Objects) 형태로 반환하는 정적 메서드입니다.
public static function retrieve($param = null)
{
$pdo = PDO_Manage::getConnectDB();
// MSSQL Window Function 기반 서브쿼리 작성
$query = 'SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (ORDER BY id DESC) AS Seq
FROM ' . self::moodlesjc . 'm_cdms_subject
' . self::_makeWhere($param) . '
) t ';
$where = self::_makeMssqlPaging($param);
$stmt = $pdo->prepare($query . $where . self::_makeSort($param));
self::_doBindValue($stmt, $param);
$stmt->execute();
$retrieveArr = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$cdmsSubject = new cdmsSubject();
$cdmsSubject->loadByRowData($row);
$retrieveArr[] = $cdmsSubject;
}
return $retrieveArr;
}
public function add()
{
// C(Create) 등록 로직 구현
}
public function modify()
{
// U(Update) 수정 로직 구현
}
4. 전체 클래스 구조 및 모범 사례
위와 같은 형태의 데이터 모델 클래스를 작성할 때는 다음 사안들을 고려하는 것이 바람직합니다.
- 메모리 관리: instance() 메서드로 동일 PK 객체의 중복 조회를 방지하여 메모리 오버헤드를 낮출 수 있습니다.
- 바인딩 처리: SQL Injection 방지를 위해 동적 파라미터는 항상 Prepared Statement의 bindValue()를 활용합니다.
- 체이닝 지원: $this->load()와 같이 메서드가 $this를 반환하면 $obj->load()->getName()과 같은 체이닝 표현식이 가능합니다.