Programming/PHP

PHP 방명록 기능 소스

zzarungna 2021. 11. 18. 20:59
반응형

PHP 방명록 기능 소스

최근에 우분투 서버에 MariaDB와 아파치 서버를 구성하여 PHP를 설치하였습니다. 이왕 설치한 거 간단히 방명록 기능을 구현해 보았는데 필요할 때 개인적으로 참고할 목적과 필요하신 분들과 정보 공유를 위해 정리해 봤습니다.

 

웹 프로그래밍 방명록 구현을 위해 구성된 서버 버전은 다음과 같습니다.

우분투 - 20.04

MariaDB 버전 - 10.3.31

Apache 서버 버전 - 2.4.41

PHP 버전 - 7.4.3

 

방명록 글쓰기, 방명록 글 수정, 방명록 글 삭제, 방명록 검색, 페이징 기능을 간단히 구현하였으며 예외처리나 기타 보안 사항까지 모두 처리 하지 않았기에 현업에서 사용 시 필요한 구문만 참고 후 추가 수정이 필요합니다.

 

먼저 MariaDB에서 간단히 방명록 저장용 테이블을 하나 생성해 줍니다.

CREATE TABLE board(
	no INT NOT NULL AUTO_INCREMENT,
	name VARCHAR(20),
	email VARCHAR(40),
	pass VARCHAR(30),
	content TEXT,
	date DATETIME,
	PRIMARY KEY(NO)
);

 

당장 필요한 건 아니지만, 나중에 페이징 테스트를 하기 위해 데이터도 임시로 넣을 수 있도록 프로시져를 하나 만들어 줬습니다.

DELIMITER ;;
CREATE PROCEDURE auto_insert(IN count INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    WHILE (i <= count) DO
		  INSERT INTO board (name, email, pass, content, date)VALUES(CONCAT('에스파' ,i) , CONCAT('auto', i, '@mail.com'), '12345', CONCAT('자동 생성 데이타 에요', i), NOW());
        SET i = i + 1;
    END WHILE;
END;;
DELIMITER ;

CALL auto_insert(231);/*데이터 넣기*/

DROP PROCEDURE auto_insert;/*여러 종류 데이터 넣으려면 지우고 내용만 조금 변경*/

 

방명록 첫 페이지

간단히 방명록 첫 페이지를 HTML과 CSS를 활용해 작성했습니다.


 

home.html(메인 페이지)

기능이 따로 있는 페이지가 아니어서 html 페이지로 만들었으며 basic.css 스타일 시트 파일만 가져오는 간단한 HTML 소스입니다.

<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<title>방명록</title>
	<link rel="stylesheet" href="basic.css">
</head>
<body>
  <h1 class="my_title">방 명 록</h1>
  <hr id="title">

  <a href="/board/list.php" class="my_link"><h2 class="my_subtitle">방명록 목록</h2></a>
  <a href="/board/write.html" class="my_link"><h2 class="my_subtitle">방명록 작성</h2></a>
</body>
</html>

 

basic.css(방명록 전체 디자인)

방명록 페이지 전체에서 사용하는 CSS 코드를 한군데에 모두 모았습니다. 기본 HTML 구문과 겹치지 않도록 대부분 클래스 선택자를 활용했습니다.

#title{/*제목 밑줄*/
  width: 38%;
}
.my_title{/*제목 글자 정렬 색*/
  text-align: center;
  color: #4d5756;
}
.my_subtitle{/* 부제목 크기*/
  width: 250px;
}
.my_link{/*링크 밑줄 없애기*/
  text-decoration: none;
}
.btn{/*버튼 크기 조정*/
  width: 200px;
}
.my_subtitle{/*main.html 서브 제목*/
  border-bottom: solid 1.5px lightgrey;
}
.my_ul{/*리스트 페이지 디자인*/
  list-style-type: circle;
}
.my_text{/*링크 글자 조정*/
  font-size: 20px;
  font-weight: bold;
}
.my_div{/*글 목록 리스트 디자인*/
  border: 1px solid #d1d1d1;
  margin-bottom: 10px;
  border-radius: 30px;
}
.my_p{/*P태그 사용하게 되면 가운데 정렬*/
  text-align: center;
}
.my_textarea{/*글 작성 디자인*/
  width: 98.70%;
  border-radius: 7px;
  border: 1px outset #d1d1d1;
}
.my_input{/*input text 디자인*/
  height: 28px;
}
.my_hr{/*메뉴 밑줄 디자인*/
  width: 15%;
  border: 1px solid #lightgrey;
}

 

방명록 글 목록 페이지

방명록 홈에서 방명록 목록을 선택하게 되면 방명록 전체 글 목록을 확인할 수 있는 페이지입니다.


 

list.php(방명록 목록 기능)

include 파일은 basic.css(페이지 디자인), dblink.php(DB 접속),  listpage.php(방명록 상세 페이지), page.php(페이징 처리 및 검색) 파일을 다른 페이지에서도 사용해 파일을 나누어서 만들어 include 구문을 사용해 나눠 놓은 파일을 가져와 소스를 작성했습니다.

<?php
  include "dblink.php";

  $query = "SELECT * FROM board ORDER BY no";
  $result = mysqli_query($conn,$query);

  $rows = mysqli_num_rows($result);//DB 조회 결과 갯수를 result 변수에 넣어줘야 include 페이지 오류 나지 않음.
  if(!$rows) {
    echo "현재 등록되어있는 글이 없습니다.";
    exit;
  }
?>
<title>방명록 목록</title>
<link rel="stylesheet" href="basic.css">
<h1 class="my_title">방명록 목록</h1>
<hr id="title">

<a href="/board/home.html" class="my_link"><span class="my_text">【방명록 홈】</span></a>
<a href="/board/write.html" class="my_link"><span class="my_text">【방명록 작성】</span></a>
<hr class="my_hr" align="left">
<?php
  include "page.php";

  $sql="SELECT * FROM board ORDER BY no DESC LIMIT $skip_record,$page_max";
  $result = mysqli_query($conn,$sql);

  include "listpage.php";
  include "paging.php";

  mysqli_close($conn);
?>

 

dblink.php(데이타베이스 접속)

데이터베이스 접속을 처리하는 파일입니다.

<?php
  $conn=mysqli_connect("localhost","root","12345","homework");
  if(!$conn) {
      die("db 접속 에러 : " . mysqli_error());
  }
?>

 

listpage.php(방명록 개별 목록 기능)

SELECT 쿼리 결과가 같아야 활용할 수 있는데 개인적으로는 검색 이후 나오는 페이지가 방명록 상세 페이지와 다른 부분이 거의 없어 해당 구문만 따로 뺐습니다.

<?php
while($row = mysqli_fetch_array($result)) {
  $no = $row['no'];
  $name = $row['name'];
  $email = $row['email'];
  $content = $row['content'];
  $date = $row['date'];

  echo("
  <div class='my_div'>
  <ul class='my_ul'>
    <li>글번호 : $no</li>
    <li>작성자 : $name</li>
    <li>내용 : $content</li>
    <li>등록일 : $date</li>
    <li><a href='/board/update.php?no=$no'>【수정】</a><a href='/board/delete.php?no=$no'>【삭제】</a></li>
  </ul>
  </div>
  ");
}
?>

 

방명록 페이지, 페이징 계산 및 검색 페이지

방명록 하단에 페이지, 페이징 처리 및 검색 결과에 표시되는 페이지 및 검색 태그를 다른 곳에서도 사용해 따로 파일을 뺐습니다.


 

page.php(페이지 계산 기능)

page를 계산하기 위해 필요한 내용을 따로 파일을 만들어 정리했습니다. 이 페이지를 include 하기 전 SELECT 쿼리의 총 개수를 담는 변수 이름을 $rows 이름의 변수로 담아야 다른 페이지에서 활용할 때 에러가 나지 않으니 참고하시면 좋을 것 같습니다.

<?php
$page_max = 10;//페이지에 표시될 페이징 갯수
$total = $rows;//DB SELECT 전체 행
$page_check = $total/$page_max;
$page_total = (int)($page_check);//전체 페이지 계산
$page_num = isset($_GET['page_num']) == '' ? 1 : $_GET['page_num'];//get 페이지 번호가 없는 경우 페이지 번호를 1로 지정.

$pg_cal = (int)(($page_num-1) / $page_max) * $page_max;//페이징 시작 위치 계산
$pg_start =  $pg_cal+1;//다음 시작 페이지 계산
$pg_end = $pg_start + $page_max;//다음 마지막 페이지 계산
$prev = $pg_start-$page_max; //이전 페이징 시작 위치 계산

if($page_total < $page_check)//기본 페이지 1로 셋팅
    $page_total += 1;

if($page_num == 1)//DB LIMT 갯수 계산
       $skip_record=0;
else
       $skip_record=($page_num-1)*$page_max;
?>

 

paging.php(방명록 다음 페이지, 이전 페이지, 처음, 끝 표시 기능)

하단에 들어갈 페이지 숫자와 같이 이전, 다음, 처음, 마지막 페이지 이동 시 필요한 소스입니다. 어려운 내용이 있는 구문은 아니지만 다른 페이지에서도 반복적으로 사용하기에 따로 파일을 뺐습니다.

 

반복문과 제어문을 활용해 하단 페이지 숫자 및 다음, 이전, 처음, 끝 페이 구분이 가능하며 표시됩니다.

<p class="my_p">
<?php
if($page_num != '1'){//처음 페이지
  echo("<a href='$_SERVER[PHP_SELF]?page_num=1'>[처음]</a> ");
};

if($page_num >= 11)//이전 페이지
  echo("<a href='$_SERVER[PHP_SELF]?page_num=$prev'>[이전]</a> ");

for($page=$pg_start; $page < $pg_end; $page++) {//현재 페이지 링크 표시되지 않도록.
  if($page <= $page_total){
    if($page_num == $page){
  		echo "[$page] ";
  	}else{
      echo "<a href=$_SERVER[PHP_SELF]?page_num=$page>[$page]</a> ";
  	}
  }
}

if($page_num < $page_total)//다음 페이징
  echo("<a href='$_SERVER[PHP_SELF]?page_num=$pg_end'>[다음]</a> ");

if($page_num != $page_total)//끝 마지막 페이지
  echo("<a href='$_SERVER[PHP_SELF]?page_num=$page_total'>[끝]</a> ");
?>
</p>

<form action="/board/search.php" method="post"><!-- 검색 페이지 -->
<p class="my_p">
  <select name="search_list" id="search_list">
      <option value="name">이름</option>
      <option value="content">내용</option>
  </select>
    <input type="text" id="search" name="search">
    <input type="submit" value="검색">
</p>
</form>

 

방명록 글 수정 페이지

방명록 목록에서 글마다 달린 수정 버튼을 눌렀을 때 표시되는 페이지 입니다.


 

update.php(방명록 글 수정 기능)

업데이트 페이지는 SELECT 결과를 보여주는 화면이 아니어서 include 파일은 dblink.php 파일만 가져왔습니다. 한 페이지에서 update 처리와 글수정 정보를 보여주기 위해 POST 전송 여부를 확인했습니다.

<?php
include "dblink.php";

if ($_SERVER['REQUEST_METHOD'] === 'POST'){//post 전송
  $pw = $_POST['check'];
  $no = $_POST['no'];
  $content = $_POST['content'];

  $query = "SELECT no FROM board WHERE no='$no' AND pass = '$pw'";//비밀번호 확인 쿼리
  $result = mysqli_query($conn,$query);
  $row = mysqli_fetch_array($result);

  if($row){//비밀번호 맞을때 UPDATE 실행
    $sql = "UPDATE board SET content = '$content' WHERE no = '$no';";

    mysqli_query($conn, $sql);//UPDATE 실행

    $result = mysqli_affected_rows($conn);//update 몇개 되었는지

    if($result > "0"){
      echo "<script>alert('글이 수정되었습니다.');</script>";
      echo "<script>location.href='/board/list.php';</script>";
    }
  }else{
    echo "<script>alert('비밀번호 입력이 안되었거나 잘못된 비밀번호 입니다.');</script>";
    echo "<script>window.history.back();</script>";
  }

}
?>
<title>방명록 글 수정</title>
<link rel="stylesheet" href="basic.css">
<h1 class="my_title">방명록 글 수정</h1>
<hr id="title">

<a href="/board/list.php" class="my_link"><span class="my_text">【방명록 목록】</span></a>
<a href="/board/write.html" class="my_link"><span class="my_text">【방명록 작성】</span></a>
<hr class="my_hr" align="left">

<?php
if(($_SERVER['REQUEST_METHOD'] === 'GET')){//한페이지에서 수정 기능을 같이 처리하기 위해 글 목록에서 넘어온 경우에만 보여주기.
  $no = $_GET['no'];
  $query = "SELECT * FROM board WHERE no = $no";
  $result = mysqli_query($conn,$query);

  if($row = mysqli_fetch_array($result)) {
    $no = $row['no'];
    $name = $row['name'];
    $email = $row['email'];
    $content = $row['content'];
    $date = $row['date'];

    echo("
    <div class='my_div'>
    <form action='$_SERVER[PHP_SELF]' method='post'>
      <ul class='my_ul'>
        <li>글번호 : $no</li>
        <li>작성자 : $name</li>
        <li>내용<textarea id='content' name='content' rows='10' cols='50' class='my_textarea'>$content</textarea></li>
        <li>등록일 : $date</li>
      </ul>
      <p style='text-align:center;'>
        <input type='password' id='check' name='check' placeholder='비밀번호 확인' style='height: 28px;' >&nbsp;<input type='submit' value='글 수정' >
      </p>
      <input type='hidden' id='no' name='no' value='$no'>
    </form>
    </div>
    ");
  }
}

mysqli_close($conn);
?>

 

방명록 글 작성 페이지

방명록 작성 링크를 선택했을 때 표시되는 페이지입니다. 기능이 들어가지 않은 단순 페이지라 html로 만들었으며 방명록 등록 버튼은 submit 전송으로 add.php에서 처리됩니다. html 파일에서 PHP 파일로 이동해 처리되는 방식도 참고하시면 좋을 것 같습니다.


 

write.html(방명록 글 작성 기능)

글 작성 페이지에서만 JavaScript를 활용해 데이터 입력을 했는지 체크하였으며 서버 측 기능이 없어 html 페이지로 작성하였습니다.

<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<title>방명록 글 작성</title>
	<link rel="stylesheet" href="basic.css">
	<script>
	function check(){
		if(document.getElementById("text").value.length == 0) {//text area 체크
			alert("글을 작성해 주세요.");
			document.getElementById("text").focus();
			return false;
		}

		if(document.getElementById("name").value.length == 0) {//이름 체크
			alert("이름을 작성해 주세요.");
			document.getElementById("name").focus();
			return false;
		}

		if(document.getElementById("email").value.length == 0) {//이메일 체크
			alert("이메일을 작성해 주세요.");
			document.getElementById("email").focus();
			return false;
		}

		if(document.getElementById("pw").value.length == 0) {//비밀번호 체크
			alert("비밀번호를 작성해 주세요.");
			document.getElementById("pw").focus();
			return false;
		}
	}
	</script>
</head>
<body>
	<h1 class="my_title">방명록 글 작성</h1>
	<hr id="title">

	<a href="/board/home.html" class="my_link"><span class="my_text">【방명록 홈】</span></a>
	<a href="/board/list.php" class="my_link"><span class="my_text">【방명록 목록】</span></a>
	<hr class="my_hr" align="left">

	<form action="/board/add.php" method="post" onsubmit="return check()">
	  <textarea placeholder="댓글을 작성해 주세요." id="text" name="text" rows="7" cols="50" class="my_textarea"></textarea>
		<br>
		<p class="my_p">
		  <input type="text" id="name" name="name" class="my_input" placeholder="이름 입력" >
			<input type="text" id="email" name="email" class="my_input" placeholder="이메일 입력" >
		  <input type="password" id="pw" name="pw" class="my_input" placeholder="비번 입력" >
		  <input type="submit" id="btn" value="방명록 등록">
		</p>
	</form>
</body>
</html>

 

 


 

add.php(글 등록 기능)

update.php와 다르게 다른 페이지에서 쿼리를 처리하니 확실히 소스가 간결해져서 보기 좋은 것 같습니다. 간단히 db 연결 파일만 가져와 INSERT 쿼리를 날리는 코드입니다.

<?php
  include "dblink.php";

  if ($_SERVER['REQUEST_METHOD'] === 'POST'){
    $name = $_POST['name'];
    $email = $_POST['email'];
    $pass = $_POST['pw'];
    $content = $_POST['text'];

    $sql = "INSERT INTO board (name, email, pass, content, date) VALUES('$name', '$email', '$pass', '$content', NOW())";

    $result = mysqli_query($conn, $sql);
  }

  if($result=="1"){
    echo "<script>alert('글이 등록되었습니다.');</script>";
    echo "<script>location.href='/board/list.php';</script>";
  }

  echo($result);
  mysqli_close($conn);
?>

 

방명록 글 삭제 페이지

방명록 목록 중 삭제를 선택하면 볼 수 있는 페이지입니다. 글 삭제 버튼을 누르게 되면 delete.php 파일로 입력한 비밀번호와 함께 페이지가 전환 됩니다.


 

delete.php(방명록 글 삭제 기능)

한 페이지에서 보여주고 삭제까지 처리되어 POST 전송 여부를 확인하였으며 비밀번호 확인 후 삭제 쿼리를 보내게 됩니다. mysqli_affected_rows를 활용해 delete가 정상적으로 되었는지 확인했습니다.

<?php
include "dblink.php";

if ($_SERVER['REQUEST_METHOD'] === 'POST') {//삭제 버튼 눌렀을 때.
  $pw = $_POST['check'];
  $no = $_POST['no'];

  $query = "SELECT no FROM board WHERE no='$no' AND pass = '$pw'";//글 삭제 비밀번호 확인
  $result = mysqli_query($conn,$query);
  $row = mysqli_fetch_array($result);

  if($row){//비밀번호 맞을때 DELETE 쿼리 실행
    $sql = "DELETE FROM board WHERE no = '$no' AND pass = '$pw'";

    mysqli_query($conn, $sql);//DELETE 실행

    $result = mysqli_affected_rows($conn);//delete 몇개 삭제 되었는지

    if($result > 0){//1개 이상 변화 있었으면 글 삭제 OK.
      echo "<script>alert('글이 삭제되었습니다.');</script>";
      echo "<script>location.href='/board/list.php';</script>";
    }
  }else{
    echo "<script>alert('비밀번호 입력이 안되었거나 잘못된 비밀번호 입니다.');</script>";
    echo "<script>window.history.back();</script>";
  }
}else{//글 목록에서 넘어왔을때
  $no = $_GET['no'];
}
?>
<title>방명록 글 삭제</title>
<link rel="stylesheet" href="basic.css">
<h1 class="my_title">방명록 글 삭제</h1>
<hr id="title">

<a href="/board/list.php" class="my_link"><span class="my_text">【방명록 목록】</span></a>
<a href="/board/write.html" class="my_link"><span class="my_text">【방명록 작성】</span></a>
<hr class="my_hr" align="left">
<?php
$no = $_GET['no'];
$query = "SELECT * FROM board WHERE no = $no";
$result = mysqli_query($conn,$query);

if($row = mysqli_fetch_array($result)) {
  $no = $row['no'];
  $name = $row['name'];
  $email = $row['email'];
  $content = $row['content'];
  $date = $row['date'];

  echo("
  <div class='my_div'>
  <form action='$_SERVER[PHP_SELF]' method='post' onsubmit='alert('ddd')'>
    <ul class='my_ul'>
      <li>글번호 : $no</li>
      <li>작성자 : $name</li>
      <li>내용$content</li>
      <li>등록일 : $date</li>
    </ul>
    <p style='text-align:center;'>
      <input type='password' id='check' name='check' placeholder='비밀번호 확인' style='height: 28px;' >&nbsp;<input type='submit' value='글 삭제' >
      <input type='hidden' id='no' name='no' value='$no'>
    </p>
    <input type='hidden' id='no' name='no' value='$no'>
  </form>
  </div>
  ");
}
  mysqli_close($conn);
?>

 

방명록 검색 결과 페이지

방명록 목록 하단에 페이지 번호 밑에 있는 이름이나 내용으로 검색했을 때 나오게 되는 페이지이며 검색 결과가 많게 되면 페이징 처리도 됩니다.


 

search.php(방명록 검색 기능)

내용, 이름 검색을 확인 후 쿼리문을 보내기 위해서 분기문이 조금 있습니다. 검색 결과가 많을 경우 페이징 처리를 하기 위해 검색 데이터는 세션에 저장하여 유지하였습니다. 방명록 목록 기능과 보여주는 화면이 같아 page.php, listpage.php, paging.php를 그대로 가져와 사용했습니다.

<?php
/**
s_type - 이름, 내용 검색인지 구분하기 위해
search - 검색어
search_type - 검색 타입에 따라 쿼리문 글자 변경용 변수
**/
include "dblink.php";
session_start();//검색 데이타 유지하기 위해서 사용

  $s_type = "";
  $search = "";
  $search_type = "";

  if($_SERVER['REQUEST_METHOD'] === 'POST'){//검색 결과 필요한 데이터 유지를 위해 세션에 데이터 저장
    $s_type = $_POST['search_list'];
    $search = $_POST['search'];

    $_SESSION["s_type"]= $s_type;//검색된 결과에서 페이지 전환시 데이터 유지하기 위해 사용
    $_SESSION["search"]= $search;//검색된 결과에서 페이지 전환시 데이터 유지하기 위해 사용
  }else{//검색된 결과 이후 페이징 될때마다 검색 데이터 유지
    $s_type = $_SESSION["s_type"];
    $search = $_SESSION["search"];
  }

  if($s_type=="name"){//검색 선택에 따라 쿼리문 다르게 조회
    $search_type = "name";
  }else if($s_type=="content"){
    $search_type = "content";
  }

  $query = "SELECT * FROM board WHERE $search_type LIKE '%$search%'  ORDER BY NO;";

  $result = mysqli_query($conn,$query);
  include "error.php";

  $rows = mysqli_num_rows($result);//DB 조회 결과 갯수를 result 변수에 넣어줘야 include 페이지 오류 나지 않음.

  if(!$rows) {
          echo "검색 결과가 없습니다.";
          exit;
  }
?>
<title>방명록 검색 결과</title>
<link rel="stylesheet" href="basic.css">
<h1 class="my_title">방명록 검색 결과 목록</h1>
<hr id="title">

<a href="/board/list.php" class="my_link"><span class="my_text">【방명록 목록】</span></a>
<a href="/board/write.html" class="my_link"><span class="my_text">【방명록 작성】</span></a>
<hr class="my_hr" align="left">
<?php
  include "page.php";

  $sql="SELECT * FROM board WHERE $search_type LIKE '%$search%' ORDER BY no DESC LIMIT $skip_record,$page_max ";
  $result = mysqli_query($conn,$sql);

  include "listpage.php";
  include "paging.php";

  mysqli_close($conn);
?>

 

마지막으로 코드 작성 시 사용했던 툴은 Atom을 사용하였으며 폴더 구조는 아래 이미지와 같습니다.


 

PHP 언어를 활용해 방명록 기능이나 게시판 기능은 인터넷에 많이 있지만, 개인적으로 보기 깔끔하지 않아 정리해 봤습니다.


현업에서 사용하려면 많은 부분을 손봐야 하겠지만 교육용이나 연습용으로 필요하신 분들이 있을 수도 있다는 생각에 해당 파일을 압축해서 파일도 올려 놓을 테니 소스가 필요하신 분들은 참고하시면 좋을 것 같습니다.

 

파일을 받아 사용하시려면 board 폴더를 하나 만드시고 DB 연결 정보를 변경하시면 될 것 같습니다.

php_board.zip
0.01MB

반응형