그누보드 DB 건드리지 않고, 상담 신청 폼 만드는 법

작성자

카테고리:

‘이벤트’ 게시판 생성 후, 게시판 목록 하단에 상담 신청 영역을 추가해보자.

우선 ftp에 접속해서 ‘/www/skin/board’ 경로로 간다.
사용할 게시판 테마를 basic이든, gallery든 하나 정해서 복사한다.
복사한 폴더 명을 ‘event’로 변경해준다..

테마 스킨을 사용할 경우 테마 안에 있는 board로 가야한다.
/www/theme/테마명/skin/board

동일하게 ‘/www/mobile/skin/board’ 경로로 가서,
하나의 폴더를 복사 후, ‘event’로 폴더명을 변경해준다.

그누보드 관리자에 로그인해서 접속한다.
사용자에게 노출시킬 ‘이벤트’ 게시판을 하나 생성해주자.
게시판 관리 > 게시판 관리 로 가서 ‘게시판 추가’ 버튼을 누른다.

게시판 값들을 입력해준다.

스킨 디렉토리와 모바일 스킨 디렉토리를 새로 만든 ‘event’로 선택해준다.

모든 설정을 마치고 확인을 눌러서 ‘이벤트’ 게시판을 생성한다.

게시판을 하나 더 만든다.
여기에는 상담신청 폼 데이터들이 쌓이게 할 것이기 때문에 메뉴에는 등록하지 않는다.

설정값들을 설정한 후, 확인을 눌러서 ‘상담신청내역’ 게시판을 생성한다.

우선 해야할 일은 3가지다.

  1. list.skin.php 파일 수정 (코드 한줄 넣기)
  2. consultation_form.php 새로 만들기
  3. 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');

이제 저장 기능을 연결할 것이다.

  1. consultation_form.php 위쪽 수정
  2. <form> 시작 태그 교체
  3. consultation.css 맨 아래 추가
  4. 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

이제 상담신청 폼에서 테스트로 정보들을 입력하고,
상담신청내역 게시판에 잘 들어오는지 확인해본다.

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다