[PHP] Prepared Statement 에서 동적으로 파라미터 바인딩
일반적으로 MySQLi Prepared Statement 를 사용할 때는 아래와 같이 한다.
<?php
$sql = " select mb_name from `{$db['member_table']}` where mb_id = ? ";
$stmt = $mysqli->stmt_init();
$stmt->prepare($sql);
$stmt->bind_param('s', $mb_id);
$stmt->execute();
$stmt->bind_result($mb_name);
$stmt->fetch();
$stmt->close();
?>
파라미터가 정해져있다면 위 코드는 문제가 없다. 그러나 회원리스트 등에서 검색을 처리하는 등의 과정에서 파라미터 개수가 때에 따라 변하게 된다. 이럴 때 사용할 수 있는 방법은 아래의 코드와 같다.
<?php
$sfl = $_GET['sfl'];
$stx = $_GET['stx'];
$page = (int)$_GET['page'];
$sql_common = " from `{$db['member_table']}` ";
$stmt_types = array();
$stmt_param = array();
$param_type = '';
$bind_param = array();
$sql_search = '';
if($stx) {
if(!$sfl)
$sfl = 'mb_nick';
switch($sfl) {
case 'mb_email':
case 'mb_id':
$sql_search = " where {$sfl} = ? ";
$stmt_types[] = 's';
$stmt_param[] = $stx;
break;
default:
$sql_search = " where {$sfl} like ? ";
$stmt_types[] = 's';
$stmt_param[] = $stx.'%';
}
}
$sql_order = " order by mb_id desc ";
$sql = " select count(*) as cnt {$sql_common} {$sql_search} ";
$type_count = count($stmt_types);
for($i=0; $i<$type_count; $i++) {
$param_type .= $stmt_types[$i];
}
$bind_param[] = & $param_type;
for($i=0; $i<$type_count; $i++) {
$bind_param[] = & $stmt_param[$i];
}
$stmt = $mysqli->stmt_init();
$stmt->prepare($sql);
call_user_func_array(array($stmt, 'bind_param'), $bind_param);
$stmt->execute();
$stmt->bind_result($total_count);
$stmt->fetch();
$stmt->close();
$rows = 10;
$total_page = ceil($total_count / $rows); // 전체 페이지 계산
if ($page < 1) $page = 1; // 페이지가 없으면 첫 페이지 (1 페이지)
$from_record = ($page - 1) * $rows; // 시작 열을 구함
$sql_limit = " limit ?, ? ";
$stmt_types[] = 'i';
$stmt_param[] = $from_record;
$stmt_types[] = 'i';
$stmt_param[] = $rows;
$sql = " select * {$sql_common} {$sql_search} {$sql_order} {$sql_limit} ";
$param_type = '';
$bind_param = array();
$type_count = count($stmt_types);
for($i=0; $i<$type_count; $i++) {
$param_type .= $stmt_types[$i];
}
$bind_param[] = & $param_type;
for($i=0; $i<$type_count; $i++) {
$bind_param[] = & $stmt_param[$i];
}
$stmt = $mysqli->stmt_init();
$stmt->prepare($sql);
call_user_func_array(array($stmt, 'bind_param'), $bind_param);
$stmt->execute();
$data = get_stmt_assoc_array($stmt);
$stmt->close();
?>
위 코드의 핵심은 call_user_func_array() 함수를 이용해 동적으로 파마리터 바인딩을 처리하는 것이다. get_stmt_assoc_array() 함수는 이전 포스트를 참고하면 된다.