‘이벤트’ 게시판 생성 후, 게시판 목록 하단에 상담 신청 영역을 추가해보자.
우선 ftp에 접속해서 ‘/www/skin/board’ 경로로 간다. 사용할 게시판 테마를 basic이든, gallery든 하나 정해서 복사한다. 복사한 폴더 명을 ‘event’로 변경해준다..
테마 스킨을 사용할 경우 테마 안에 있는 board로 가야한다. /www/theme/테마명/skin/board
동일하게 ‘/www/mobile/skin/board’ 경로로 가서, 하나의 폴더를 복사 후, ‘event’로 폴더명을 변경해준다.
그누보드 관리자에 로그인해서 접속한다. 사용자에게 노출시킬 ‘이벤트’ 게시판을 하나 생성해주자. 게시판 관리 > 게시판 관리 로 가서 ‘게시판 추가’ 버튼을 누른다.
게시판 값들을 입력해준다.
스킨 디렉토리와 모바일 스킨 디렉토리를 새로 만든 ‘event’로 선택해준다.
모든 설정을 마치고 확인을 눌러서 ‘이벤트’ 게시판을 생성한다.
게시판을 하나 더 만든다. 여기에는 상담신청 폼 데이터들이 쌓이게 할 것이기 때문에 메뉴에는 등록하지 않는다.
설정값들을 설정한 후, 확인을 눌러서 ‘상담신청내역’ 게시판을 생성한다.
우선 해야할 일은 3가지다.
list.skin.php 파일 수정 (코드 한줄 넣기)
consultation_form.php 새로 만들기
consultation.css 새로 만들기
ftp로 돌아가서, list.skin.php를 찾아서 연다. 경로는 이렇다. /skin/board/event/list.skin.php 파일을 수정할건데 혹시 모르니 백업 파일을 만들어두자.
마크업이 끝나는 지점에 아래 코드를 넣어주자.
<?php include_once($board_skin_path.'/consultation_form.php'); ?>
consultation_form.php 파일을 새로 만들어준다. 여기에는 마크업을 입력하면 된다. 코드는 사용할 폼에 알맞게 변경해주면 된다.
<?php
if (!defined('_GNUBOARD_')) exit;
add_stylesheet(
'<link rel="stylesheet" href="'.$board_skin_url.'/consultation.css">',
0
);
?>
<section class="consultation-wrap">
<div class="consultation-inner">
<div class="consultation-title">
<span>CONSULTATION</span>
<h2>간편 상담 신청</h2>
<p>상담 신청을 남겨주시면 확인 후 연락드리겠습니다.</p>
</div>
<form id="consultationForm" autocomplete="off">
<div class="consultation-fields">
<div class="consultation-field">
<label for="consult_name">성함</label>
<input
type="text"
id="consult_name"
name="consult_name"
placeholder="성함을 입력해주세요"
required
>
</div>
<div class="consultation-field">
<label for="consult_part">상담 부위</label>
<select id="consult_part" name="consult_part" required>
<option value="">상담 부위를 선택해주세요</option>
<option value="유륜">유륜</option>
<option value="외음부">외음부</option>
<option value="팔꿈치">팔꿈치</option>
<option value="겨드랑이">겨드랑이</option>
<option value="기타 부위">기타 부위</option>
</select>
</div>
<div class="consultation-field">
<label for="consult_time">통화 가능 시간</label>
<select id="consult_time" name="consult_time" required>
<option value="">통화 가능 시간을 선택해주세요</option>
<option value="10:00~11:00">10:00~11:00</option>
<option value="11:00~12:00">11:00~12:00</option>
<option value="13:00~14:00">13:00~14:00</option>
<option value="14:00~15:00">14:00~15:00</option>
<option value="15:00~16:00">15:00~16:00</option>
<option value="16:00~17:00">16:00~17:00</option>
<option value="17:00~18:00">17:00~18:00</option>
</select>
</div>
<div class="consultation-field consultation-phone">
<label for="consult_phone">연락처</label>
<input
type="tel"
id="consult_phone"
name="consult_phone"
placeholder="010-0000-0000"
maxlength="13"
required
>
</div>
</div>
<div class="consultation-agree">
<label>
<input
type="checkbox"
id="consult_privacy"
name="consult_privacy"
value="1"
required
>
<span>개인정보 수집 및 이용에 동의합니다.</span>
</label>
<button type="button" class="privacy-detail">
자세히 보기
</button>
</div>
<button type="submit" class="consultation-submit">
상담 신청
</button>
</form>
</div>
</section>
consultation.css 파일을 새로 만들어준다. 여기에는 css를 입력하면 된다.
.consultation-wrap {
margin-top: 100px;
padding: 80px 20px;
background: #f5f7f9;
box-sizing: border-box;
}
.consultation-inner {
width: 100%;
max-width: 1280px;
margin: 0 auto;
}
.consultation-title {
margin-bottom: 40px;
text-align: center;
}
.consultation-title span {
display: block;
margin-bottom: 10px;
color: #2d6388;
font-size: 14px;
font-weight: 700;
letter-spacing: 2px;
}
.consultation-title h2 {
margin: 0 0 12px;
color: #222;
font-size: 36px;
line-height: 1.3;
}
.consultation-title p {
margin: 0;
color: #777;
font-size: 16px;
}
.consultation-fields {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 18px;
}
.consultation-field label {
display: block;
margin-bottom: 9px;
color: #333;
font-size: 15px;
font-weight: 600;
}
.consultation-field input,
.consultation-field select {
width: 100%;
height: 58px;
padding: 0 18px;
border: 1px solid #ddd;
border-radius: 4px;
background: #fff;
color: #333;
font-size: 15px;
box-sizing: border-box;
}
.consultation-field input:focus,
.consultation-field select:focus {
border-color: #2d6388;
outline: none;
}
.consultation-agree {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
margin-top: 30px;
color: #555;
font-size: 14px;
}
.consultation-agree label {
display: flex;
align-items: center;
gap: 7px;
cursor: pointer;
}
.consultation-agree input {
width: 17px;
height: 17px;
margin: 0;
}
.privacy-detail {
padding: 0;
border: 0;
border-bottom: 1px solid #777;
background: none;
color: #777;
font-size: 13px;
cursor: pointer;
}
.consultation-submit {
display: block;
width: 260px;
height: 62px;
margin: 30px auto 0;
border: 0;
border-radius: 4px;
background: #2d6388;
color: #fff;
font-size: 18px;
font-weight: 700;
cursor: pointer;
}
.consultation-submit:hover {
background: #234f6d;
}
@media (max-width: 768px) {
.consultation-wrap {
margin-top: 60px;
padding: 55px 20px;
}
.consultation-title h2 {
font-size: 28px;
}
.consultation-fields {
grid-template-columns: 1fr;
gap: 15px;
}
.consultation-submit {
width: 100%;
}
}
이제 이 3가지 파일을 ‘/skin/board/event’ 경로에 업로드 시켜준다. (list.skin.php, consultation_form.php, consultation.css)
업로드 후, ‘이벤트’ 게시판 화면 새로고침해서 폼이 제대로 보이는지 확인하자. 아래처럼 나오면 잘 된 것이다.
이제 다음 단계는 상담 신청 버튼을 누르면 consultation 게시판에 저장되도록 연결 하는 것이다.
우선 그누보드 버전을 확인해야한다. 그누보드 최상단 /www 경로에서 ‘config.php’ 찾아서 열어본다. Ctrl+F를 눌러 ‘G5_VERSION’를 검색해보면, 아래처럼 생긴 것이 있을 것이다. 이것이 버전이다.
define('G5_VERSION', '5.6.10');
검색이 되지 않는다면, 아래와 같이 설정이 어디에 있는지 적혀있는 줄이 있을 것이다. 현재 홈페이지의 경우 ‘version.php’에 있다고 한다.
include_once($g5_path['path'].'/version.php'); // 설정 파일
그누보드 최상단 /www 경로에서 ‘version.php’ 찾아서 열어본다. 그누보드 5.6.8 이란 것을 확인 할 수 있다.
define('G5_GNUBOARD_VER', '5.6.8');
이제 저장 기능을 연결 할 것이다.
consultation_form.php 위쪽 수정
<form> 시작 태그 교체
consultation.css 맨 아래 추가
consultation_submit.php 생성
1. consultation_form.php 위쪽 수정
기존 상단 PHP 안에 토큰 생성 코드를 추가한다.
// 상담 신청 보안 토큰
$consult_token = md5(uniqid((string) mt_rand(), true));
set_session('ss_consult_token', $consult_token);
set_session('ss_consult_started', G5_SERVER_TIME);
2. <form> 시작 태그 교체
‘<form id=”consultationForm” autocomplete=”off”>’ 위 한 줄을 아래와 같이 바꾼다.
<form
id="consultationForm"
action="<?php echo $board_skin_url; ?>/consultation_submit.php"
method="post"
autocomplete="off"
>
<input
type="hidden"
name="consult_token"
value="<?php echo $consult_token; ?>"
>
<!-- 자동등록 프로그램 확인용 -->
<div class="consultation-trap" aria-hidden="true">
<label for="consult_website">홈페이지</label>
<input
type="text"
id="consult_website"
name="consult_website"
tabindex="-1"
autocomplete="off"
>
</div>
3. consultation.css 맨 아래 추가
.consultation-trap {
position: absolute !important;
left: -9999px !important;
width: 1px !important;
height: 1px !important;
overflow: hidden !important;
}
4. consultation_submit.php 생성
<?php
$g5_path['path'] = '../../..';
include_once($g5_path['path'].'/common.php');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
alert('올바른 방법으로 이용해주세요.');
}
// 상담 저장 게시판
$bo_table = 'consultation';
$write_table = $g5['write_prefix'].$bo_table;
// 상담 게시판 존재 여부 확인
$board = sql_fetch("
select *
from {$g5['board_table']}
where bo_table = '{$bo_table}'
");
if (empty($board['bo_table'])) {
alert('상담 게시판이 존재하지 않습니다.');
}
// 보안 토큰 확인
$session_token = get_session('ss_consult_token');
$post_token = isset($_POST['consult_token'])
? trim($_POST['consult_token'])
: '';
if (
!$session_token ||
!$post_token ||
!hash_equals($session_token, $post_token)
) {
alert('잘못된 접근입니다. 페이지를 새로고침한 후 다시 신청해주세요.');
}
// 한 번 사용한 토큰 제거
set_session('ss_consult_token', '');
// 너무 빠른 자동등록 방지
$started = (int) get_session('ss_consult_started');
set_session('ss_consult_started', '');
if (!$started || G5_SERVER_TIME - $started < 2) {
alert('잠시 후 다시 신청해주세요.');
}
// 숨겨진 항목에 값이 있으면 자동등록으로 판단
$website = isset($_POST['consult_website'])
? trim($_POST['consult_website'])
: '';
if ($website !== '') {
alert('올바른 방법으로 이용해주세요.');
}
// 입력값 받기
$consult_name = isset($_POST['consult_name'])
? trim(strip_tags($_POST['consult_name']))
: '';
$consult_part = isset($_POST['consult_part'])
? trim(strip_tags($_POST['consult_part']))
: '';
$consult_time = isset($_POST['consult_time'])
? trim(strip_tags($_POST['consult_time']))
: '';
$consult_phone = isset($_POST['consult_phone'])
? preg_replace('/[^0-9]/', '', $_POST['consult_phone'])
: '';
$consult_privacy = isset($_POST['consult_privacy'])
? $_POST['consult_privacy']
: '';
// 필수 입력값 확인
if ($consult_name === '') {
alert('성함을 입력해주세요.');
}
if (mb_strlen($consult_name, 'UTF-8') > 30) {
alert('성함을 올바르게 입력해주세요.');
}
// 허용된 상담 부위
$allowed_parts = array(
'유륜',
'외음부',
'팔꿈치',
'겨드랑이',
'기타 부위'
);
if (!in_array($consult_part, $allowed_parts, true)) {
alert('상담 부위를 선택해주세요.');
}
// 허용된 통화 시간
$allowed_times = array(
'10:00~11:00',
'11:00~12:00',
'13:00~14:00',
'14:00~15:00',
'15:00~16:00',
'16:00~17:00',
'17:00~18:00'
);
if (!in_array($consult_time, $allowed_times, true)) {
alert('통화 가능 시간을 선택해주세요.');
}
// 휴대전화 번호 확인
if (!preg_match('/^01[0-9]{8,9}$/', $consult_phone)) {
alert('연락처를 정확히 입력해주세요.');
}
if ($consult_privacy !== '1') {
alert('개인정보 수집 및 이용에 동의해주세요.');
}
// 동일 IP의 연속 등록 방지
$consult_ip = isset($_SERVER['REMOTE_ADDR'])
? preg_replace('/[^0-9a-fA-F:\.]/', '', $_SERVER['REMOTE_ADDR'])
: '';
$recent = sql_fetch("
select wr_datetime
from {$write_table}
where wr_ip = '".addslashes($consult_ip)."'
order by wr_id desc
limit 1
");
if (
!empty($recent['wr_datetime']) &&
G5_SERVER_TIME - strtotime($recent['wr_datetime']) < 30
) {
alert('이미 상담 신청이 접수되었습니다. 잠시 후 다시 시도해주세요.');
}
// DB 저장용 처리
$wr_name = addslashes(clean_xss_tags($consult_name));
$wr_part = addslashes(clean_xss_tags($consult_part));
$wr_time = addslashes(clean_xss_tags($consult_time));
$wr_phone = addslashes($consult_phone);
$wr_subject = addslashes(
'[상담신청] '.$consult_name.' / '.$consult_part
);
$wr_content = addslashes(
"성함: {$consult_name}\n".
"상담 부위: {$consult_part}\n".
"통화 가능 시간: {$consult_time}\n".
"연락처: {$consult_phone}\n".
"개인정보 수집 동의: 동의"
);
$wr_password = get_encrypt_string(
uniqid('consult_', true)
);
// 상담 게시글 저장
$sql = "
insert into {$write_table}
set
wr_num = (
select ifnull(min(wr_num) - 1, -1)
from {$write_table} as sq
),
wr_reply = '',
wr_comment = 0,
ca_name = '',
wr_option = 'secret',
wr_subject = '{$wr_subject}',
wr_content = '{$wr_content}',
wr_seo_title = '',
wr_link1 = '',
wr_link2 = '',
wr_link1_hit = 0,
wr_link2_hit = 0,
wr_hit = 0,
wr_good = 0,
wr_nogood = 0,
mb_id = '',
wr_password = '{$wr_password}',
wr_name = '{$wr_name}',
wr_email = '',
wr_homepage = '',
wr_datetime = '".G5_TIME_YMDHIS."',
wr_last = '".G5_TIME_YMDHIS."',
wr_ip = '".addslashes($consult_ip)."',
wr_1 = '{$wr_part}',
wr_2 = '{$wr_time}',
wr_3 = '{$wr_phone}',
wr_4 = '동의',
wr_5 = '',
wr_6 = '',
wr_7 = '',
wr_8 = '',
wr_9 = '',
wr_10 = ''
";
sql_query($sql);
$wr_id = sql_insert_id();
// 부모 글 번호 설정
sql_query("
update {$write_table}
set wr_parent = '{$wr_id}'
where wr_id = '{$wr_id}'
");
// 최신글 테이블 등록
sql_query("
insert into {$g5['board_new_table']}
(bo_table, wr_id, wr_parent, bn_datetime, mb_id)
values
('{$bo_table}', '{$wr_id}', '{$wr_id}', '".G5_TIME_YMDHIS."', '')
");
// 게시판 글 개수 증가
sql_query("
update {$g5['board_table']}
set bo_count_write = bo_count_write + 1
where bo_table = '{$bo_table}'
");
// 원래 이벤트 페이지로 이동
$return_url = isset($_SERVER['HTTP_REFERER'])
? $_SERVER['HTTP_REFERER']
: G5_URL;
alert(
'상담 신청이 완료되었습니다. 확인 후 연락드리겠습니다.',
$return_url
);
?>
이 3가지 파일을 ‘/skin/board/event’ 경로에 업로드 시켜준다. consultation_form.php consultation.css consultation_submit.php
이제 상담신청 폼에서 테스트로 정보들을 입력하고, 상담신청내역 게시판에 잘 들어오는지 확인해본다.