Lumpy Space Princess - Adventure Time

PHP

게시판 검색 결과 PHP

jongyung 2023. 5. 1. 12:33

“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90

설명:

게시판 검색 결과 화면입니다.

 

코드를 나눠서 설명하겠습니다.

PHP

<?php
    include "../connect/connect.php";
    include "../connect/session.php";

    if(isset($_GET['page'])){
        $page = (int) $_GET['page'];
    } else {
        $page = 1;
    }

    $searchKeyword = $_GET['searchKeyword'];
    $searchOption = $_GET['searchOption'];

    $searchKeyword = $connect -> real_escape_string(trim($searchKeyword));
    $searchOption = $connect -> real_escape_string(trim($searchOption));

    $sql = "SELECT b.boardID, b.boardTitle, b.boardContents, m.youName, b.regTime, b.boardView FROM board b JOIN members m ON(b.memberID = m.memberID) ";

    // $sql = "SELECT b.boardID, b.boardTitle, b.boardContents, m.youName, b.regTime, b.boardView FROM board b JOIN members m ON(b.memberID = m.memberID) WHERE b.boardTitle LIKE '%{$searchKeyword}%' ORDER BY boardID DESC";
    // $sql = "SELECT b.boardID, b.boardTitle, b.boardContents, m.youName, b.regTime, b.boardView FROM board b JOIN members m ON(b.memberID = m.memberID) WHERE b.boardContents LIKE '%{$searchKeyword}%' ORDER BY boardID DESC";
    // $sql = "SELECT b.boardID, b.boardTitle, b.boardContents, m.youName, b.regTime, b.boardView FROM board b JOIN members m ON(b.memberID = m.memberID) WHERE m.youName LIKE '%{$searchKeyword}%' ORDER BY boardID DESC";

    switch($searchOption){
        case "title":
            $sql .= "WHERE b.boardTitle LIKE '%{$searchKeyword}%' ORDER BY boardID DESC ";
            break;
        case "content":
            $sql .= "WHERE b.boardContents LIKE '%{$searchKeyword}%' ORDER BY boardID DESC ";
            break;
        case "name";
            $sql .= "WHERE m.youName LIKE '%{$searchKeyword}%' ORDER BY boardID DESC ";
            break;
    }
    $result = $connect -> query($sql);

    $totalCount = $result -> num_rows;
    // echo $totalCount;
?>

해당 코드는 PHP로 작성된 게시판 검색 기능을 구현하는 코드입니다.

먼저 ../connect/connect.php 파일과 ../connect/session.php 파일을 include하여 데이터베이스 연결과 세션을 시작합니다.

검색 키워드와 검색 옵션을 $_GET을 이용하여 전달받습니다. 검색 키워드는 real_escape_string 함수를 이용하여 SQL Injection 공격으로부터 안전하게 처리하고, 검색 옵션은 trim 함수를 이용하여 양쪽 공백을 제거합니다.

$sql 변수에는 게시판의 글 제목, 내용, 작성자 이름, 작성 일시, 조회수 등을 검색하는 SQL 쿼리가 저장됩니다. 이 쿼리는 JOIN 구문을 사용하여 board 테이블과 members 테이블을 연결하고, ORDER BY 구문을 사용하여 boardID 필드를 기준으로 내림차순으로 정렬합니다.

검색 옵션에 따라 WHERE 구문을 추가하여 검색 쿼리를 구성합니다. 

switch 구문을 사용하여 검색 옵션에 따라 검색하는 필드가 달라지도록 합니다. 

검색 키워드는 % 기호를 이용하여 부분 검색할 수 있도록 처리합니다.

마지막으로 검색 결과의 총 개수를 $totalCount 변수에 저장합니다. 이 변수는 페이징 기능을 구현할 때 사용됩니다.

HTML

<body class="gray">
    <?php include "../include/skip.php" ?>
    <!-- skip -->

    <?php include "../include/header.php" ?>
    <!-- header -->

    <main id="main" class="container">

        <div class="intro__inner center">
            <picture class="intro__images small">
                <source srcset="../assets/img/board01.png, ../assets/img/board01@2x.png 2x, ../assets/img/board01@3x.png 3x" />
                <img src="../assets/img/board01.png" alt="소개이미지">
            </picture> 
            <h2>결과 게시판</h2>
            <p class="intro__text">
            웹디자이너, 웹퍼블리셔, 프론트엔드 개발자를 위한 게시판입니다.<br>
            총 <em><?=$totalCount?></em>건의 게시물이 등록되어 있습니다.
            </p>
        </div>
        <!-- intro inner -->

해당 코드는 검색 결과 페이지 상단에 표시되는 검색 결과 요약 정보를 출력하는 HTML 코드입니다.

$totalCount 변수에 저장된 검색 결과의 총 개수를 출력합니다. 이 값을 이용하여 검색된 게시물의 개수를 사용자에게 보여줍니다.

<h2> 태그를 이용하여 "결과 게시판"이라는 제목을 표시하고, <p> 태그를 이용하여 "웹디자이너, 웹퍼블리셔, 프론트엔드 개발자를 위한 게시판입니다. 총 {$totalCount}건의 게시물이 등록되어 있습니다."라는 설명 텍스트를 표시합니다.

또한, <picture> 태그를 사용하여 미디어 쿼리에 따라 다른 이미지를 출력할 수 있도록 합니다. 이 코드에서는 source 태그를 이용하여 고해상도 디스플레이에서는 @2x 또는 @3x 이미지를 사용하도록 지정하였습니다.

PHP

<?php
    $viewNum = 10;
    $viewLImit = ($viewNum * $page) - $viewNum;

    $sql .= "LIMIT {$viewLImit}, {$viewNum}";
    $result = $connect -> query($sql);

    if($result){
        $count = $result -> num_rows;

        if($count > 0){
            for($i=0; $i<$count; $i++){
                $info = $result -> fetch_array(MYSQLI_ASSOC);
                echo "<tr>";
                echo "<td>".$info['boardID']."</td>";
                echo "<td><a href='boardView.php?boardID={$info['boardID']}'>".$info['boardTitle']."</td>";
                echo "<td>".$info['youName']."</td>";
                echo "<td>".date('Y-m-d', $info['regTime'])."</td>";
                echo "<td>".$info['boardView']."</td>";
                echo "</tr>";
            }

        } else {
            echo "<tr><td colspan='5'>게시글이 없습니다.</td></tr>";
        }
    }
?>

해당 코드는 검색 결과 페이지에서 페이징 처리된 게시물 목록을 출력하는 PHP 코드입니다.

$viewNum 변수는 한 페이지에 표시될 게시물의 수를 지정합니다. $page 변수는 현재 페이지를 나타내며, $viewLImit 변수에 $page 값을 이용하여 출력될 게시물의 범위를 지정합니다.

$sql 변수에 LIMIT 절을 추가하여 $viewLImit과 $viewNum 값을 이용하여 페이징 처리된 게시물 목록을 불러옵니다. 

이후, $result 변수에 해당 쿼리 결과를 저장하고, 결과가 존재하는지 확인한 후, $count 변수에 결과의 총 개수를 저장합니다.

for문을 이용하여 $result에서 가져온 검색 결과를 하나씩 순회하며, 각각의 게시물 정보를 <tr> 태그를 이용하여 테이블 형태로 출력합니다. 게시물의 제목은 <a> 태그를 이용하여 클릭 시 상세 내용을 보여주는 boardView.php 페이지로 이동할 수 있도록 링크를 걸어놓습니다.

검색 결과가 존재하지 않을 경우 "게시글이 없습니다."라는 메시지를 출력합니다.

PHP 

<?php
    // 총 페이지 갯수
    $boardTotalCount = ceil($totalCount/$viewNum);
    
    // 1 2 3 4 5 [6] 7 8 9 10
    $pageView = 4;
    $startPage = $page - $pageView; // 2
    $endPage = $page + $pageView; // 10
    
    // 처음/마지막 페이지 초기화
    if($startPage < 1) $startPage = 1;
    if($endPage >= $boardTotalCount) $endPage = $boardTotalCount;

    // 첫 페이지로 가기/ 이전 페이지로 가기
     if($page != 1 && $page < $boardTotalCount){
        echo "<li><a href='boardSearch.php?page=1&searchKeyword={$searchKeyword}&searchOption={$searchOption}'>처음으로</a></li>";
        $prevPage = $page - 1;
        echo "<li><a href='boardSearch.php?page={$prevPage}&searchKeyword={$searchKeyword}&searchOption={$searchOption}'>이전</a></li>";
    }
    
    // 페이지
    for($i=$startPage; $i<=$endPage; $i++){
        $active = "";
        if($i == $page) $active = "active";
        
        echo "<li class='{$active}'><a href='boardSearch.php?page={$i}&searchKeyword={$searchKeyword}&searchOption={$searchOption}'>{$i}</a></li>";
    }
    
    // 마지막 페이지로/ 다음 페이지로
    if($page != $boardTotalCount && $page < $boardTotalCount){
        $nextPage = $page + 1;
        echo "<li><a href='boardSearch.php?page={$nextPage}&searchKeyword={$searchKeyword}&searchOption={$searchOption}'>다음</a></li>";
        echo "<li><a href='boardSearch.php?page={$boardTotalCount}&searchKeyword={$searchKeyword}&searchOption={$searchOption}'>마지막으로</a></li>";
    }
?>

위 코드는 검색 결과 게시판에서 페이지네이션을 구현하는 코드입니다.

먼저, 검색 결과에 따른 게시글의 총 갯수와 페이지당 보여질 게시글 수($viewNum)를 이용하여 총 페이지 갯수($boardTotalCount)를 계산합니다. 

ceil() 함수를 이용해 소수점 이하의 숫자가 있을 경우 올림하여 정수형으로 반환합니다.

그 다음, 현재 페이지($page)를 기준으로 시작 페이지($startPage)와 끝 페이지($endPage)를 계산합니다. 

페이지 번호가 일정한 범위($pageView) 안에서 보이도록 계산하고, 만약 시작 페이지($startPage)가 1보다 작다면 1로, 끝 페이지($endPage)가 총 페이지 갯수($boardTotalCount)보다 크다면 총 페이지 갯수로 설정합니다.

그 후, 페이지 네이션에서 처음 페이지로 가기, 이전 페이지로 가기, 페이지 번호, 다음 페이지로 가기, 마지막 페이지로 가기 등의 기능을 구현합니다. 현재 페이지 번호와 링크되는 페이지는 활성화된 상태로 표시합니다. 이전 페이지로 가기와 다음 페이지로 가기 버튼은 현재 페이지가 첫 페이지($page=1)가 아니고, 마지막 페이지($page=$boardTotalCount)가 아닐 경우에만 활성화됩니다.

마지막으로, 구현한 페이지네이션을 HTML 태그와 함께 출력하여 사용자가 페이지를 이동할 수 있도록 합니다.

여기에 쓰인 속성 및 메서드에 대해서 설명하겠습니다.

$_GET은 PHP에서 제공하는 슈퍼 글로벌 변수 중 하나로, URL에서 전달된 쿼리 문자열을 가져옵니다.

쉽게 말해, 웹 페이지 주소 뒤에 ?와 함께 전달되는 변수들을 배열 형태로 저장하는 역할을 합니다.
이 변수를 사용하여 사용자로부터 입력받은 데이터나 페이지 이동에 필요한 정보를 전달하고, 처리하는 등의 다양한 용도로 활용할 수 있습니다.

예를 들어, URL에 'boardID=3'이라는 쿼리 문자열이 전달되면, $_GET['boardID']를 통해 해당 값을 가져와서 다양한 처리에 사용할 수 있습니다.

real_escape_string 함수는 주어진 문자열에서 MySQL에서 사용하는 메타 문자들을 이스케이프(escape)하여, SQL Injection 공격을 방지할 수 있도록 합니다.
이 함수는 주로 PHP에서 MySQL 데이터베이스에 값을 입력할 때, 입력값을 이스케이프해서 사용합니다.

예를 들어, 사용자가 입력한 문자열 중에 작은따옴표(')가 들어갈 경우, 이스케이프 처리하지 않으면 SQL문이 제대로 동작하지 않거나, 해커가 이를 이용하여 SQL Injection 공격을 할 수 있습니다.
이 때문에, 입력값을 데이터베이스에 저장하기 전에 real_escape_string 함수를 사용하여 이스케이프 처리를 해야합니다.

trim은 문자열의 양쪽 끝에서 공백을 제거하는 PHP 함수입니다.
trim 함수를 사용하면 문자열의 왼쪽과 오른쪽에 있는 공백을 제거할 수 있습니다.

예를 들어, 사용자가 폼에 입력한 문자열을 처리하기 전에 trim 함수를 사용하여 앞뒤의 공백을 제거하면 입력 오류를 방지할 수 있습니다. 함수의 사용법은 다음과 같습니다.
$string = trim($string);​

위와 같이 사용하면 $string 변수의 양쪽에 있는 공백이 제거됩니다. 만약 특정 문자열을 제거하고 싶은 경우, 다음과 같이 사용할 수 있습니다.

$string = trim($string, " \t\n\r\0\x0B");

위 코드에서는 공백, 탭, 개행, 캐리지 리턴, NULL, 수직 탭과 같은 문자열을 제거합니다.

switch 문은 특정 변수의 값에 따라 다양한 분기 처리를 할 때 사용하는 제어문입니다. 
switch 문은 일반적으로 if-else 문으로 대체 가능하지만, 여러 가지 가능한 값들 중 하나만 처리할 경우 switch 문이 코드를 더 간결하고 가독성 높게 만들 수 있습니다.

switch 문의 기본적인 구조는 다음과 같습니다.

switch (variable) {
    case value1:
        // value1에 대한 처리
        break;
    case value2:
        // value2에 대한 처리
        break;
    case value3:
        // value3에 대한 처리
        break;
    default:
        // variable 값이 위의 모든 값과 일치하지 않을 때의 처리
        break;
}

switch 문은 먼저 variable 변수의 값을 확인한 후, 해당 값이 case 문 중 어떤 값과 일치하는지 비교합니다. 
일치하는 case 문이 있으면 해당하는 코드 블록을 실행하고, break 문을 만나면 switch 문을 종료합니다. 
일치하는 case 문이 없으면 default 문을 실행합니다. default 문이 없으면 switch 문은 아무 작업도 수행하지 않고 종료합니다.

switch 문은 case 문에 여러 개의 값을 동시에 지정하거나, default 문을 생략하거나, break 문을 생략하여 다음 case 문으로 넘어가는 fall-through 기능을 사용할 수 있지만, 이러한 경우 코드의 가독성이 저하될 수 있으므로 주의가 필요합니다.

LIMIT은 SQL에서 결과 집합에서 반환되는 행 수를 제한하는 데 사용되는 절입니다.

예를 들어, "SELECT * FROM my_table LIMIT 10"는 my_table 테이블에서 10개의 행만 반환합니다.

LIMIT 절에는 두 개의 매개 변수가 필요합니다. 첫 번째는 반환할 첫 번째 행의 위치를 지정하는 오프셋(offset)이며, 두 번째는 반환할 행 수를 지정하는 리미트(limit)입니다.

오프셋을 생략하면 0으로 간주되며, 따라서 첫 번째 행부터 반환됩니다. 
리미트를 생략하면 결과 집합에 있는 모든 행이 반환됩니다.

LIMIT은 주로 SELECT 쿼리에서 사용되지만 DELETE 및 UPDATE 쿼리에서도 사용될 수 있습니다.