[php] 게시판 페이지 4 - 게시글 수정&생성 페이지 만들기
※ 보안적 요소는 거의 고려하지 않고 php명령어 숙달용으로 혼자서 만드는 로그인 페이지 입니다.
▶게시판 페이지를 위해 만들어야 할 파일 (※이번 시간에 만들파일은 굵은 글씨로 표기)
db.php : 데이터베이스 연결파일
index.php : 게시판 홈 화면
search_result.php : 게시글 검색 화면
board_read.php : 게시글 읽는 페이지
board_modify.php : 게시글 수정&생성 페이지
modify_check.php : 게시글 수정&생성 처리 페이지
board_delete.php : 게시글 삭제 처리 페이지
thumb_check.php : 좋아요 기능 처리 페이지
▶말하기 앞서
'회원가입 페이지 만들기' 에서 회원가입과 회원정보수정 페이지를 통합했듯이, 나는 되도록 만들 수 있는 페이지를 줄이려 하는 편이다. 게시글 수정&생성페이지 역시 합쳐서 두 기능을 한 페이지에서 처리할 수 있기 때문에 나는 두 페이지를 합쳐서 만들었다. 개인적으로 이렇게하면 코드가 복잡해지기 때문에 수정페이지와 생성페이지를 분리해서 만드는 것도 괜찮다고 생각한다.
▶게시글 수정&생성 페이지(board_modify.php)
위에서 언급한 회원가입과 회원정보수정 페이지 응용이다. 회원가입과 회원정보수정을 세션유무에 따라서 나눴듯이 게시글 수정&생성 페이지는 게시글의 id값을 받느냐 안받느냐로 구분한다. 또한, 게시글의 id값을 받아도 내가 작성자가 아니면 수정권한이 없도록 해야한다. 내가 코드로 구성한 부분은 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
<?php
// GET 변수를 받는지 확인
if(isset($_GET["idx"])) {
// 수정모드 부여
$mode = "modify";
$head = "글 수정";
// 수정권한 확인
$id = $_GET["idx"];
$sql = "SELECT * FROM board WHERE idx = '$id'";
$res = mysqli_query($conn1,$sql);
$board = mysqli_fetch_array($res);
$id = $_GET["idx"];
// 세션아이디와 작성자아이디 일치 확인
if(!($_SESSION['ss_jj_id'] === $board['id'])) {
echo "<script>alert('권한이 없습니다.');</script>";
echo "<script>history.go(-1);</script>";
}
else {
// 아무것도 없이 pass
}
} else {
// 글 작성 모드 부여
$mode = "insert";
$head = "글 작성";
$mod_cer = "";
}
?>
|
cs |
GET값을 받게 되면, 'modify'모드를 설정하기 위해, $mode 변수에 'modify'를 부여한다. 그리고 id값에 따른 게시글에 정보를 불러오고, 그 정보 중 아이디값을(아이디는 unique key라 중복이 불가하므로) 비교하여 권한이 있는지 없는지 확인한다.
GET값을 받지 못하면, 게시글 페이지에서 넘어온 것이 아니니, 'insert'모드를 설정한다. $mode 변수에 'insert'를 부여하고 $mod_cer은 insert모드에만 부여하는 변수인데 빈값을 입력해준다. 빈값을 입력해줘도 입력한 값은 존재하므로, isset함수로 확인해보면 True(1)가 나오게 된다. (이는 뒤에서 modify모드일 때, board의 내용들을 불러올 때 사용된다.)
이제 값들을 입력하고 "modify_check.php"에 보내줄 form을 정의하는데, post방식으로 보내준다. get방식으로 보내면 url조작으로 게시글의 수정에 나쁜 영향을 줄 수 있기 때문이다. 보내줄 값은 해당 게시글의 id값과 mode(insert/modify)값과 입력할 정보들(title, content, file)이다. 또한, 회원가입/정보수정 페이지에서 만든 것의 복습인데, <?php echo $mod_cer ?? $board['content'] ?> 와 같이 '??' 기능을 활용할 예정이다('echo ~ ?? ~ '는 앞의 변수가 존재하면 해당 변수를, 없다면 뒤의 변수를 출력하는 기능이다. 이제보니깐 $board['~']를 앞에뒀으면 $mod_cer변수를 정의할 필요가 없었을 것 같다.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<form class="mt-3" action="./modify_check.php" method="post" enctype="multipart/form-data">
<input type="hidden" name="mode" value="<?php echo $mode ?>">
<input type="hidden" name="id" value="<?php echo $id ?>">
<div class="container">
<div class="row g-5">
<div class="form-group">
<label for="title" class="form-label mt-5">제목</label>
<textarea name="title" id="title" type="title" class="form-control" placeholder="제목을 입력하세요." rows="1"><?php echo $mod_cer ?? $board['title'] ?></textarea>
</div>
<div class="form-group">
<label for="Textarea" class="form-label mt-4">내용</label>
<textarea class="form-control" name="content" id="content" placeholder="내용을 입력하세요" rows="4" style="height: 154px;" required><?php echo $mod_cer ?? $board['content'] ?></textarea>
</div>
<div class="form-group mb-5">
<label for="formFile" class="form-label mt-4">파일첨부</label>
<input class="form-control" type="file" id="formFile" name="j_file"/>
</div>
<button type="submit" class="btn btn-primary"><?=$head?></button>
</div>
</div>
</form>
|
cs |
이렇게 구성된 게시글 수정/생성 페이지는 다음과 같이 구성된다.
▶게시글 수정&생성 처리 페이지(modify_check.php)
세션에서 로그인한 사람의 이름(내가 만들었던 로그인페이지에는 없었는데, 이름도 세션정보로 저장하게 추가설정했다.) 그리고 아이디정보를 받는다. POST로는 바로 전에 전송했던 정보들을 전부 받아준다. 그리고 file정보는 조금 독특하게 받는데, 우선 file을 받는 것과 관련된 명령어들을 알아야 한다.
명령어 | 설명 |
$_FILES['file']['name'] | 업로드된 파일의 이름 |
$_FILES['file']['type'] | 업로드된 파일의 MIME(마임) 형식 - 예:image/gif |
$_FILES['file']['size'] | 업로드된 파일의 크기(바이트로 표시됨) |
$_FILES['file']['tmp_name'] | 서버에 저장된 파일의 임시 복사본의 이름 |
$_FILES['file']['error'] | 파일 업로드 중 발생한 오류의 오류코드 |
우선, tmp_name을 이용해서 임시로 파일을 받아놓고(서버의 tmp파일에 저장.), name을 이용해서 파일이름을 뽑아준다. 그리고 파일을 저장할 다이렉션 경로를 지정해준다(나같은 경우, ./upload_file/로 경로를 설정했음). 또한, error을 변수로 저장해서 오류가 있을 때는 오류코드를 통해 어떤 오류가 있는지 출력하도록 만든다. file업로드에 관련된 오류코드는 다음과 같다.
오류 값 | 오류 코드 | 설명 |
0 | UPLOAD_ERR_OK | 로드 정상 완료 |
1 | UPLOAD_ERR_INI_SIZE | php.ini에 설정된 최대 파일크기 초과 |
2 | UPLOAD_ERR_FORM_SIZE | HTML폼에 설정된 최대 파일크기 초과 |
3 | UPLOAD_ERR_PARTIAL | 파일의 일부만 업로드 됨 |
4 | UPLOAD_ERR_NO_FILE | 업로드할 파일이 없음 |
6 | UPLOAD_ERR_NO_TMP_DIR | 웹서버에 임시폴더가 없음 |
7 | UPLOAD_ERR_CANT_WRITE | 웹서버에 파일을 쓸 수 없음 |
8 | UPLOAD_ERR_EXTENSION | PHP 확장기능에 의한 업로드 중단 |
다음과 같이 구성해서 변수들을 활용하되, 파일 업로드 오류가 있으면 오류 메시지를 출력하게끔 설정했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
<?php
// 세션 변수
$name = trim($_SESSION['ss_jj_name']);
$user_id = trim($_SESSION['ss_jj_id']);
// 받아온 데이터들 정리
$mode = $_POST['mode'];
$title = $_POST['title'];
$content = $_POST['content'];
$id = $_POST['id'];
// 파일관련 변수
$file_tmp = $_FILES['j_file']['tmp_name'];
$file_name = $_FILES['j_file']['name'];
$file_dir = "./upload_file/".$file_name;
$file_error = $_FILES['j_file']['error'];
move_uploaded_file($file_tmp,$file_dir);
// 파일 오류코드 에러발생시 (0은 정상, 4는 파일 미첨부)
switch ($file_error) {
case 1:
echo "<script>alert('파일의 용량이 큽니다.');</script>";
echo "<script>history.go(-1);</script>";
exit;
case 2:
echo "<script>alert('파일의 용량이 큽니다.');</script>";
echo "<script>history.go(-1);</script>";
exit;
case 3:
echo "<script>alert('파일이 일부만 업로드 됐습니다.');</script>";
echo "<script>history.go(-1);</script>";
exit;
case 5:
echo "<script>alert('웹서버에 임시폴더가 없습니다.');</script>";
echo "<script>history.go(-1);</script>";
exit;
case 7:
echo "<script>alert('PHP 확장기능을 확인해주세요.');</script>";
echo "<script>history.go(-1);</script>";
exit;
}
// 모드에 따른 SQL 처리
if($mode == "insert"){
$sql = "INSERT INTO board SET id ='$user_id', name ='$name', title = '$title', content = '$content', file = '$file_name'";
$result = mysqli_query($conn1, $sql);
} else if($mode == "modify"){
$sql = "UPDATE board
SET id ='$user_id', name = '$name', title = '$title', content = '$content', file = '$file_name' WHERE idx = '$id'";
$result = mysqli_query($conn1, $sql);
} else {
echo "<script>alert('mode set error!');</script>";
echo "<script>history.go(-1);</script>";
}
//업로드 결과
if ($result) {
echo "<script>alert('완료되었습니다.');</script>";
echo "<script>location.replace('./index.php');</script>";
} else {
echo "error, please check again.";
mysqli_error($conn1);
mysqli_close($conn1);
}
|
cs |
▶게시글 삭제 처리페이지(board_delete.php)
삭제처리는 딱히 삭제를 설정하는 페이지가 필요없다. 따라서 삭제버튼을 눌렀을 때, 권한이 있으면 삭제되게끔 처리하는 페이지만 만들어주면 된다. GET으로 게시글 id정보를 받고, 세션으로 로그인한 사람의 id정보를 불러온다. GET으로 받은 게시글의 id정보로 해당 게시글의 전부를 모두 불러오고, 그 중의 작성자 id와 관련된 값을 불러와서 세션에 저장된 id값과 비교해준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<?php
$id = $_GET['idx'];
$user_id = trim($_SESSION['ss_jj_id']);
$sql1 = "SELECT id FROM board WHERE idx='$id'";
$res = mysqli_query($conn1, $sql1);
$arr = mysqli_fetch_array($res);
if(!($user_id===$arr[0])) {
echo "<script>alert('권한이 없습니다.');</script>";
echo "<script>location.replace('./index.php');</script>";
} else {
$sql = "DELETE FROM board WHERE idx='$id'";
$result = mysqli_query($conn1, $sql);
if($result) {
echo "<script>alert('삭제되었습니다.');</script>";
echo "<script>location.replace('./index.php');</script>";
} else {
echo "error, please check again.";
mysqli_error($conn1);
mysqli_close($conn1);
}
}
|
cs |
현재 접속한 사람이 작성자가 맞으면 삭제가 처리된다.