강좌
클라우드/리눅스에 관한 강좌입니다.
프로그램 분류

미. 답신 글 달기 -1 담신 글의 원리

작성자 정보

  • 웹관리자 작성
  • 작성일

컨텐츠 정보

본문

[강좌] php+mysql 게시판 만들기 #미-1

안녕하세요. 디망쉬입니다.

제 강좌의 보충편이 나우누리 isf 에 올라와있습니다.
:] 비교적 빨리 빨리 진행한 덕에 허술하게 넘어갔던 부분을 나우누리 id, 푸른잎새(김선준)님께서 써주셔서
감사할 따름이랍니다. 내용도 좋구요. 제 강좌를 보시는 들은 한 번쯤 참조하세요. :]

다만 한 가지 말씀드리자면

[보충] php+mysql 게시판 만들기 #는-잎

에서 나오는 후자의 방식(두번째 방식)과 전자의 방식 (첫번째 방식)의 차이점을 아실 필요가 있습니다. :]

<?
$test = "dimanche";
echo "
어서오세요-$dimanche";
?>

어서오세요-<? echo "$dimanche"; ?>

는 출력상 차이가 없습니다. 하지만 후자의 방식은 좀 더 느린 방식입니다.
왜냐하면 웹 서버가 해당 페이지 파일을 읽어와 클라이언트(유저)에게 보내줄 때
<? 나 <?php 같은 코드가 보이면 php 모듈에 커넥트(접속)하여 해석합니다.

즉 <? 과 ?> 가 많으면 그만큼 반응이 느려지죠.

이건 http://coco.st 에 접속해보시면 아실 겁니다.
잘 보시면 부분적으로 출력되는게 보이죠. 이게 부분적으로 출력 부분을 잘라낸 것인데 이런 각 부분들마다 <? 로 해놨기 떄문에 느리죠. 그래서 속도가 중요할 경우 <? 를 한 번 열은 걸로 일을 완료하는 것이 가장
좋습니다.
하지만 관리 상으로는 <? 과 ?> 을 필요한 부분마다 따로 해주는게 좋겠죠. :]

--------------------------------
전 편의 마지막 회의 질문 답에서 좀 더 최적화시킬 방법을 찾아봤습니다. 그걸 여기서 알아보죠. :]

일단 error_no 는 필요없습니다. 아주 간단합니다.
게시물 읽기나 수정, 삭제는 반드시 해당 글의 no 를 넘겨받아야 합니다. 그리고 이걸 토대로 select 쿼리를
날려서 결과값을 받은 뒤 이걸 뿌리고 사용하고 하죠.

이게 바로 힌트! 쿼리를 날려주고 나온 값을 mysql_fetch_array 로 배열화하죠? 사용하려고.
그렇게 나온 배열 변수들을 체크합니다. 가급적이면 반드시 입력되어 있을 만한 항목을요. 예를 들면
게시물 작성자는 항상 들어갑니다. 혹은 입력 시간도요.
그런데 어떻게 잔머리를 굴리거나 버그로 인해 게시물 작성자명은 입력 안될 수 있지만 게시물
입력 시간은 내부적에서 자동으로 time() 의 값이 들어가니 항상 들어가겠죠? 그래서 이걸 이용해보죠.

만약 mysql_fetch_array 함수로 얻어진 배열 변수명이 $view 라고 하죠.
(이건 글 읽기, 수정, 삭제에서 사용되기도 하죠) 그렇다면

if ($view[filluptime] == "") {

이라고 하면 됩니다. 즉 게시물 입력 시간이 없다는건 곧 해당 글이 존재하지 않는다는거죠.
그렇죠?

if ($view[filluptime] == "") {
echo "
<script language="javascript">
alert("게시물 번호가 선택되지 않았습니다.");
history.back();
</script>
exit;
";
else {
주절 주절
}

하면 될 것입니다. 물론 이건 적용하실지 안하실지는 여러분의 과제입니다.
다만 여러분은 이런 식으로 보다 많은 잔머리(^^;)를 활용하셔서 최대한 최적화하고 빠르게 돌아갈 수 있게 해야 속이 편하다는거죠. ^^;
--------------------------------

에구. 이번 회는 시작이 잡담보다 어째 교육적(?)인 내용이 많군요.

* Red Alert!!! *
제 강좌 '는-1' 편에서 오타가 있습니다.
빼먹은 것두 있습니다. -_-; 급히 쓴 티가 역력하군요.
초보분들 피말릴 수도 있을 일들이기에 7월 13일
이전에 받으신 분은 반드시 새로 받으세요. --;;
죄송. 흑



미. 답신 글 달기

a. 답신 글의 원리


굉장히 귀찮은 부분의 구현이 나왔습니다. 구현은 쉽지만 왜 그래야하는지 설명하고 이해하는게
여지껏 우리가 공부한 '디, 망, 쉬, 는' 편들과는 비교를 거부합니다. --;

답신글 원리에 대해서는 '망-2'편에서 게시판 DB 디자인할 때 아주 잠깐 언급했습니다.
이 편에서 우리는 출력 순서 인덱스를 (idx int(5) DEFAULT '0' NOT NULL,) 사용하기로 했습니다.
그런 의미에서 우리가 사용할 게시판 테이블의 DB 구조를 볼까요?

CREATE TABLE testboard (
no int(5) DEFAULT '0' NOT NULL auto_increment,
num int(5) DEFAULT '0' NOT NULL,
idx int(5) DEFAULT '0' NOT NULL,
usrtitle tinytext,
contents text,
replyon int(1) DEFAULT '0' NOT NULL,
replyto int(5) DEFAULT '0' NOT NULL,
replyfrom int(5) DEFAULT '0' NOT NULL,
replydepth int(5) DEFAULT '0' NOT NULL,
hit int(5) DEFAULT '0' NOT NULL,
filepath varchar(100), # 추가
filename varchar(100), # 추가
filesize int(4), # 추가
usrname varchar(12),
usrpasswd char(28),
usremail varchar(80),
usrhomepage varchar(80),
filluptime int(11) DEFAULT '0' NOT NULL,
PRIMARY KEY (no)
)

에헤. 오랜만에 봐서 그런지 반갑군요. ^^;
이제 위 부분에서 replyon, replyto, replyfrom, replydepth 에 대해서 설명할 차례군요.

1. replyon attribute
해당 글이 답신글을 갖고 있는지를 판별하는 것입니다.
만약 2번 글이 답신글을 갖고 있다면 2번글의 replyon 은 1이 되고, 답신 글이 없을 경우 0이 될 것입니다.

2. replyto, replyfrom attribute
이 둘은 어떤 글에 대한 답신 글인지를 의미합니다.
하지만 차이가 있습니다.

- replyto
해당 답신글들이 맨 처음 시작된 글

- replyfrom
어떤 글에 대한 답신 글인지 지정

잘 모르시겠다구요? 직접 게시판 예제를 보도록 하죠.

no : 제목
----+-----------------------
3 : 커헉. 진짜다!
2 : 와우. 1번을 드시다니!
1 : 안녕하세요!
- : re: 어서오세요.
- : re: re: 감사합니다.
- : re: 반가워요.

이게 게시판의 모습이구요. 게시물 번호가 - 인 것들은 관련글들이죠. 1번글에 대한 답신 글들.
이것들을 DB 에서 본다면

no : num : idx : 제목
----+-----+-----------------
6 : 3 : 6 : 커헉. 진짜다!
5 : 2 : 5 : 와우. 1번을 드시다니!
1 : 1 : 4 : 안녕하세요!
3 : 0 : 3 : re: 어서오세요.
4 : 0 : 2 : re: re: 감사합니다.
2 : 0 : 1 : re: 반가워요.

위와 같이 됩니다. 이건 이미 '망-2'에서 다뤘었죠? 그럼 여기서 replyto, replyfrom 값들을 알아보죠. 어떠할까요.

no : num : idx : replyfrom : replyto : 제목
----+-----+---------------+-----------+----------
6 : 3 : 6 : 0 : 0 : 커헉. 진짜다!
5 : 2 : 5 : 0 : 0 : 와우. 1번을 드시다니!
1 : 1 : 4 : 0 : 0 : 안녕하세요!
3 : 0 : 3 : 1 : 1 : re: 어서오세요.
4 : 0 : 2 : 3 : 1 : re: re: 감사합니다.
2 : 0 : 1 : 1 : 1 : re: 반가워요.

처럼 됩니다. 자. 're: 어서오세요.' 라는 글부터 보죠. 이 글은 1번글인 '안녕하세요!'
라는 글에 대한 답신 글입니다. 're: 어서오세요.'
라는 글의 답신 시작글은(replyto) 1번 글이고, 연결된 글은(replyfrom) 1번 글입니다.
그래서 replyfrom 와 replyto 모두 1 이죠.

그렇다면 're: re: 감사합니다.' 글을 보죠.
이 글은 1번 글에 답신을 달은 're: 어서오세요.'
글에 대한 답신입니다. 일단 이 글은 're: 어서오세요.'에 대한 답신글 이므로 replyfrom 는 're: 어서오세요.' 글의 no 가 저장되어 3이 됩니다.
그리고 이 답신 글들의 시작은 1번 글이므로 replyto 은 1이 되죠.
무슨 말인고 하면 're: re: 감사합니다.' 글은 're: 어서오세요.' 의 답신 글이고,
're: 어서오세요.' 글은 1번 글의 답신 글 입니다. 즉 답신 글의 시작은 1번 글이죠.
그래서 replyto 을 해준 겁니다.

replyto 이 왜 필요할까요? 사용자 편의를 위함이죠 뭐. 관련 글들 끼리 묶어낼 수가 있거든요. :]

SELECT * from testboard
WHERE no=1 OR replyto=1

이라고 하면 no 가 1, 3, 4, 2번 글들이 주룩 나옵니다. 즉 1 번 글과 관련 글들이 나오는거죠.


3. replydepth
이건 답신 글의 깊이입니다. 그러니까 답신 글들이 시작 글(답신 시작)로부터 몇 번째 답신 글이냐는 거죠.

1 : 1 : 4 : 0 : 0 : 안녕하세요!
3 : 0 : 3 : 1 : 1 : re: 어서오세요.
4 : 0 : 2 : 3 : 1 : re: re: 감사합니다.
2 : 0 : 1 : 1 : 1 : re: 반가워요.

에서 're: 어서오세요.' 는 1번 글의 답신글인데 첫 글이죠? 그래서 replydepth 는 1이 됩니다.
하지만 're: re: 감사합니다.' 는 're: 어서오세요.' 를 거친 답신 글입니다. 즉 '안녕하세요!' 글의
입장에서는 두 번째죠. (물론 're: 어서오세요.' 글의 입장에서는 첫 번째지만) 그래서 replydepth는
2가 됩니다.

이것의 필요성요? 저는 사용자 편의성이라 봅니다. :]
(제가 짠 게시판에서 replydepth 는 단지 한 번만 사용됩니다. 한가지 용도로만. 그래도 문제없이
잘 되구요) 예를 들면 몇 번째 답변 글이라던가 글 검색이라던가. 냥냥. ^^; (사용하기 나름이군요)


자아~ 그럼 이번엔 답신 글을 쓰면 DB 내부적으로는 어떤 일이 일어나나 보겠습니다. 이걸 처음에 잘
예상하고 기획해야만 게시판을 '삽질'하지 않고 단번에 짤 수 있죠.
(흑 저는 답신 글 구현에서 한 4번 소스 뒤집은 기억이)

일단 순서도를 보죠.


1. 해당 글을 포함해 뒤의 글들(idx 를 기준으로) idx 값을 1씩 증가

2. 해당 글의 replyon 을 1로 고침

3. 답신 글 내용을 입력시킴. 이때 no 는 num 은 0 이 되고, replyfrom 에는 해당 글 no, replyto 은 답신이 시작된 맨 처음 글 no, replydepth 는 해당 글의 replydepth 에서 1 을 더한 값으로 가진채 들어갑니다.
그리고 idx 는 해당글의 idx 가 들어갑니다.

헉. 헉. 쉬운 듯 한데 뭔가 복잡하군요. -_-;
실제 예를 보도록 하죠.

no : num : idx : 제목
----+-----+-----------------
4 : 4 : 4 : 좋겠수?
3 : 3 : 3 : 커헉. 진짜다!
2 : 2 : 2 : 와우. 1번을 드시다니!
1 : 1 : 1 : 안녕하세요!

위와 같은 상태이며 no 가 2번인 글에 답신 글을 달겠습니다. 일단 1번 과정인 '해당 글을 포함해
뒤의 글들 idx 값을 1씩 증가'를 하겠죠?

no : num : idx : 제목
----+-----+-----------------
4 : 4 : 5 : 좋겠수?
3 : 3 : 4 : 커헉. 진짜다!
2 : 2 : 3 : 와우. 1번을 드시다니!
1 : 1 : 1 : 안녕하세요!

이렇게 되었습니다. 그럼 2번 과정인 '해당 글의 replyon 을 1로 고침' 를 해볼까요? 음. 통신망의
줄이 80 bytes 니까 글 제목은 생략합니다.^^; 그리고 reply 는 rp 로 줄여쓸께요. ^^;

no : num : idx : rpon : rpfrom : rpto : rpdepth
----+-----+-----+------+--------+------+--------
4 : 4 : 5 : 0 : 0 : 0 : 0
3 : 3 : 4 : 0 : 0 : 0 : 0
2 : 2 : 3 : 1 : 0 : 0 : 0
1 : 1 : 1 : 0 : 0 : 0 : 0

위처럼요. 이제 3번 과정이 남았습니다. 이건 입력될 답신글 과정입니다.
그냥 입력되면 안되고 num 은 0, replyto 은 시작 글, replyfrom 은 해당 글, replydepth 는 해당 글의
replydepth 에서 1 증가지요? 그리고 idx 는 해당글의 idx 가 들어가구요.

no : num : idx : rpon : rpfrom : rpto : rpdepth
----+-----+-----+------+--------+------+--------
4 : 4 : 5 : 0 : 0 : 0 : 0
3 : 3 : 4 : 0 : 0 : 0 : 0
2 : 2 : 3 : 1 : 0 : 0 : 0
5 : 0 : 2 : 0 : 2 : 2 : 1
1 : 1 : 1 : 0 : 0 : 0 : 0

이렇게 됩니다. 여기서 no 가 5인 글이 바로 답신 글입니다.

여기서 만족할 순 없습니다. 답신 글 두개만 더 달아보죠. 우선 방금 입력된 새 답신글
(no 가 5인거)에 대한 답신글을 달아보겠습니다

1번 과정에 따른 테이블 모습 :


no : num : idx : rpon : rpfrom : rpto : rpdepth
----+-----+-----+------+--------+------+--------
4 : 4 : 6 : 0 : 0 : 0 : 0
3 : 3 : 5 : 0 : 0 : 0 : 0
2 : 2 : 4 : 1 : 0 : 0 : 0
5 : 0 : 3 : 0 : 2 : 2 : 1
1 : 1 : 1 : 0 : 0 : 0 : 0


=> no 가 5인 글을 포함한 그 이후의 글들
replyon 의 idx 가 1씩 증가했습니다.

2번 과정에 따른 테이블 모습 :


no : num : idx : rpon : rpfrom : rpto : rpdepth
----+-----+-----+------+--------+------+--------
4 : 4 : 6 : 0 : 0 : 0 : 0
3 : 3 : 5 : 0 : 0 : 0 : 0
2 : 2 : 4 : 1 : 0 : 0 : 0
5 : 0 : 3 : 1 : 2 : 2 : 1
1 : 1 : 1 : 0 : 0 : 0 : 0

=> no 가 5인 글의 replyon 이 1이 되었습니다.

3번 과정에 따른 테이블 모습 :

no : num : idx : rpon : rpfrom : rpto : rpdepth
----+-----+-----+------+--------+------+--------
4 : 4 : 6 : 0 : 0 : 0 : 0
3 : 3 : 5 : 0 : 0 : 0 : 0
2 : 2 : 4 : 1 : 0 : 0 : 0
5 : 0 : 3 : 1 : 2 : 2 : 1
6 : 0 : 2 : 0 : 5 : 2 : 2
1 : 1 : 1 : 0 : 0 : 0 : 0

=> no 가 6인 글이 입력되었습니다.
idx 는 no 가 5번의 idx 인 2가 들어갔고 5번에 대한 답신 글이므로 replyfrom 는 5가 들어갔습니다.
그리고 이러한 답신 글들은 시초가 no 가 2인 글이므로 replyto 에는 2가 들어갔습니다.
그리고 해당 글이 no 가 5인 글인데 이 글의 replydepth 는 1이므로 no 6 번(새로 입력된 답신글)의 replydepth 는 1이 증가한 2가 됩니다.


음. 이것만으로는 잘 이해가 안가시려나?

이번엔 다시 no 가 2인 글에 답신 글을 달아보겠습니다.

1번 과정에 따른 테이블 모습 :

no : num : idx : rpon : rpfrom : rpto : rpdepth
----+-----+-----+------+--------+------+--------
4 : 4 : 7 : 0 : 0 : 0 : 0
3 : 3 : 6 : 0 : 0 : 0 : 0
2 : 2 : 5 : 1 : 0 : 0 : 0
5 : 0 : 3 : 1 : 2 : 2 : 1
6 : 0 : 2 : 0 : 5 : 2 : 2
1 : 1 : 1 : 0 : 0 : 0 : 0

2번 과정에 따른 테이블 모습 :

no : num : idx : rpon : rpfrom : rpto : rpdepth
----+-----+-----+------+--------+------+--------
4 : 4 : 7 : 0 : 0 : 0 : 0
3 : 3 : 6 : 0 : 0 : 0 : 0
2 : 2 : 5 : 1 : 0 : 0 : 0
5 : 0 : 3 : 1 : 2 : 2 : 1
6 : 0 : 2 : 0 : 5 : 2 : 2
1 : 1 : 1 : 0 : 0 : 0 : 0

3번 과정에 따른 테이블 모습 :

no : num : idx : rpon : rpfrom : rpto : rpdepth
----+-----+-----+------+--------+------+--------
4 : 4 : 7 : 0 : 0 : 0 : 0
3 : 3 : 6 : 0 : 0 : 0 : 0
2 : 2 : 5 : 1 : 0 : 0 : 0
7 : 0 : 4 : 0 : 2 : 2 : 1
5 : 0 : 3 : 1 : 2 : 2 : 1
6 : 0 : 2 : 0 : 5 : 2 : 2
1 : 1 : 1 : 0 : 0 : 0 : 0

과정에 대한 설명은 뺐습니다. 저 위와 다를 게 없거든요. 단지 뭐가 어떻게 변했는지
찾아보시고 왜 그렇게 됐는지 과정 설명과 대입시켜 연산해보세요. :]


이걸로서 이론은 끝났습니다. 이제 실제로 소스로 구현해보겠습니다.

관련글 입력 방법은 위의 세 과정대로 하면 됩니다.

1. 해당 글을 포함해 뒤의 글들(idx 를 기준으로)
idx 값을 1씩 증가

이건

UPDATE testboard SET idx = idx + 1
WHERE idx >= 해당글idx

으로 하면 됩니다.

2. 해당 글의 replyon 을 1로 고침

이건

UPDATE testboard SET replyon=1
WHERE no = 해당글no


3. 답신 글 내용을 입력시킴. 이때 no 는 num 은 0 이 되고, replyfrom 에는 해당 글 no, replyto 은 답신이 시작된 맨 처음 글 no, replydepth 는 해당 글의 replydepth 에서 1 을 더한 값으로 가진채 들어갑니다.
그리고 idx 는 해당글의 idx 가 들어갑니다.

이건

INSERT INTO testboard VALUES ('',0,해당글idx,
'글제목','글본문',0,해당글번호,시작글번호,깊이, ...

식으로 들어가면 됩니다.

이때 중요한 것이 있습니다. 바로 replyto 입니다. 답신 당할(?) 해당글의 replyto 가
0 이 아닐 경우 입력될 replyto 에는 이 글의 replyto 가 저장되고, 0일 경우 replyto 에는 해당 글의 no 가 들어갑니다.

왜 그럴까요? 이게 더 빠르거든요. 만약 no 가 3번에 답신 글을 단다고 하죠.
이 글은 어떠한 글에 대한 답신 글이 아닌 그냥 일반 글일 경우, 이 글은 replyto 가 0 입니다.
어떠한 글에 대한 답신 글이 아니니까요. 이럴 때는 답신다는 글의 replyto 에 해당글의 no 가 들어갑니다.
하지만 답신 당할(?) 글이 이미 어떠한 글에 대한 답신 글일 경우 이미 들어가있는 replyto 값을 넣어주면 됩니다. no 를 넣으면 안되죠. :] 소스로 구현하자면

if (답신당할글의replyto) {
$rp[replyto] = 답신당한글의replyto;
}
else {
$rp[replyto] = 답신당한글의no;
}

정도 됩니다. 물론 $rp[replyto] 는 답신 글의 replyto 에 들어갈 변수구요.

에헤야. 그럼 슬슬 정리하는 기분으로 소스를 만들어보겠습니다.

<?
/*--------------------------
filename : reply.php3
--------------------------*/
$connect = mysql_connect("localhost","아이디","비번");
mysql_select_db("사용DB명",$connect);

require "function.php3";

$result = mysql_query("SELECT * FROM $board
WHERE no=$no", $connect);

$view = mysql_fetch_array($result);

echo ("

<html>

<head>
<title>답신 글 입력</title>
</head>

<body>
<center>
광고 및 욕설 글은 언제나 발견되는 대로 삭제됩니다. ^^<p>

<form method="post" action="run.php3"
enctype="multipart/form-data">
<input type="hidden" name="board"
value="$board">
<input type="hidden" name="rpo[no]"
value="$no">
<input type="hidden" name="mode" value="reply">

<table width="550" cellspacing="1"
border="0" cellpadding="2">
<tr>
<td align="left"><font size="2"><b>
| <a href="list.php3?board=$board"> |
게시물 목록</a>
</b></font></td>
</tr>
</table>

<table width="400" cellspacing="1" bgcolor="#A5A595"
border="0" cellpadding="5">
<!-- 작성자명 -->
<tr>
<td width="30%" bgcolor="#A5A595" align="center">
<font size="2" color="white"><b>작성자명</b></font></td>
<td width="70%" bgcolor="white" align="left">
<font color="white">
<input type="text" name="fil[name]" value="$mwbwd[name]"
size="10" maxlength="10">
</font></td>
</tr>

<!-- Email -->
<tr>
<td width="30%" bgcolor="#A5A595" align="center">
<font size="2" color="white"><b>E-mail</b></font></td>
<td width="70%" bgcolor="white" align="left">
<font color="white">
<input type="text" name="fil[email]" value="$mwbwd[email]"
size="20" maxlength="256">
</font></td>
</tr>

<!-- Homepage -->
<tr>
<td width="30%" bgcolor="#A5A595" align="center">
<font size="2" color="white"><b>Homepage</b></font></td>
<td width="70%" bgcolor="white" align="left">
<font color="white">
<input type="text" name="fil[homepage]" value="$mwbwd[homepage]"
size="20" maxlength="256">
</font></td>
</tr>

<!-- Password -->
<tr>
<td width="30%" bgcolor="#A5A595" align="center">
<font size="2" color="white"><b>비밀번호</b></font></td>
<td width="70%" bgcolor="white" align="left">
<font color="white">
<input type="password" name="fil[pw]" value="$mwbwd[pw]"
size="10" maxlength="20">
</font></td>
</tr>

<!-- Subject -->
<tr>
<td width="30%" bgcolor="#A5A595" align="center">
<font size="2" color="white"><b>글 제목</b></font></td>
<td width="70%" bgcolor="white" align="left">
<font color="white">
<input type="text" name="fil[title]"
size="30" maxlength="256" value="$view[usrtitle]">
</font></td>
</tr>

<!-- Text -->
<tr>
<td width="30%" bgcolor="#C5C5B5" align="center">
<font size="2" color="white"><b>본 문</b></font></td>
<td width="70%" bgcolor="white" align="left">
<font color="white">
<textarea name="fil[text]" wrap="hard" rows="10" cols="36">


::: $view[usrname] 님이 쓰신 글
$view[contents]
</textarea>
</font></td>
</tr>
</table>
<input type="submit" value="저장하자">
<input type="reset" value="재작성">
</form>

<table width="550" cellspacing="1"
border="0" cellpadding="2">
<tr>
<td align="right"><font size="2"><b>
| <a href="list.php3?board=$board"> |
게시물 목록</a>
</b></font></td>
</tr>
</table>

</center>
</body>

</html>
"); // 전체 화면 출력 완료
?>

 

이건 답신글 입력 폼 페이지입니다. :] 글 입력 폼과 거의 동일하므로 별도의 설명은 제외하죠.
(사실 쉬운 내용인지라)

이번엔 글 읽는 중 글 답신이 되야하기 때문에 글 읽어주는 view.php3 도 살짝 수정해야합니다.

<?
/*--------------------------
filename : view.php3
--------------------------*/
$connect = mysql_connect("localhost","아이디","비번");
mysql_select_db("사용DB명",$connect);

require "function.php3";

$updok = mysql_query("UPDATE $board SET
hit = hit + 1 WHERE no=$no", $connect);

$result = mysql_query("SELECT * FROM $board
WHERE no=$no", $connect);

$view = mysql_fetch_array($result);

$view[usrname] = htmlspecialchars($view[usrname]);
$view[usremail] = htmlspecialchars($view[usremail]);
$view[usrtitle] = htmlspecialchars($view[usrtitle]);
$view[contents] = htmlspecialchars($view[contents]);
$dates = date ("Y-m-d, h:i:s", $view[filluptime]);

$perpage = 10;
$tlpn = get_pagenum();
$nowpage = get_page($view[idx]);

if ($view[usremail] != "") {
$name = "<a
href="mailto:$view[usremail]">$view[usrname]</a>";
}
else {
$name = "$view[usrname]";
}
if ($view[usrhomepage] != "") {
$homeurl = "<a
href="$view[usrhomepage]"
target="_blank">[Homepage]</a>";
}
else {
$homeurl = "";
}

echo "
<html>

<head>
<title>글 내용 보기</title>
</head>

<body>
<center>


<table width="550" cellspacing="1"
border="0" cellpadding="2">
<tr>
<td align="left"><font size="2"><b>
|<a href="list.php3?board=$board&page=$nowpage">
게시물 목록</a>
|<a href="edit.php3?board=$board&no=$no">
수정</a>
|<a href="delete.php3?board=$board&no=$no">
삭제</a>
|<a href="reply.php3?board=$board&no=$no">
답신</a> |
</b></font></td>
</tr>
</table>

<table width="550" cellspacing="1"
border="0" cellpadding="2">
<tr>
<td colspan="2" bgcolor="#A5A595">
<font color="white" size="2">
$view[num] 번 글 : <b>$view[usrtitle]</b>
</font></td>
</tr>

<tr>
<td align="left" bgcolor="#E5E5D5">
<font size="2">조회수 : $view[hit]</font></td>

<td align="right" bgcolor="#E5E5D5">
<font size="2">$name 님이 $homeurl
$dates 에 작성해주셨습니다.</font></td>
</tr>
</table>

<table width="550" cellspacing="1"
border="0" cellpadding="2">
<tr>
<td><pre><font size="2">
$view[contents]
</font></pre>
</td>
</tr>
</table>

<table width="550" cellspacing="1"
border="0" cellpadding="2">
<tr>
<td align="right"><font size="2"><b>
|<a href="list.php3?board=$board&page=$nowpage">
게시물 목록</a>
|<a href="edit.php3?board=$board&no=$no">
수정</a>
|<a href="delete.php3?board=$board&no=$no">
삭제</a>
|<a href="reply.php3?board=$board&no=$no">
답신</a> |
</b></font></td>
</tr>
</table>

</center>

</body>

</html>
";
?>

단지

|<a href="list.php3?board=$board&page=$nowpage">
게시물 목록</a>
|<a href="edit.php3?board=$board&no=$no">
수정</a>
|<a href="delete.php3?board=$board&no=$no">
삭제</a> |

|<a href="list.php3?board=$board&page=$nowpage">
게시물 목록</a>
|<a href="edit.php3?board=$board&no=$no">
수정</a>
|<a href="delete.php3?board=$board&no=$no">
삭제</a>
|<a href="reply.php3?board=$board&no=$no">
답신</a> |

로 고친 것 뿐입니다. ^^;

이번엔 run.php3 에 답신글 입력 모드를 추가해 볼까요?

elseif ($mode == "reply") {
$result = mysql_query("SELECT * FROM $board
WHERE no=$rpo[no]", $connect);
$rpt = mysql_fetch_array($result);
mysql_free_result($result);

$rpi[replydepth] = $rpt[replydepth] + 1;
$rpi[idx] = $rpt[idx];

if ($rpt[replyto]) {
$rpi[replyto] = $rpt[replyto];
}
else {
$rpi[replyto] = $rpt[no];
}

$rpi[time] = time();
$rpi[pw] = crypt($fil[pw]);

$upidx = mysql_query("UPDATE $board SET idx = idx + 1
WHERE idx >= $rpt[idx]", $connect);
$upno = mysql_query("UPDATE $board SET replyon = 1
WHERE no = $rpo[no]", $connect);
$result = mysql_query("INSERT INTO $board VALUES('',
0, $rpi[idx], '$fil[title]', '$fil[text]',
0, $rpi[replyto], $rpo[no], $rpi[replydepth],
0, '', '', 0, '$fil[name]', '$rpi[pw]',
'$fil[email]', '$fil[homepage]', $rpi[time])", $connect);
}

에헤야. 생각보다 적죠? 차근 차근 살펴보겠습니다.

$result = mysql_query("SELECT * FROM $board
WHERE no=$rpo[no]", $connect);
$rpt = mysql_fetch_array($result);
mysql_free_result($result);

이건 답신 당할 글의 정보를 가져오는 과정 입니다. 이미 수차례 해봤죠? :]

$rpi[replydepth] = $rpt[replydepth] + 1;

이건 입력할 답신 글의 replydepth 를 만드는 겁니다.
replydepth 는 답신 당할 글의 replydepth 에서 1을 증가시켜준 걸로 저장하면 된다고 했었죠? :]

$rpi[idx] = $rpt[idx];

답신글의 idx 를 만드는 겁니다. 답신 당할 글의 idx 를 넣는거죠.
그리고 답신 당할 글 이후의(idx를 기준으로) 모든 글의 idx 를 1로 고치는 겁니다.
(이건 좀 더 아래에)

if ($rpt[replyto]) {
$rpi[replyto] = $rpt[replyto];
}
else {
$rpi[replyto] = $rpt[no];
}

이건 replyto 를 생성하는거죠? 위에서 설명했습니다. ^^;

$upidx = mysql_query("UPDATE $board SET idx = idx + 1
WHERE idx >= $rpt[idx]", $connect);

답신 당할 글 이후의(idx 기준) 글들의 idx 를 1씩 증가시키는 루틴입니다. WHERE 문이 핵심이죠.

$upno = mysql_query("UPDATE $board SET replyon = 1
WHERE no = $rpo[no]", $connect);

답신 당할 글의 replyon 을 1로 바꿔주는 부분입니다.
$rpo[no]는 아시다시피 reply.php3 에서 넘어오는 답신 당할 글 번호죠.

$result = mysql_query("INSERT INTO $board VALUES('',
0, $rpi[idx], '$fil[title]', '$fil[text]',
0, $rpi[replyto], $rpo[no], $rpi[replydepth],
0, '', '', 0, '$fil[name]', '$rpi[pw]',
'$fil[email]', '$fil[homepage]', $rpi[time])", $connect);

이제 답신 글을 저장합니다. :]

기왕한거 이미 배웠던 쿠키와 페이지 이동도 넣어볼까요? :]

expi = 60 * 60 * 24 * 30;
setcookie("mwbwd[name]", $fil[name], time() + $expi);
setcookie("mwbwd[email]", $fil[email], time() + $expi);
setcookie("mwbwd[homepage]", $fil[homepage], time() + $expi);

Header("Location: list.php3?board=$board");

이걸 뒤에 넣으면 됩니다. ^^


이제 게시물 리스트와 게시물 내용 보기를 다듬어보겠습니다.

게시물 리스트에서는 글 번호가 0으로 나오는 문제를 해결하는거죠. 무슨 말이냐구요?
관련 글은 num attribute 가 0 으로 들어가잖아요. :] 그런 뒤 re: 를 붙이는 기능도 하죠.

안녕
re: 오오오
re*2: 이야아
re*3: 오홍

식으로 되게요. :]

그런 뒤 게시물 내용 보기에서 몇 번 글이라고 출력되는 거를 몇 번 글에 대한 답신글 정도로 바꾸는 거구요.

일단 게시물 리스트를 고쳐보죠.

if ($list[num] == "0") $list[num] = "&nbsp;";

이건 num 이 0 이면 빈공백(&nbsp;)로 $list[num] 변수를 바꿔치기 하는 겁니다.

너무 간단하군요 -_-; 이번엔 RE: 를 붙이는걸 해보죠.

for ($i=1; $i <= $list[replydepth]; $i++) {
$blanktitle .= "&nbsp;&nbsp;";
}

if ($list[replydepth] == 1) {
$retitle .= "RE: ";
}
else {
$retitle .= "RE*$list[replydepth]: ";
}

단지 7줄이군요. (공백까지. 헤헤) 일단

for ($i=1; $i <= $list[replydepth]; $i++) {
$blanktitle .= "&nbsp;&nbsp;";
}

이거는 replydepth 를 체크하는 겁니다. replydepth 가 1이면 &nbsp;&nbsp; 한 개, 즉 빈 공백 2 칸이 붙죠.
그래서

안녕
re: 오오오
re*2: 이야아
re*3: 오홍

이게 가능해집니다. :]

re*2, re*3 처럼 해주는 건 그 다음 4 줄입니다.

if ($list[replydepth] == 1) {
$retitle .= "RE: ";
}
elseif ($list[replydepth] == 0) {
$retitle = "";
}
else {
$retitle .= "RE*$list[replydepth]: ";
}

간단하죠. replydepth 가 1일 경우는 그냥 RE: 로만 해주고, 1이 아닐 경우는 RE*replydepth 해주는 겁니다.
만약 replydepth 가 5일 경우 RE*5 가 되죠.

그런 뒤 제목줄을 기존처럼 $list[usrtitle] 만 하지 않고 $blanktitle 과 $retitle 을 붙여 줍니다.

$blanktitle$retitle$list[usrtitle]

처럼 해주시면 됩니다. list.php3 를 살짝 고쳐볼까요?

if ($list[num] == "0") $list[num] = "&nbsp;";

$blanktitle = "";
for ($j=1; $j <= $list[replydepth]; $j++) {
$blanktitle .= "&nbsp;&nbsp;";
}

$retitle = "";
if ($list[replydepth] == 1) {
$retitle = "RE: ";
}
elseif ($list[replydepth] == 0) {
$retitle = "";
}
else {
$retitle .= "RE*$list[replydepth]: ";
}

전 위의 코드를 출력하기 전에 넣어놨습니다. 그런데 의문 가지실 분이 계실려나?

for ($j=1; $j <= $list[replydepth]; $j++) {

에서 $i 도 아니고 왜 하필 $j 일까요.
이거 단박에 맞추시는 분은 정말 제 강좌의 열렬한 팬이실 듯. ^^; 이건 간단합니다.
우리는 게시물 리스트에서 줄마다 색상이 다르죠.
이걸 구현하기 위해 우리는 $i 변수를 사용했습니다. 그러니 $i 변수를 못쓰는거죠.
변수가 중복되면 첫 줄만 공백이고 나머지 줄은 색이 다 들어가있습니다. --;

이번엔 게시물을 읽을 때 몇 번 글, 몇 번 글에 대한 답신 글 이런 걸 구현해보죠.

원리부터 볼까요?
게시판은 어떤 걸 봐야 이용자가 읽으려하는 글이 어떤 글에 대한 답신 글인지 아닌지를 알 수 있을까요?
일단 replyon 이 있을 겁니다. replyon 이 1 이면 그 글은 답신 글이 아닐 가능성이 많습니다.
replyon 은 해당 글이 답신 글을 가지고 있다는 의미거든요.

하지만 꼭 그런 건 아니랍니다.
답신 글도 답신 글을 가질 수 있거든요. :] 때문에 우리는 해당 글이 답신 글인지 아닌지를 알 수 있기 위해서는 replyon 과 더불어 replyto, replyfrom, replydepth 중 나를 함께 검사해봐야 해당 글이 답신 글인지 알 수 있습니다. 왜냐하면 답신 글은 replyto, replyfrom, replydepth 들이 0이 아니거든요. 전 간단하게 replyto 로 하죠 뭐.

일단 답신 글이 아닌 경우는 어떤 경우일 까요?

첫 번째는 replyon 이 0 보다 크고 replyto 은 0인 경우입니다.
즉 글 자체가 답신 글을 갖고 있는 경우지요.
정확히 말하면 글 자체가 답신 글을 갖고 있으며 어느 글에 대한 답신 글이 아닌 경우입니다.

두 번째는 replyon 이 0 이고 replyto 역시 0 인 경우입니다. 즉 답신 글을 갖고
있지 않고 replyto 역시 0일 때. 이걸 if 문으로 하면

if (($view[replyon] > 0) && ($view[replyto] == 0))
{
$num = "$no";
$num .= "번 글";
}
elseif (($view[replyon] == 0) && ($view[replyto] == 0)) {
$num = "$no";
$num .= "번 글";
}

이 됩니다. 그리고 그 외의 경우는 모두 답신 글로 처리를 하죠.

else {
$num = "$view[replyfrom]";
$num .= "번의 답신글($view[no])";
}

이걸 게시물 내용 출력하기 전에 처리해주면 되겠죠오. 그런 뒤

<table width="550" cellspacing="1"
border="0" cellpadding="2">
<tr>
<td colspan="2" bgcolor="#A5A595">
<font color="white" size="2">
$view[num] 번 글 : <b>$view[usrtitle]</b>

<table width="550" cellspacing="1"
border="0" cellpadding="2">
<tr>
<td colspan="2" bgcolor="#A5A595">
<font color="white" size="2">
$num : <b>$view[usrtitle]</b>

로 바꾸면 됩니다. ^^;

최근 일에 쫓기다보니 기한 맞추기 위해 빠르게 강좌를 쓰는 영향으로 오타가 많고 내용상의 문제도 간간히 나타나고 있습니다. 이것에 대해 정말 죄송스런 맘을 감출 수가 없군요. 흑.

'미-2'편은 약간은 회의적인(?) 내용을 담을 예정이랍니다. 흑.

이제 사실상의 게시판 제작은 끝났습니다. 자료실과 메일 보내기 기능을 빼버리면 사실상 게시판으로서
필요한 걸 다 구현한 셈이지요.

----------------------------
함께하면 즐거운 사이트들 (-_-; 광고임 -_-;)
http://game.creple.com/delthia
http://creple.com
http://coco.st
----------------------------


- ?! 디망쉬

관련자료

댓글 0
등록된 댓글이 없습니다.

공지사항


뉴스광장


  • 현재 회원수 :  60,041 명
  • 현재 강좌수 :  35,855 개
  • 현재 접속자 :  135 명