파일업로드를 위해 글쓰기 부분을 수정한다.
/app/Views/board_write.php
< form method = "post" action = " <?= site_url ( '/writeSave' ) ? > " enctype = "multipart/form-data" >
< input type = "hidden" name = "bid" value = " <?php echo isset ( $view -> bid )? $view -> bid : 0 ; ? > " >
< div class = "mb-3" >
< label for = "exampleFormControlInput1" class = "form-label" > 이름 </ label >
< input type = "text" name = "username" class = "form-control" id = "exampleFormControlInput1" placeholder = "이름을 입력하세요." value = " <?php echo $_SESSION [ 'username' ] ? > " >
</ div >
< div class = "mb-3" >
< label for = "exampleFormControlInput1" class = "form-label" > 제목 </ label >
< input type = "text" name = "subject" class = "form-control" id = "exampleFormControlInput1" placeholder = "제목을 입력하세요." value = " <?php echo isset ( $view -> subject )? $view -> subject : '' ; ? > " >
</ div >
< div class = "mb-3" >
< label for = "exampleFormControlTextarea1" class = "form-label" > 내용 </ label >
< textarea class = "form-control" id = "exampleFormControlTextarea1" name = "content" rows = "3" > <?php echo isset ( $view -> content )? $view -> content : '' ; ? > </ textarea >
</ div >
< div class = "mb-3" >
< input type = "file" name = "upfile" id = "upfile" class = "form-control form-control-lg" aria-label = "Large file input example" >
</ div >
< br />
<?php
$btntitle = isset ( $view -> bid )? "수정" : "등록" ;
? >
< button type = "submit" class = "btn btn-primary" > <?php echo $btntitle ; ? > </ button >
</ form >
이렇게 파일 선택하는 부분이 생긴다. 왜 이게 생겼는지 모르면 html 부터 공부하고 오자.
파일을 저장하기 위해서는 파일을 저장하는 테이블을 만들어야한다. 물론 다른 방법도 있다. board 테이블에 칼럼을 하나 파서 거기다 넣어도 된다. 그런데 내가 그런 방식을 싫어한다. 자기 맘이란 소리다.
CREATE TABLE `file_table` ( `fid` int(11) NOT NULL AUTO_INCREMENT, `bid` int(11) DEFAULT NULL, `userid` varchar(100) DEFAULT NULL, `filename` varchar(100) DEFAULT NULL, `regdate` datetime DEFAULT current_timestamp(), `status` tinyint(4) DEFAULT 1, `memoid` int(11) DEFAULT NULL, `type` varchar(45) DEFAULT NULL, PRIMARY KEY (`fid`), KEY `idx_file_table_userid` (`userid`), KEY `idx_file_table_type` (`type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
기존에 있던 사람들은 그 테이블을 지우고 다시 만들자. 기존건 문제가 좀 있었다...쿨럭...
이제 파일을 첨부하고 등록하면 파일을 서버에 저장해주는 부분을 수정해보자. 어디서 해야겠는가? 그렇다 컨트롤러다.
/app/Controllers/Board.php
<?php
namespace App\Controllers ;
use App\Models\ BoardModel ; //사용할 모델을 반드시 써줘야한다.
class Board extends BaseController
{
public function list ()
{
$db = db_connect ();
$query = "select * from board order by bid desc" ;
$rs = $db -> query ( $query );
$data [ 'list' ] = $rs -> getResult (); //결과값 저장
return render ( 'board_list' , $data ); //view에 리턴
}
public function write ()
{
if (! isset ( $_SESSION [ 'userid' ])){
echo "<script>alert('로그인하십시오.');location.href='/login'</script>" ;
exit ;
}
return render ( 'board_write' );
}
public function save ()
{
if (! isset ( $_SESSION [ 'userid' ])){
echo "<script>alert('로그인하십시오.');location.href='/login'</script>" ;
exit ;
}
$db = db_connect ();
$bid = $this -> request -> getVar ( 'bid' ); //bid값이 있으면 수정이고 아니면 등록이다.
$subject = $this -> request -> getVar ( 'subject' );
$content = $this -> request -> getVar ( 'content' );
if ( $bid ){
$query = "select * from board where bid=" . $bid ;
$rs = $db -> query ( $query );
if ( $_SESSION [ 'userid' ]== $rs -> getRow ()-> userid ){
$sql = "update board set subject='" . $subject . "', content='" . $content . "' where bid=" . $bid ;
$rs = $db -> query ( $sql );
return $this -> response -> redirect ( site_url ( '/boardView/' . $bid ));
} else {
echo "<script>alert('본인이 작성한 글만 수정할 수 있습니다.');location.href='/login';</script>" ;
exit ;
}
}
$file = $this -> request -> getFile ( 'upfile' ); //첨부한 파일의 정보를 가져온다.
if ( $file -> getName ()){ //파일 정보가 있으면 저장한다.
$filename = $file -> getName (); //기존 파일명을 저장할때 필요하다. 여기서는 사용하지 않는다.
//$filepath = WRITEPATH. 'uploads/' . $file->store(); 매뉴얼에 나와있는 파일 저장 방법이다.여기서는 안쓴다.
$newName = $file -> getRandomName (); //서버에 저장할때 파일명을 바꿔준다.
$filepath = $file -> store ( 'board/' , $newName ); //CI4의 store 함수를 이용해 저장한다.
}
$sql = "insert into board (userid,subject,content) values ('" . $_SESSION [ 'userid' ] . "','" . $subject . "','" . $content . "')" ;
$rs = $db -> query ( $sql );
$insertid = $db -> insertID ();
if ( $file -> getName ()){
$sql2 = " INSERT INTO file_table
(bid, userid, filename, type )
VALUES (' " . $insertid . "', ' " . $_SESSION [ 'userid' ] . "', '" . $filepath . "','board')" ;
$rs2 = $db -> query ( $sql2 );
}
return $this -> response -> redirect ( site_url ( '/board' ));
}
public function view ( $bid = null )
{
$db = db_connect ();
$query = "select * from board where bid=" . $bid ;
$rs = $db -> query ( $query );
$data [ 'view' ] = $rs -> getRow ();
$query2 = "select * from file_table where type='board' and bid=" . $bid ;
$rs2 = $db -> query ( $query2 );
$data [ 'file_view' ] = $rs2 -> getRow ();
return render ( 'board_view' , $data );
}
public function modify ( $bid = null )
{
$db = db_connect ();
$query = "select * from board where bid=" . $bid ;
$rs = $db -> query ( $query );
if ( $_SESSION [ 'userid' ]== $rs -> getRow ()-> userid ){
$data [ 'view' ] = $rs -> getRow ();
return render ( 'board_write' , $data );
} else {
echo "<script>alert('본인이 작성한 글만 수정할 수 있습니다.');location.href='/login';</script>" ;
exit ;
}
}
public function delete ( $bid = null )
{
$db = db_connect ();
$query = "select * from board where bid=" . $bid ;
$rs = $db -> query ( $query );
if ( $_SESSION [ 'userid' ]== $rs -> getRow ()-> userid ){
$query = "delete from board where bid=" . $bid ;
$rs = $db -> query ( $query );
return $this -> response -> redirect ( site_url ( '/board' ));
} else {
echo "<script>alert('본인이 작성한 글만 삭제할 수 있습니다.');location.href='/login';</script>" ;
exit ;
}
}
}
save() 함수 부분을 확인해보자. 소스에 주석을 달아놨다. 첨부한 파일의 정보를 가져올때 upfile이라는 이름은 board_write.php에서 지정했던 이름이다.
그리고 그 아래에 보면 file_table이라는 테이블에 파일 등록 정보를 따로 저장하는 부분을 추가 했다. 기존에 php강좌에서 사용했던 방식 그대로 쓰는거다. 새로운게 아니다. 만약 테이블이 없다면 https://programmerdaddy.tistory.com/215 이 링크를 보고 오자.
이렇게 하고 파일을 첨부해서 글을 등록해보자. 그리고 파일이 제대로 등록됐는지 확인해보자. 우선 파일이 잘 올라갔는지 확인해보자.
컨트롤러에서 파일을 저장하기위해 사용한 함수가 있었다.
$filepath = $file->store('board/', $newName);
첨부한 파일을 board라는 폴더에 저장하라는 뜻이다. 그런데 board는 어디에 있는 board란 말인가? 위 첨부한 이미지에 보듯이 CI4는 기본적으로 /writable/uploads/아래에 등록하게 된다. 거기에 board라는 폴더를 옵션으로 주었기때문에 그 아래board라는 폴더에 파일을 저장했다.
테이블에도 잘 들어갔는지 확인해보자.
이렇게 file_table 테이블에잘 들어갔다. file_name에 있는 값과 board 폴더에 들어간 파일명이 같은지 확인해보자.
그런데 이렇게만 되면 별 문제 없는 것 처럼 보이지만 아주 큰 문제가 있다. 저 wirtable이라는 폴더를 웹에서는 접근할 수 가 없다. 사용자 보기 페이지에서 저 파일을 보기 위해서 저 파일에 접근해야하지만 웹 권한으로는 접근이 안된다.
그래서 심볼릭 링크를 주거나 하는 별의별 방법을 다 동원하게 된다.
다음 시간엔 첨부 파일의 업로드 경로를 수정해 웹에서도 접근할 수 있도록 수정해보도록 하자.