project

[웹게시판] (2) 게시글 목록(index.php)

cheda 2022. 1. 13. 17:29

게시글 목록 페이지

index.php 파일은 웹게시판의 메인화면이 될 목차페이지를 생성한다.

 

 

index.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");
    $query ="select * from board order by number desc";
    $result = $connect->query($query);
    $total = mysqli_num_rows($result);
?>
    <header>
        <div class="site_name">
            <img src=./images/logo.png></div>
            <font style="color: #FFB722;">노랑</font>이 제일 좋아
        </div>
        
<?php
    // 세션검사 -> Login/Logout 버튼 출력
    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">게시판</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
        while($rows = mysqli_fetch_assoc($result)){ //DB에 저장된 데이터 수 (열 기준)
            if($total%2==0) {  ?>
                <tr class = "even">
<?php       }
            else{ ?>
                <tr>
<?php       }

            $title=$rows['title'];
            if(mb_strlen($title, "UTF-8")>28) {
                $title = mb_substr($rows['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 $rows['number']?>">
            <?php echo $title?></td>
            <td width = "100" align = "center"><?php echo $rows['id']?></td>
            <td width = "200" align = "center">
<?php
            $d = substr($rows['date'], 0, 10);
            date_default_timezone_set('Asia/Seoul');
            $today = date("Y-m-d");
            if ($d != $today) {
                echo $d;
            }
            else {
                $before = strtotime(substr($rows['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 $rows['hit']?></td>
            </tr>
<?php
            $total--;
        }
        ?>
        </tbody>
        </table>
 
        <div class = bt id="bt1">
            <font style="cursor:pointer" onClick="location.href='./write.php'">글쓰기</font>
        </div>
    </section>
 
</body>
</html>

 

(1) DB에서 게시판 데이터 가져오기

게시글이 저장된 board_db의 board 테이블에서 데이터를 가져온다.

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

MySQL 질의문
SELECT * FROM board ORDER BY number DESC
  • ORDER BY를 사용하여 number 칼럼을 기준으로 데이터를 내림차순(DESC) 정렬

 

PHP 함수
mysqli_connect()
  • (PHP 5, PHP 7, PHP 8) mysqli_connect: mysqli::__construct()의 별칭
  • mysqli::__construct(): MySQL 서버에 대한 새 연결을 연다.
  • 매개변수: (hostname, username, password, database, port, socket)
query()
  • (PHP 5, PHP 7, PHP 8) 데이터베이스에 대한 쿼리를 수행한다.
  • 매개변수: (mysql, query, result_mode)
    mysql: mysqli_connect() 또는 mysqli_init()에 의해 반환된 mysqli 객체
    query: 쿼리 문자열
    result_mode: MySQL 서버에서 결과가 반환되는 방식. 기본값으로 결과 set과 함께 mysqli_result 객체 반환
mysqli_num_rows()
  • (PHP 5, PHP 7, PHP 8) 매개변수로 전달된 mysqli_result 객체의 행 수를 반환한다.

 

 

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

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

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

 

PHP 함수, 변수, 언어구조
session_start()
  • (PHP 4, PHP 5, PHP 7, PHP 8) GET 또는 POST 요청을 통해 전달되거나 쿠키를 통해 전달된 세션 식별자를 기반으로 새 세션을 생성하거나 현재 세션을 재개한다.
isset()
  • (PHP 4, PHP 5, PHP 7, PHP 8) 인자로 전달된 변수가 선언되었고 null이 아니라면 true를 반환한다.
  • 그렇지 않다면 false를 반환한다.
$_SESSION
  • (PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8) 세션 변수로, 전역변수이다.
  • 현재 스크립트에서 사용할 수 있는 세션 변수를 포함하는 연관 배열로 저장된다.
echo
  • (PHP4, PHP 5, PHP 7, PHP 8) 추가 개행이나 공백 없이 하나 이상의 표현식(expression)을 출력한다.
  • 함수가 아니라 언어구조이다.

 

(3) 검색창

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

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

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

 

(4) 게시글 목록 출력

board 테이블의 각 행은 하나의 게시물에 대한 정보를 저장하고 있다.

따라서 mysqli_fetch_assoc 함수를 통해 각 행을 가져오는 과정을 while문을 통해 반복하면서,

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

  • (1)의 과정에서 mysqli_num_rows() 함수를 통해 board 테이블의 행 개수를 $total에 저장하였다.
    게시글의 번호는 $total을 기준으로 출력한다.
    board_table의 number 칼럼은 고정된 값이다. 따라서 number 칼럼의 값으로 번호를 출력하면 작성된 게시물이 삭제된 경우 번호가 순서대로 출력되지 않는다.
  • 제목이 28글자가 넘는다면, 28번째 이후의 글자는 ...으로 출력한다.
  • 게시글이 작성된 지 하루가 지난 후부터는 작성일에 날짜를 표시한다.
    만약 하루가 지나지 않았다면 작성시각으로부터 지난 시간을 분 단위로 계산한다.
    60분 이하라면 분 단위로 작성일을 표시하고, 60분 이상이라면 시간 단위로 작성일을 표시한다.

 

PHP 함수
mysqli_fetch_assoc()
  • (PHP 5, PHP 7, PHP 8) 연속적인 호출을 통해 매개변수로 전달된 mysqli_result 객체의 각 행을 연관 배열로 가져온다.
  • 호출에 대한 후속호출은 result set의 다음 행을 반환하고, 행이 더 이상 없는 경우 null을 반환한다.
mb_strlen()
  • (PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8) 문자열 길이를 반환한다.
  • 매개변수: (string, encoding)
    string: 길이를 계산할 문자열
    encoding: 문자 인코딩 지정. 생략하거나 null로 설정하면 내부 문자 인코딩 값이 사용된다.
mb_substr()
  • (PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8) 원본 문자열의 일부를 반환한다.
  • 매개변수: (string, start, length, encoding)
    string: 원본 문자열
    start: 부분문자열의 시작위치 지정
    length: 추출할 부분문자열 길이 지정
    encoding: 문자 인코딩 지정. 생략하거나 null로 설정하면 내부 문자 인코딩 값이 사용된다.
substr()
  • (PHP 4, PHP 5, PHP 7, PHP 8) 원본 문자열의 일부를 반환한다.
  • 매개변수: (string, offset, length)
    string: 원본 문자열
    offset: 부분문자열의 시작위치 지정
    length: 추출할 부분문자열 길이 지정
date_default_timezone_set('Asia/Seoul)
  • (PHP 5 >= 5.1.0, PHP 7, PHP 8) 스크립트의 모든 날짜/시간 함수의 기준이 되는 시간대 설정
  • 매개변수: timezoneId
time()
  • (PHP 4, PHP 5, PHP 7, PHP 8) 현재 Unix 타임스탬프 반환
date()
  • (PHP 4, PHP 5, PHP 7, PHP 8) 로컬 시간/날짜 형식을 지정한다.
  • 형식이 지정된 날짜 문자열을 반환한다. timestamp에 숫자가 아닌 값이 사용되면 false를 반환한다.
  • 매개변수: (format, timestamp)
    format
    timestamp: 기본값으로 time()이 사용된다.
  • format
  • Y: 4자리 년도
  • m: 앞에 0이 있는 두 자리 월 (1월은 01, 12월은 12로 표시)
  • d: 앞에 0이 있는 두 자리 날짜
  • H: 앞에 0이 있는 24시간 형식의 시간
  • i: 앞에 0이 있는 분
  • s: 앞에 0이 있는 초
strtotime()
  • (PHP 4, PHP 5, PHP 7, PHP 8) 날짜/시간 문자열을 Unix timestamp로 변환하여 반환
더보기
더보기

mb_strlen(), mb_substr() 함수 사용을 위해서는 mbstring 확장을 로드해주어야 한다.

php 설치 폴더의 php.ini 파일에서 extension=mbstring 문장 앞의 주석(;)을 삭제해주면 된다.

 

(5) 글쓰기 버튼 출력

글쓰기 버튼을 클릭하면 write.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. [집에 가고 싶어요] [php/mysql] 게시판 만들기 (목차)
  2. [S_Writer의 IT NOTE] 게시판 만들기 #12 검색 기능