테스트 사이트 - 개발 중인 베타 버전입니다

index.php 에서만 문의 등록 폼이 안되는 이유 채택완료

이학권 4개월 전 조회 1,516

안녕하세요. 오랜만에 문의 남깁니다.

 

제가 사이트를 하나 만들어 보고 있는데요

 

index 페이지와 렌딩 페이지가 있을때

동일한 상담문의 폼을 그대로 복붙해도

 

렌딩 페이지에서는 정상적으로 문의 게시글이 작성되고,

index 페이지에서는 상담문의 성공 얼럿이 뜨지만 문의 게시글이 작성되지 않습니다.

 

아래는 해당 코드입니다.

 

</p>

<p><div class="custom-main-banner">

    <div class="banner-container">

        <div class="banner-left">

            <h2>온라인 상담 신청</h2></p>

<p>            <form id="consultForm" action="제 도메인 주소/bbs/write_update.php" method="post">

                <input type="hidden" name="bo_table" value="tl_qa">

                <input type="hidden" name="wr_id" value="">

                <input type="hidden" name="sca" value="">

                <input type="hidden" name="w" value="">

                <input type="hidden" name="html" value="html1">

                <!-- CSRF 방지를 위한 토큰 추가 -->

                <input type="hidden" name="token" value="<?php echo get_write_token('tl_qa'); ?>">

                </p>

<p>                <div class="form-group">

                    <label for="name"></label>

                    <input type="text" id="name" name="wr_name" placeholder="이름" required />

                    <input type="hidden" name="wr_subject" id="wr_subject_hidden" />

                </div></p>

<p>                <div class="form-group">

                    <label for="phone"></label>

                    <input type="tel" id="phone" name="wr_content" placeholder="‘-’ 없이 숫자만 입력" pattern="[0-9]{11,14}" required />

                </div></p>

<p>                <div class="form-group">

                    <label for="selectCategory"></label>

                    <select id="selectCategory" name="consult_type">

                        <option value="상담신청">상담신청</option>

                        <option value="상품1">상품1</option>

                        <option value="상품2">상품2</option>

                        <option value="상품3">상품3</option>

                        <option value="상품4">상품4</option>

                        <option value="상품5">상품5</option>

                    </select>

                </div></p>

<p>                <div class="form-check">

                    <input type="checkbox" id="agree" checked />

                    <label for="agree">개인정보 수집 및 이용 동의 <a href="#" id="openModal">자세히보기</a></label>

                </div></p>

<p>                <button class="btn-submit blue" type="submit">빠른 상담</button>

            </form></p>

<p>            <!-- 개인정보 수집 모달 -->

            <div class="memo__modal" id="privacyModal" style="display: none;">

                <div class="memo-modal__inner">

                    <div class="memo-modal__close" id="closeModal">닫기</div>

                    <div class="memo-modal__txt">

                        <h3>개인(신용)정보의 수집,이용에 관한사항</h3>

                        <p>[개인정보보호법] 및 [신용정보의 이용 및 보호에 관한 법률]에 따라 아래와 같은 내용으로 본인의 개인정보 수집·이용에 동의합니다.</p>

                       기타 개인정보 내용

                    </div>

                </div>

            </div>

        </div>

        <div class="banner-right">

            <div class="banner-card">

                <span class="card-label">상품1</span>

                <h3>상품1</h3>

                <p>어쩌고저쩌고</p>

                <div class="card-image"><img src="<?=G5_THEME_URL?>/img/cnimg.png" alt="상품1"></div>

                <a href="/theme/sample03/html/렌딩.php" class="goto-button">바로가기</a>

            </div>

            <div class="banner-card">

                <span class="card-label">상품1</span>

                <h3>상품1</h3>

                <p>어쩌고저쩌고</p>

                <div class="card-image"><img src="<?=G5_THEME_URL?>/img/cnimg.png" alt="상품1"></div>

                <a href="/theme/sample03/html/렌딩.php" class="goto-button">바로가기</a>

            </div>

            <div class="banner-card">

                <span class="card-label">상품1</span>

                <h3>상품1</h3>

                <p>어쩌고저쩌고</p>

                <div class="card-image"><img src="<?=G5_THEME_URL?>/img/cnimg.png" alt="상품1"></div>

                <a href="/theme/sample03/html/렌딩.php" class="goto-button">바로가기</a>

            </div>

            <div class="banner-card">

                <span class="card-label">상품1</span>

                <h3>상품1</h3>

                <p>어쩌고저쩌고</p>

                <div class="card-image"><img src="<?=G5_THEME_URL?>/img/cnimg.png" alt="상품1"></div>

                <a href="/theme/sample03/html/렌딩.php" class="goto-button">바로가기</a>

            </div>

            <div class="banner-card">

                <span class="card-label">상품1</span>

                <h3>상품1</h3>

                <p>어쩌고저쩌고</p>

                <div class="card-image"><img src="<?=G5_THEME_URL?>/img/cnimg.png" alt="상품1"></div>

                <a href="/theme/sample03/html/렌딩.php" class="goto-button">바로가기</a>

            </div>

        </div>

    </div>

</div></p>

<p> </p>

<p><script></p>

<p>// 오류 로그 저장 함수

function saveErrorLog(data) {

    const timestamp = new Date().toISOString();

    const logEntry = { 

        timestamp, 

        sessionId: document.cookie.match(/PHPSESSID=([^;]+)/)?.[1] || 'none',

        referer: window.location.href,

        cookies: document.cookie,

        ...data 

    };

    let logs = JSON.parse(localStorage.getItem('ormErrors') || '[]');

    logs.push(logEntry);

    localStorage.setItem('ormErrors', JSON.stringify(logs));

    console.log('Error log saved:', logEntry);

}</p>

<p>document.getElementById('consultForm').addEventListener('submit', function(e) {

    e.preventDefault(); // Prevent default form submission</p>

<p>    const form = e.target;</p>

<p>    const name = document.getElementById('name').value.trim();

    const phone = document.getElementById('phone').value.trim();

    const consultTypeElement = form.querySelector('select[name="consult_type"]');

    const consultType = consultTypeElement ? consultTypeElement.value : '상담신청';

    const agree = document.getElementById('agree').checked;</p>

<p>    // 1. Name validation: Korean characters, 2-5 letters

    const namePattern = /^[가-힣]{2,5}$/;

    const invalidNamePattern = /^(?:[ㄱ-ㅎㅏ-ㅣ]+)$/;

    const repeatedCharPattern = /^(.)\1+$/;

    if (!namePattern.test(name)) {

        alert("이름은 2~5글자 한글로 입력해 주세요.");

        return;

    }

    if (invalidNamePattern.test(name) || repeatedCharPattern.test(name)) {

        alert("이름을 확인해 주세요.");

        return;

    }</p>

<p>    // 2. Phone validation: 11-14 digits (aligned with cancer.txt)

    const phonePattern = /^[0-9]{11,14}$/;

    if (!phonePattern.test(phone)) {

        alert("연락처는 11~14자리 숫자만 입력해 주세요.");

        return;

    }</p>

<p>    if (!agree) {

        alert("개인정보 수집 및 이용에 동의해야 상담이 가능합니다.");

        return;

    }</p>

<p>    // 3. Construct post content with consult type

    const currentPageUrl = window.location.href;

    const postContent = `상담신청: ${consultType}
이름: ${name}
연락처: ${phone}
신청페이지: ${currentPageUrl}`;</p>

<p>    // Debugging: Log post content and form fields

    console.log("postContent:", postContent);

    console.log("Form fields:", {

        bo_table: form.querySelector('input[name="bo_table"]').value,

        wr_name: name,

        wr_content: postContent,

        wr_subject: name + " 님의 상담 요청",

        consult_type: consultType

    });</p>

<p>    // Set subject and content

    const subjectHidden = document.getElementById('wr_subject_hidden');

    if (subjectHidden) {

        subjectHidden.value = name + " 님의 상담 요청";

    }

    const phoneInput = document.getElementById('phone');

    if (phoneInput) {

        phoneInput.value = postContent;

    }</p>

<p>    // Debugging: Log FormData

    const formData = new FormData(form);

    for (let [key, value] of formData.entries()) {

        console.log(`FormData: ${key} = ${value}`);

    }</p>

<p>    // AJAX request

    fetch(form.action, {

        method: 'POST',

        body: formData

    })

    .then(response => {

        // Debugging: Log response status and headers

        console.log("Response status:", response.status, response.statusText);

        console.log("Response headers:", [...response.headers.entries()]);

        if (!response.ok) {

            throw new Error(`HTTP error! Status: ${response.status} ${response.statusText}`);

        }

        return response.text();

    })

    .then(responseText => {

        // Debugging: Log response text

        console.log("Response text:", responseText);

        // Use cancer.txt's success condition

        if (responseText.includes("location.replace") || responseText.includes("onclick=")) {

            alert("상담 신청이 완료되었습니다.");

            form.reset();

        } else {

            alert("전송에 실패했습니다. 다시 시도해 주세요.");

            console.error("Unexpected response:", responseText);

        }

    })

    .catch(error => {

        console.error("Fetch error:", error);

        alert("서버 오류가 발생했습니다: " + error.message);

    });

});</p>

<p>// Modal open/close (integrated from cancer.txt and index_n.txt)

document.getElementById('openModal').addEventListener('click', function(e) {

    e.preventDefault();

    document.getElementById('privacyModal').style.display = 'flex';

});</p>

<p>document.getElementById('closeModal').addEventListener('click', function() {

    document.getElementById('privacyModal').style.display = 'none';

});</p>

<p>// index_n.txt's existing banner slider and modal script

document.addEventListener('DOMContentLoaded', function() {

    const bannerRight = document.querySelector('.banner-right');

    let isDown = false;

    let startX;

    let scrollLeft;

    let autoScroll;</p>

<p>    // Drag functionality

    bannerRight.addEventListener('mousedown', (e) => {

        isDown = true;

        bannerRight.classList.add('active');

        startX = e.pageX - bannerRight.offsetLeft;

        scrollLeft = bannerRight.scrollLeft;

        clearInterval(autoScroll);

        bannerRight.style.scrollBehavior = 'auto';

    });</p>

<p>    bannerRight.addEventListener('mouseleave', () => {

        isDown = false;

        bannerRight.classList.remove('active');

        bannerRight.style.scrollBehavior = 'smooth';

        startAutoScroll();

    });</p>

<p>    bannerRight.addEventListener('mouseup', () => {

        isDown = false;

        bannerRight.classList.remove('active');

        bannerRight.style.scrollBehavior = 'smooth';

        startAutoScroll();

    });</p>

<p>    bannerRight.addEventListener('mousemove', (e) => {

        if (!isDown) return;

        e.preventDefault();

        const x = e.pageX - bannerRight.offsetLeft;

        const walk = (x - startX) * 2;

        bannerRight.scrollLeft = scrollLeft - walk;

    });</p>

<p>    // Touch functionality

    bannerRight.addEventListener('touchstart', (e) => {

        isDown = true;

        startX = e.touches[0].pageX - bannerRight.offsetLeft;

        scrollLeft = bannerRight.scrollLeft;

        clearInterval(autoScroll);

        bannerRight.style.scrollBehavior = 'auto';

    });</p>

<p>    bannerRight.addEventListener('touchend', () => {

        isDown = false;

        bannerRight.style.scrollBehavior = 'smooth';

        startAutoScroll();

    });</p>

<p>    bannerRight.addEventListener('touchmove', (e) => {

        if (!isDown) return;

        const x = e.touches[0].pageX - bannerRight.offsetLeft;

        const walk = (x - startX) * 2;

        bannerRight.scrollLeft = scrollLeft - walk;

    });</p>

<p>    // Auto-scroll functionality

    function startAutoScroll() {

        clearInterval(autoScroll);

        autoScroll = setInterval(() => {

            const cardWidth = window.innerWidth <= 768 ? 200 + 20 : 250 + 20;

            const maxScroll = bannerRight.scrollWidth - bannerRight.clientWidth;</p>

<p>            if (bannerRight.scrollLeft + cardWidth >= maxScroll) {

                setTimeout(() => {

                    bannerRight.style.scrollBehavior = 'auto';

                    bannerRight.scrollLeft = 0;

                    bannerRight.style.scrollBehavior = 'smooth';

                }, 500);

            } else {

                bannerRight.scrollLeft += cardWidth;

            }

        }, 2000);

    }</p>

<p>    bannerRight.style.scrollBehavior = 'smooth';

    startAutoScroll();

});

</script></p>

<p>

 

조언 부탁드립니다ㅠㅠ

그누5 버전은 가장 최신이고 

서버 환경은 UTF-8 (PHP8.4, mariadb-10.x) 입니다.

 

댓글을 작성하려면 로그인이 필요합니다.

답변 4개

채택된 답변
+20 포인트
웅푸
4개월 전
로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

이학권
4개월 전
좋은 자료 알려주셔서 감사합니다!

아직 정확한 원인은 못찾았는데 이 자료로 설치 후 테스트해보다가
테이블명만 다른 게시글로 변경했는데 잘 작동하네요;;

다른 렌딩페이지에서는 기존대로 tl_qa 테이블로 잘 쌓이고
메인은 다른 테이블명으로 수정하니까 되네요;;;

도움 주셔서 감사합니다!

댓글을 작성하려면 로그인이 필요합니다.

4개월 전

아래 3개중에 하나일것 같은데 확인한번 해보세요

 

PHP 토큰 미처리    index.html → index.php로 변경 + common.php 포함
JS 값 누락    wr_subject, wr_content가 정상적으로 세팅되는지 확인
응답만 받음    fetch 응답 확인 + 서버단 POST값 수신 여부 확인

로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

이학권
4개월 전
답변 감사합니다~!

댓글을 작성하려면 로그인이 필요합니다.

4개월 전

index 에 common 파일 인클루드 되어있나요?

로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

이학권
4개월 전
안녕하세요! 답변 감사합니다

include_once('./_common.php');

이렇게 들어가 있습니다~!

댓글을 작성하려면 로그인이 필요합니다.

4개월 전

ai로 한건가요?? 

암튼 저거 개발자도구 켜서 네트워크로 확인해보세요

에러 로그로 내용이 잘 들어가는데 페이로드 문제 없는지 그리고 응답이나 시작점 눌러서 json 출력 잘되는지 꼼꼼히 확인해보세요

로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

이학권
4개월 전
안녕하세요! 답글 감사합니다! 네 ai로 만들어보고있습니다~! Ai도 이 문제를 해결못하고 비슷한 답변만 계속 뽑아내더라구요ㅜ 조언감사합니다!

댓글을 작성하려면 로그인이 필요합니다.

답변을 작성하려면 로그인이 필요합니다.

로그인