project

[웹게시판] (4) 게시글 검색(search.php)

cheda 2022. 1. 17. 17:38

게시글 검색결과 페이지

search.php 파일은 index.php의 검색창에서 검색어를 입력받고, 검색어가 포함된 게시글들을 찾아서 출력하는 페이지를 생성한다.

홈화면에서 제목 카테고리로 'test' 검색
제목 카테고리에서 'test'를 검색한 결과

 

 

검색결과 목록페이지에서 작성자 카테고리로 'abc' 검색

 

작성자 카테고리로 'abc'를 검색한 결과

 

search.php

<!DOCTYPE html>
 
<html>
<head>
        <meta charset = 'utf-8'>
</head>
<style>
    <!-- 생략: 아래의 css -->
</style>

<body>
<?php
    $connect = mysqli_connect('localhost', 'board_user', 'password', 'board_db') or die ("connect fail");
    $category = $_POST['cate'];
    $search_con = $_POST['search'];
?>

<header>
        <div class="site_name">
            <img src=./images/logo.png></div>
            <font style="color: #FFB722;">노랑</font>이 제일 좋아
        </div>
        
<?php
    // ##FIXME## 
    session_start();
 
    if(isset($_SESSION['userid'])) {
?>
        <div class = account_display>
<?php
            echo $_SESSION['userid'];?>님 &nbsp;
            <font style="cursor:pointer" onClick="location.href='./logout.php'" class = bt>Logout</font>
        </div>
<?php
    }
    else {
?>
        <div class = account_display>
            <div class = bt>
                <font style="cursor:pointer" onClick="location.href='./login.php'">Login</font>
            </div>
        </div>
<?php   }
?>
    </header>

    <!--SEARCH-->
    <div id="search_box">    
        <form method="post", action="search.php">
            <button id="search_button">  </button>
            <select name="cate">
                <option value="title">제목</option>
                <option value="id">작성자</option>
                <option value="content">내용</option>
            </select>
            <input class="input_box" type="text" name="search" required="required"/>
        </form>
    </div>
    <!--SEARCH END-->

    <section>
        <div id="menu_title">게시판 >
            <font size="5">'<?php echo $search_con; ?>'검색결과</font>
        </div>

        <table table-layout:fixed; word-break:break-all;>
        <thead align = "center">
        <tr>
            <td width = "50" align="center"></td>
            <td width = "500" align = "center">제목</td>
            <td width = "100" align = "center">작성자</td>
            <td width = "200" align = "center">작성일</td>
            <td width = "50" align = "center">조회</td>
        </tr>
        </thead>

        <tbody>
<?php
            $query = "select * from board where $category like '%$search_con%' order by number desc";
            // 특정 문자 포함 데이터 검색: select [필드명] from [테이블명] where [필드명] like '%특정 문자열%'
            // 테이블 조회 정렬: order by [컬럼1] desc: 내림차순 정렬

            $result = $connect->query($query);
            $total = mysqli_num_rows($result);

            while ( $row= $result->fetch_array() ) {
                if($total%2==0) { ?>
                    <tr class = "even">
<?php           }
                else{ ?>
                    <tr>
<?php           } 

                $title=$row['title'];
                if(mb_strlen($title, "UTF-8")>28) {
                    $title = mb_substr($row['title'], 0, 28, "UTF-8")."...";
                } ?>

            <td width = "50" align = "center"><?php echo $total?></td>
            <td width = "500" align = "center">
                <a href = "./view.php?number=<?php echo $row['number']?>">
                <span style="background:#FFF3DD;"><?php echo $title?></td></span>
            <td width = "100" align = "center"><?php echo $row['id']?></td>
            <td width = "200" align = "center">
            <?php
            $d = substr($row['date'], 0, 10);
            date_default_timezone_set('Asia/Seoul');
            $today = date("Y-m-d");
            if ($d != $today) {
                echo $d;
            }
            else {
                $before = strtotime(substr($row['date'], 11, ));
                $now = strtotime(date('H:i:s', time()));
                $min = (int)(($now - $before)/60);
                if ($min < 60) {
                    echo $min.'분 전';
                }
                else {
                    $hour = (int)($min/60);
                    echo $hour.'시간 전';
                }
            } ?>
            </td>
            <td width = "50" align = "center"><?php echo $row['hit']?></td>
            </tr>
<?php
            $total--;
        }
        ?>
        </tbody>
        </table>

        <div class = bt id="bt1">
            <font style="cursor:pointer" onClick="location.href='./index.php'">홈으로</font>
        </div>
    </section>
 
</body>
</html>

 

(1) DB에 연결하기

게시글이 저장된 board_db에 board_user 사용자로 연결한다.

카테고리 변수와 검색어를 각각 변수 $category와 $search_con에 저장한다.

최신글이 먼저 출력되도록 number 칼럼을 기준으로 내림차순한다(최신 글일수록 number 칼럼에 저장된 값이 크다).

PHP 함수, 변수
mysqli_connect()
  • (생략: index.php에서 설명)
$_POST[]
  • (PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8) HTTP POST 메소드를 통해 현재 스크립트에 전달된 변수의 연관 배열

 

(2) 웹서비스 이름 / 계정정보 출력

session을 검사해서 로그인 상태를 확인하고, 로그아웃된 상태라면 로그인 버튼을 출력한다.

로그인된 상태라면 사용자의 아이디와 로그아웃 버튼을 출력한다.

PHP 함수, 변수, 언어구조
session_start() / isset() / $_SESSION / echo
  • (생략: index.php에서 설명)

 

(3) 검색창

form 태그를 이용해 검색내용을 POST 메소드로 search.php 에 전달한다.

select 태그를 이용해 제목/작성자/내용 option을 선택한 후, 검색어를 입력할 수 있다.

검색어 입력 후 버튼을 클릭하면 search.php가 실행된다.

 

(4) 해당 카테고리에서 검색어가 포함된 게시글 가져오기

MySQL 쿼리를 통해 검색어가 포함된 게시물 데이터들을 $result에 저장하고,

검색된 게시물 게수를 $total에 저장한다.

MySQL 질의문
SELECT * FROM board WHERE $category LIKE '%$search_con%' ORDER BY number DESC
  • LIKE는 특정 패턴과 매칭되는지 검사하는 연산자이다. WHERE 조건절을 사용해 카테고리(제목/작성자/내용)의 데이터 내에 검색어와 일치하는 단어(문장)가 있는 열들을 가져온다.
  • ORDER BY를 사용하여 number 칼럼을 기준으로 데이터를 내림차순(DESC) 정렬

 

PHP 함수
query() / mysqli_num_rows()
  • (생략: index.php에서 설명)

 

(5) 목록 출력

mysqli_fetch_array 함수를 통해 $result에 저장된 데이터를 행 단위로 가져오는 과정을 while문을 통해 반복하면서,

매 반복마다 검색된 게시글의 번호, 제목, 작성자, 작성일, 조회수를 출력한다.

게시물 제목을 클릭할 경우, 게시글 내용을 보여주는 view.php 페이지로 이동하도록 링크를 설정한다. 이 때 GET방식으로 게시글 번호를 인자로 넘겨준다.

  • (4)의 과정에서 mysqli_num_rows() 함수를 통해 검색된 게시물의 개수를 $total에 저장하였다.
    게시글의 번호는 $total을 기준으로 출력한다.
  • 제목이 28글자가 넘는다면, 28번째 이후의 글자는 ...으로 출력한다.
  • 게시글이 작성된 지 하루가 지난 후부터는 작성일에 날짜를 표시한다.
    만약 하루가 지나지 않았다면 작성시각으로부터 지난 시간을 분 단위로 계산한다.
    60분 이하라면 분 단위로 작성일을 표시하고, 60분 이상이라면 시간 단위로 작성일을 표시한다.

 

PHP 함수
mysqli_fetch_array()
  • (PHP 5, PHP 7, PHP 8) 연속적인 호출을 통해 매개변수로 전달된 mysqli_result 객체의 각 행을 연관 배열, 숫자 배열 또는 둘 다로 가져온다.
  • 호출에 대한 후속호출은 result set의 다음 행을 반환하고, 행이 더 이상 없는 경우 null을 반환한다.
  • 결과 배열의 숫자 인덱스에 데이터를 저장하는 것 외에, 결과 집합의 필드 이름을 키로 사용해 연관 인덱스에 데이터를 저장할 수도 있다.
mb_strlen() / mb_substr() / substr() / date_default_timezone_set('Asia/Seoul)  / time() / date() / strtotime()
  • (생략: index.php에서 설명)

 

(6) 홈 버튼 출력

'홈으로' 버튼을 클릭하면 index.php 페이지로 연결한다.

 

 


CSS

    header {
        width: 1000px;
        height: 45px;
        margin-left: 20%;
        background-color: #FFF3DD;
        padding: 15px 0;
        text-align: center;
        font-size: 1.5em;
        font-weight: bold;
        margin-bottom: 10px;
    }
    .site_name {
        display: inline;
        vertical-align: middle;
        margin-left: 10%;
    }
    .account_display {
        display: inline;
        font-size: 16px;
        font-weight: normal;
        margin-right: 10px;
        vertical-align: top;
        float: right;
    }

    #search_box {
        width: 1000px;
        margin-left: 20%;
        background-color: #FFFFFF;
        padding: 15px 0;
        text-align: center;
        font-size: 1.5em;
        font-weight: bold;
        margin-bottom: 10px;
    }
    select {
        width: 60px;
        height: 27.5px;
        margin-right: 3px;
        border: 3px solid #FFB722;
        border-left: 0px;
        font-family: inherit;
        background: url('./images/arrow.png') no-repeat 110% 50%;
        -webkit-appearance: none;
        -moz-appearance: none;
        appearance: none;
        display: inline-block;
        float: right;
    }
    select::-ms-expand {
        display: none;
    }
    .input_box {
        border: 3px solid #FFB722;
        border-right: 0px;
        width: 200px;
        height: 20px;
        display: inline-block;
        float: right;
    }
    #search_button {
        width: 30px;
        height: 30px;
        border: 0px solid #BFBFBFBF;
        background: url('./images/search.png') no-repeat 50% 50%;
        color: #FFB722;
        font-size: 1.1em;
        vertical-align: middle;
        display: inline-block;
        float: right;
    }

    section {
        width: 1000px;
        height: 500px;
        margin-left: 20%
    }
    #menu_title {
        display: block;
        width: 900px;
        text-align: left;
        font-size: 1.5em;
        margin-top: 0.83em;
        margin-bottom: 0.83em;
    }
    table{
        border-top: 1px solid #444444;
        border-collapse: collapse;
        overflow: auto;
    }
    tr{
        border-bottom: 1px solid #444444;
        padding: 10px;
    }
    td{
        border-bottom: 1px solid #efefef;
        padding: 10px;
    }
    table .even{
        background: #efefef;
    }
    a:link {color : #000000; text-decoration:none;}
    a:hover {color : #FFB722; text-decoration : underline;}

    
    .bt{
        width: 70px;
        height: 25px;
        text-align:center;
        color:#000000;
    }
    .bt:hover{
        text-decoration: underline;
    }
    #bt1 {
        margin-top: 20px;
        border: 1px solid #BFBFBFBF;
        float: right;
    }
    
    img {
        object-fit: contain;
        vertical-align: middle;
    }

 

CSS 설명:

2022.01.13 - [project] - [웹게시판] CSS 태그/스타일

 


[ 참고한 블로그 ]

  1. [S_Writer의 IT NOTE] 게시판 만들기 #12 검색 기능