ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (기능추가4-3) 작성자 테이블 구축, 양식초기화, select 태그
    프로젝트/프로젝트_사진첩 2023. 9. 9. 20:21

    전체소스코드

    index.php

    <?php
    $conn=mysqli_connect("localhost:81","root","mysql","project_memories");

    $sql = "SELECT * FROM who";
    $result = mysqli_query($conn, $sql);
    $select_form = '<select id="select" name="creater"><option disabled selected>누구야?</option>';
    //option기본값을 disabled된(false값) 값으로 selected(기본값으로 설정) 함으로써 사용자가 이미지만 업로드하여 제출되는 일이 없도록 만듬
    while($row = mysqli_fetch_array($result)){
        $select_form .= '<option value="'.$row['id'].'">'.$row['creater'].'</option>';
    }
    $select_form .= '</select>'; //select 태그를 추가하여 이미지 업로드시 작성자를 표시함
    ?>

    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Memories</title>
        <link rel="preconnect" href="https://fonts.googleapis.com">
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    //구글 웹폰트로 나눔고딕 추가
        <link href="style_index.css" rel="stylesheet">
        <script>
        function autoSubmit() {
            var form = document.getElementById('uploadForm');
            form.submit();
        }
        </script>
    </head>

    <body>
        <div class="layout">
            <div class="titleBox">
                <div class="titleName">Memories</div>
                <form id="uploadForm" action="" method="POST" enctype="multipart/form-data">
                    <input type="hidden" name="upload" value="1">
                    <label class="uploadBotton" for="uploadInput">+</label>
                    <input type="file" id="uploadInput" style="display:none" name="image" onchange="autoSubmit()">
                    <?=$select_form?>
                </form>    
            </div>

            <?php
            session_start(); //session에 대한 설명은 아랫쪽에서 참고.

                if(isset($_POST['upload'])) {
                    $file = addslashes(file_get_contents($_FILES["image"]["tmp_name"]));
                    $filtered_id = mysqli_real_escape_string($conn, $_POST['creater']);
                    $sql = "insert into image (image,created,who_id) values('$file',NOW(),'$filtered_id')";
    //image테이블에 who_id칼럼을 추가하여 누가 작성하였는지 알수잇도록 함
                    if(mysqli_query($conn, $sql))
                    {
                        $_SESSION['message'] = "헤헤 고맙따!";
                        header("Location: ".$_SERVER['PHP_SELF']); 
                        exit(); //작성후 리다이렉트함으로써 POST로 제출된 값이 초기화되도록 함.
                    }else
                    {
                        $_SESSION['message'] = "밍..실패했어오!";
                        header("Location: ".$_SERVER['PHP_SELF']);
                        exit();
                    }
                }

                if(isset($_SESSION['message'])) {
                echo '<script type="text/javascript"> alert("' . $_SESSION['message'] . '"); </script>';
                unset($_SESSION['message']);
                }

                $sql = "select * from image order by id desc limit 18";
                $result = mysqli_query($conn, $sql);
                ?>

            <div id="photoLayout" class="photoLayout">    
                <?php    
                    while($row = mysqli_fetch_array($result))
                    {
                        echo '<div class="photo"><a href="image_display230906.php?id='.$row['id'].'">
                        <img class="img" src="data:image;base64,'.base64_encode($row['image']).'" alt="Image"></a>
                        </div>';
                    }
            ?>
            </div>
        <!-- <script>
            window.onscroll = function() {
                if((window.innerHeight + Math.ceil(window.scrollY))>= document.body.offsetHeight) {
                    let Newphoto = document.createElement('div');
                    Newphoto.classList.add('photo');
                    document.getElementById('photoLayout').appendChild(Newphoto);
                }
            }
        </script> -->
    </body>

    </html>

    session에 관한 AI의 답변(session 사용 이유 : 이미지 업로드폼 제출전 echo를 사용하니 alert창이 출력되지않았음)

    -리다이렉션을 수행하면서 동시에 메시지를 보여주려면, 세션(session)을 이용하는 방법이 있습니다. 세션은 서버 측에서 사용자의 상태 정보를 저장하는 기술로, 웹 브라우저가 종료되기 전까지는 정보가 유지됩니다.

    1. session_start();: PHP에서 세션을 사용하기 위해서는 반드시 session_start(); 함수를 호출해야 합니다. 이 함수는 현재 세션 ID를 초기화하거나 복원합니다. 이 함수가 호출되면, PHP는 현재 세션 ID와 연관된 서버에 저장된 세션 데이터를 불러옵니다.
    2. $_SESSION['message'] = "헤헤 고맙따!";: $_SESSION은 PHP의 슈퍼글로벌 변수 중 하나로, 웹 페이지 간에 정보를 공유하는 데 사용됩니다. 여기서 'message'라는 키에 메시지 문자열을 저장하고 있습니다.
    3. header("Location: ".$_SERVER['PHP_SELF']);: 이 코드는 현재 페이지로 리다이렉트합니다. 이 때, 서버에 저장된 세션 데이터도 유지됩니다.
    4. exit();: 리다이렉트 후에 추가적인 코드 실행을 막기 위해 스크립트를 종료합니다.
    5. if(isset($_SESSION['message'])) {...}: 새로운 페이지가 로드되면, 우리가 설정한 'message'라는 키의 값이 있는지 확인합니다.
    6. 'alert("' . $_SESSION['message'] . '");': JavaScript alert 창으로 메시지를 출력합니다.

    7.unset($_SESSION['message']);: 한 번 메시지가 출력되면 그 값을 삭제하여 다음 새로고침에서 같은 메시지가 또 출력되지 않게 합니다.

    8.세션이란 클라이언트(웹 브라우저)와 서버 간의 연결 상태를 유지하는 기술입니다. HTTP 프로토콜은 상태 정보(stateless)를 기억하지 않으므로, 사용자나 클라이언트의 상태 정보를 알아야 하는 경우 (로그인 정보 등), 그 정보들을 일정 시간 동안 유지할 필요가 있습니다. 세션이 활용되면서 웹 사이트에서 사용자 인증 및 개인화 등 다양한 기능을 제공할 수 있게 되었습니다.

     

    양식제출을 초기화하기 위한 코드에 대한 설명

     

    웹 페이지에서 form 제출 후 새로고침을 하면 이전에 제출했던 양식이 다시 제출되는 문제를 해결하려면, 일반적으로 'Post/Redirect/Get' (PRG) 패턴을 사용합니다.

    PHP에서는 header() 함수를 사용하여 리다이렉션을 수행할 수 있습니다. 이를 통해, form 데이터가 서버로 전송된 후에 페이지를 다른 위치로 리다이렉트하여 새로고침 시 데이터가 중복으로 전송되는 것을 방지할 수 있습니다.

    여기서 주의해야 할 점은 header() 함수는 HTTP 헤더 정보를 수정하기 때문에, 이 함수 호출 전에 어떠한 출력도 발생하면 안된다는 것입니다. 즉, echo, print 등의 출력문 또는 HTML 코드 등이 미리 실행되어서는 안됩니다.(session을 사용한 이유)

    아래 코드에서 확인할 수 있듯이 form 제출 성공 후에 페이지를 자신 자신($_SERVER['PHP_SELF'])으로 리다이렉트합니다:

     

    display_image.php

    <?php
    $conn=mysqli_connect("localhost:81","root","password","project_memories");
    $image_display='';
    $formatted_date='';
    if (isset($_GET['id'])){
        $filtered_id = mysqli_real_escape_string($conn, $_GET['id']);
        $sql = "SELECT * FROM image LEFT JOIN who ON image.who_id=who.id WHERE image.id={$filtered_id}"
    //who 테이블을 새로 만들어서 left join을 통해 정규화를 시킴
        $result = mysqli_query($conn, $sql);
        $row = mysqli_fetch_array($result);
        $article = array(
            'created' => htmlspecialchars($row['created']),
            'image' => $row['image'],
            'creater' => htmlspecialchars($row['creater']) //'who'의 자리에 누가만들엇는지 넣기 위해 추가
        );
        $image_display =
        '<img src="data:image;base64,'.base64_encode($article['image']).'"alt="Image" style="width: 100%; height: 100%;">';
        $formatted_date = date("y년 m월 d일", strtotime($article['created']));
    } else {
        header("Location: index230906.php"); //id 파라미터가 없는 경우, 보여줄 사진이 없기때문에 홈페이지로 리다이렉트
    }
    ?>
    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Memories</title>
        <link rel="preconnect" href="https://fonts.googleapis.com">
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <link href="style_display.css" rel="stylesheet">
    </head>
    <body>
        <div class="layout">
            <div class="topLayout">
                <div class="titleContents" id="who"><?=$article['creater']?></div> //작성자를 DB에서 불러와 표시
                <div class="titleContents" id="when"><?=$formatted_date?></div>
                <div class="titleContents" id="close"><a href="index230906.php">X</a></div>
            </div>
            <div class="photo">
                <div class="photoLayout" id="leftLayout">
                    <?=$image_display?>
                </div>
                <div class="photoLayout" id="rightLayout">
                    <div class="chatLayout"></div>
                    <div class="chatInputLayout">
                        <!-- <form action="" method="post">
                            <input type="text">
                            <input type="submit"> -->
                    </div>
                </div>
            <div>
        </div>
    </body>
    </html>

    css 추가(select 태그 꾸미기)

    #select {
        color : rgb(156, 156, 156);
        border : 1px solid rgb(255, 188, 188);
        padding: 2px 3px;
        border-radius: 4px;
        margin-top: 25px;
        margin-right: 8px;
        font-family: 'Nanum Gothic', sans-serif;
    }

    #select option {
        font-family: 'Nanum Gothic', sans-serif;
        background: rgb(255, 188, 188);
        color: #fff;
        padding: 3px 0;
    }

    참고) header()를 사용하기전 출력이 발생해서는 안되는 이유 (아직은 이해를 못하겠음)

    -header() 함수는 HTTP 헤더를 수정하거나 추가하는 데 사용됩니다. HTTP 헤더는 클라이언트(웹 브라우저)와 서버 간의 요청과 응답에서 메타데이터를 전송하는 데 사용되는 정보입니다.

    예를 들어, header("Location: http://www.example.com"); 코드는 웹 브라우저에게 "http://www.example.com" URL로 리다이렉션하라는 지시를 내리며, 이 지시는 HTTP 헤더를 통해 전달됩니다.

    HTTP 응답은 크게 두 부분으로 구성됩니다: 헤더(header)와 바디(body).

    • 헤더: 응답의 메타데이터(상태 코드, 콘텐츠 유형 등)를 포함합니다.
    • 바디: 실제 컨텐츠(HTML 문서, 이미지 파일 등)을 포함합니다.

    PHP 스크립트에서 echo, print, 혹은 HTML 출력 등을 수행하면 이들은 HTTP 응답의 바디 부분으로 간주되며, 웹 서버가 클라이언트에게 전송할 준비가 되었다고 판단하여 HTTP 헤더들을 보내기 시작합니다. 따라서 한번 출력이 시작되면 (즉, PHP가 어떠한 내용을 출력하기 시작하면), 그 시점 이후에는 HTTP 헤더 정보를 변경할 수 없습니다. 그래서 header() 함수 호출 전에 어떠한 출력도 발생하지 않아야 하는 것입니다.

    세션을 사용하는 것과 직접적인 연관성은 없지만, 세션 ID 같은 정보도 쿠키 형태로 클라이언트에게 보내질 때 HTTP 헤더를 이용하기 때문에 세션을 초기화(session_start()) 할 때도 역시 아무런 출력도 발생하지 않아야 합니다.  

     

    느낀점)

    -session과 form제출후 초기화하는 방법을 배움. 유용한것을 배운것같아 뿌듯.

    -DB가 큰것은 아니지만 테이블을 분리시켜 정규화시켜서 관리하기가 쉬울듯

    -select태그에 대해 공부해보면서 실제로 활용할 수 있게 됨. 

    -검색과 AI를 이용해서 나도 코딩을 할 수 있다는 자신감이 점점 붙기 시작하는 것 같아 좋음.

    -점점 만들어가면서 추가하고싶은 기능들이 많아짐.(무한스크롤, 댓글기능, 로그인 기능등을 구현하고싶음)

Designed by Tistory.