Web/CodeIgniter 검색 결과

11개 발견
  1. 미리보기
    2015.08.28 - Palpit

    [CodeIgniter] 9. AJAX 구현: jQuery

  2. 미리보기
    2015.08.26 - Palpit

    [CodeIgniter] 8. AJAX 구현: XMLHttpRequest

  3. 미리보기
    2015.08.25 - Palpit

    [CodeIgniter] 7. 사용자 인증(로그인)

  4. 미리보기
    2015.08.24 - Palpit

    [CodeIgniter] 6. 놓치기 쉬운 보안

  5. 미리보기
    2015.08.24 - Palpit

    [CodeIgniter] 5. 폼 검증하기

  6. 미리보기
    2015.08.23 - Palpit

    [CodeIgniter] 4. 게시판 프로젝트 - 수정, 삭제

  7. 미리보기
    2015.08.23 - Palpit

    [CodeIgniter] 4. 게시판 프로젝트 - 검색, 입력, 보기 기능

  8. 미리보기
    2015.08.21 - Palpit

    [CodeIgniter] 4. 게시판 프로젝트 - DB 설계, 페이징 처리

[CodeIgniter] 9. AJAX 구현: jQuery

2015.08.28 10:49 - Palpit
조회수 확인

8장에서 XMLHttpRequest 객체를 이용해 댓글 쓰기, 삭제를 구현헀습니다. 


9장에서는 jQuery를 이용해 구현해보도록 하겠습니다.


AJAX를 구현하기 위해 복잡한 과정을 거치고 DOM 스크립팅을 이용해 개발했는데 9장에서 jQuery를 이용해 개발한 소스를 비교해보면 jQuery가 단순하고 간결하게 프로그래밍할 수 있습니다.





9.1 댓글 쓰기 AJAX로 구현

 컨트롤러와 모델 부분은 수정하지 않고 뷰만 DOM 스크립팅에서 jQuery를 이용한 방식으로 수정하면 됩니다.


 * bbs/application/views/board/view_v.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<!-- <script type="text/javascript" src="/bbs/include/js/httpRequest.js"></script> -->
<script>
    $(document).ready(function() {
        $("#search_btn").click(function() {
            if ($("#q").val() == '') {
                alert("검색어를 입력하세요!");
                return false;
            } else {
                var act = "/bbs/board/lists/ci_board/q/" + $("#q").val() + "/page/1";
                $("#bd_search").attr('action', act).submit();
            }
        });
    });
 
    function board_search_enter(form) {
        var keycode = window.event.keyCode;
        if (keycode == 13)
            $("#search_btn").click();
    }
    
    $(function() {
        $("#comment_add").click(function () {
            $.ajax({
                url: "/bbs/ajax_board/ajax_comment_add",
                type: "POST",
                data: {
                    "comment_contents": encodeURIComponent($("#input01").val()),
                    "csrf_test_name": getCookie('csrf_cookie_name'),
                    "table""<?php echo $this->uri->segment(3); ?>",
                    "board_id""<?php echo $this->uri->segment(4); ?>"
                },
                dataType: "html",
                complete: function(xhr, textStatus) {
                    if (textStatus == 'success') {
                        if (xhr.responseText == 1000) {
                            alert('댓글 내용을 입력하세요.');
                        } else if (xhr.responseText == 2000) {
                            alert('다시 입력하세요.');
                        } else if (xhr.responseText == 9000) {
                            alert('로그인해야 합니다.');
                        } else {
                            alert($("#comment_area").html());
                            $("#comment_area").html(xhr.responseText);
                            $("#input01").val('');
                        }
                    }
                }
            });
        });
    });
 
    function comment_delete(no) {
        ......
    }
    
    function delete_action() {
        ......
    }
    
    function getCookie(name) {
        ......
    }
</script>
<article id="board_area">
    <header>
        <h1></h1>
    </header>
    <table cellspacing="0" cellpadding="0" class="table table-striped">
        <thead>
            <tr>
                <th scope="col"><?php echo $views -> subject;?></th>
                <th scope="col">이름: <?php echo $views -> user_name;?></th>
                <th scope="col">조회수: <?php echo $views -> hits;?></th>
                <th scope="col">등록일: <?php echo $views -> reg_date;?></th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th colspan="4">
                    <?php echo $views -> contents;?>
                </th>
            </tr>
        </tbody>
        <tfoot>
            <tr>
                <th colspan="4">
                    <a href="/bbs/board/lists/<?php echo $this -> uri -> segment(3); ?>/
                        page/<?php echo $this -> uri -> segment(7); ?>" class="btn btn-primary">목록 </a>
                    <a href="/bbs/board/modify/<?php echo $this -> uri -> segment(3); ?>/board_id/
                        <?php echo $this -> uri -> segment(4); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-warning"> 수정     </a>
                    <a href="/bbs/board/delete/<?php echo $this -> uri -> segment(3); ?>/board_id/
                        <?php echo $this -> uri -> segment(4); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-danger"> 삭제 </a>
                    <a href="/bbs/board/write/<?php echo $this -> uri -> segment(3); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-success">쓰기</a>                    
                </th>
            </tr>
        </tfoot>
    </table>
    
    <form class="form-horizontal" method="POST" action="" name="com_add">
        <fieldset>
            <div class="control-group">
                <label class="control-label" for="input01">댓글</label>
                <div class="controls">
                    <textarea class="input-xlarge" id="input01" name="comment_contents" rows="3"></textarea>
                    <input class="btn btn-primary" type="button" id="comment_add" value="작성" />
                    <p class="help-block"></p>
                </div>
            </div>
        </fieldset>
    </form>
    <div id="comment_area">
        <table cellspacing="0" cellpadding="0" class="table table-striped">
            <tbody>
<?php
    foreach ($comment_list as $lt) {
?>
                <tr id="row_num_<?php echo $lt->board_id; ?>">
                    <th scope="row">
                        <?php echo $lt->user_id;?>
                    </th>
                    <td><?php echo $lt->contents;?></a></td>
                    <td>
                        <time datetime="<?php echo mdate("%Y-%M-%j", human_to_unix($lt->reg_date)); ?>">
                            <?php echo $lt->reg_date;?>
                        </time>
                    </td>
                    <td>
                        <a href="#" onclick="javascript:comment_delete('<?php echo $lt->board_id; ?>')">
                            <i class="icon-trash"></i> 삭제
                        </a>
                    </td>
                </tr>
<?php
    }
?>
            </tbody>
        </table>
    </div>
</article
cs




 Line 21: jQuery에서 단순히 함수를 실행하라는 의미이며, DOM 객체를 사용할 준비가 되면 기능을 실행합니다.

 Line 22: jQuery에서 #은 id를 가리키고 .은 class를 가리킵니다. id가 comment_add 인 요소에 마우스 클릭 이벤트가 발생했을 때 기능을 실행하라는 의미입니다. 

 Line 23: $.ajax(action) 형태로 사용되며 AJAX 를 이용하기 위한 함수입니다. 옵션을 설정하면 그 옵션 에 대해 AJAX 액션을 실행하고 응답 결과에 대한 처리를 해줍니다.
























 jQuery를 이용해 8장의 소스보다 단순하고 간결하게 구현이 되었습니다.. 지시자 $("#comment_add")를 이용해 간단하게 요소를 지정할 수 있고, 다른 함수를 체인 형태로 연결해 실행할 수 있어 코드가 짧아지고 이해하기 쉽습니다.















9.2 댓글 삭제 AJAX 구현

 9.1 절과 마찬가지로 DOM 스크립팅으로 되어있던 내용을 jQuery로 수정합니다.


 * bbs/application/views/board/view_v.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<!-- <script type="text/javascript" src="/bbs/include/js/httpRequest.js"></script> -->
<script>
    $(document).ready(function() {
        $("#search_btn").click(function() {
            if ($("#q").val() == '') {
                alert("검색어를 입력하세요!");
                return false;
            } else {
                var act = "/bbs/board/lists/ci_board/q/" + $("#q").val() + "/page/1";
                $("#bd_search").attr('action', act).submit();
            }
        });
    });
 
    function board_search_enter(form) {
        var keycode = window.event.keyCode;
        if (keycode == 13)
            $("#search_btn").click();
    }
    
    $(function() {
        $("#comment_add").click(function () {
            ......     
        });
        
        $(".comment_delete").click(function() {
            $.ajax({
                url: '/bbs/ajax_board/ajax_comment_delete',
                type: 'POST',
                data: {
                    "csrf_test_name": getCookie('csrf_cookie_name'),
                    "table""<?php echo $this->uri->segment(3); ?>",
                    "board_id": $(this).attr("vals")
                },
                dataType: "text",
                complete: function(xhr, textStatus) {
                    if (textStatus == 'success') {
                        if (xhr.responseText == 9000) {
                            alert('로그인해야합니다.');
                        } else if (xhr.responseText == 8000) {
                            alert('본인의 댓글만 삭제할 수 있습니다.');
                        } else if (xhr.responseText == 2000) {
                            alert('다시 삭제하세요.');
                        } else {
                            $('#row_num_' + xhr.responseText).remove();
                            alert('삭제되었습니다.');
                        }
                    }
                }
            });
        });
    });
 
 
    
    
    function getCookie(name) {
        var nameOfCookie = name + "=";
        var x = 0;
        
        while ( x <= document.cookie.length) {
            var y = (x + nameOfCookie.length);
            
            if (document.cookie.substring(x, y) == nameOfCookie) {
                if (( endOfCookie = document.cookie.indexOf(";", y)) == -1
                    endOfCookie = document.cookie.length;
                
                return unescape(document.cookie.substring(y, endOfCookie));
            }
            
            x = document.cookie.indexOf(" ", x) + 1;
            
            if ( x == 0
            
            break;
        }
    }
</script>
<article id="board_area">
    <header>
        <h1></h1>
    </header>
    <table cellspacing="0" cellpadding="0" class="table table-striped">
        <thead>
            <tr>
                <th scope="col"><?php echo $views -> subject;?></th>
                <th scope="col">이름: <?php echo $views -> user_name;?></th>
                <th scope="col">조회수: <?php echo $views -> hits;?></th>
                <th scope="col">등록일: <?php echo $views -> reg_date;?></th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th colspan="4">
                    <?php echo $views -> contents;?>
                </th>
            </tr>
        </tbody>
        <tfoot>
            <tr>
                <th colspan="4">
                    <a href="/bbs/board/lists/<?php echo $this -> uri -> segment(3); ?>/
                        page/<?php echo $this -> uri -> segment(7); ?>" class="btn btn-primary">목록 </a>
                    <a href="/bbs/board/modify/<?php echo $this -> uri -> segment(3); ?>/board_id/
                        <?php echo $this -> uri -> segment(4); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-warning"> 수정     </a>
                    <a href="/bbs/board/delete/<?php echo $this -> uri -> segment(3); ?>/board_id/
                        <?php echo $this -> uri -> segment(4); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-danger"> 삭제 </a>
                    <a href="/bbs/board/write/<?php echo $this -> uri -> segment(3); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-success">쓰기</a>                    
                </th>
            </tr>
        </tfoot>
    </table>
    
    <form class="form-horizontal" method="POST" action="" name="com_add">
        <fieldset>
            <div class="control-group">
                <label class="control-label" for="input01">댓글</label>
                <div class="controls">
                    <textarea class="input-xlarge" id="input01" name="comment_contents" rows="3"></textarea>
                    <input class="btn btn-primary" type="button" id="comment_add" value="작성" />
                    <p class="help-block"></p>
                </div>
            </div>
        </fieldset>
    </form>
    <div id="comment_area">
        <table cellspacing="0" cellpadding="0" class="table table-striped">
            <tbody>
<?php
    foreach ($comment_list as $lt) {
?>
                <tr id="row_num_<?php echo $lt->board_id; ?>">
                    <th scope="row">
                        <?php echo $lt->user_id;?>
                    </th>
                    <td><?php echo $lt->contents;?></a></td>
                    <td>
                        <time datetime="<?php echo mdate("%Y-%M-%j", human_to_unix($lt->reg_date)); ?>">
                            <?php echo $lt->reg_date;?>
                        </time>
                    </td>
                    <td>
                        <a href="#" class="comment_delete" vals='<?php echo $lt->board_id; ?>')">
                            <i class="icon-trash"></i> 삭제
                        </a>
                    </td>
                </tr>
<?php
    }
?>
            </tbody>
        </table>
    </div>
</article
cs




 다음으로는 AJAX 컨트롤러의 일부분을 수정해야 합니다. 



 * bbs/application/controllers/ajax_board.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
 
/**
 * AJAX 처리 컨트롤러
 */
 
class Ajax_board extends CI_Controller {
 
    function __construct() {
        parent::__construct();
    }
 
    /**
     * AJAX 테스트
     */
    public function test() {
        $this -> load -> view('ajax/test_v');
    }
 
    public function ajax_action() {
        echo '<meta http-equiv="Content-Type" content="test/html; charset=utf-8" />';
 
        $name = $this -> input -> post("name");
 
        echo $name . "님 반갑습니다 !";
    }
 
    public function ajax_comment_add() {
        if (@$this -> session -> userdata('logged_in'== TRUE) {
            $this -> load -> model('board_m');
            
            $table = $this -> input -> post('table', TRUE);
            $board_id = $this -> input -> post('board_id', TRUE);
            $comment_contents = $this -> input -> post('comment_contents', TRUE);
            
            if ($comment_contents != '' ){
                $write_data = array(
                    "table" => $table,
                    "board_pid" => $board_id,
                    "subject" => '',
                    "contents" => $comment_contents,
                    "user_id" => $this -> session -> userdata('username')
                );
                
                $result = $this -> board_m -> insert_comment($write_data);
                
                if ($result) {
                    $sql = "SELECT * FROM "$table ." WHERE board_pid = '"$board_id . "' ORDER BY board_id DESC";
                    $query = $this -> db -> query($sql);
?>
<table cellspacing="0" cellpadding="0" class="table table-striped">
    <tbody>
<?php
                    foreach ($query -> result() as $lt) {
?>
        <tr>
            <th scope="row">
                <?php echo $lt -> user_id;?>
            </th>
            <td><?php echo $lt -> contents;?></td>
            <td>
                <time datetime="<?php echo mdate("%Y-%M-%j", human_to_unix($lt->reg_date));?>">
                    <?php echo $lt -> reg_date;?>
                </time>
            </td>
            <td>
                <a href="#" class="comment_delete" vals="<?php echo $lt->board_id; ?>">
                    <i class="icon-trash"></i>삭제
                </a>
            </td>
        </tr>
<?php
                    }
?>
    </tbody>
</table>
<?php
                } else {
                    // 글 실패시
                    echo "2000";
                }
            } else {
                // 글 내용이 없을 경우
                echo "1000";
            }
        } else {
            // 로그인 필요 에러
            echo "9000";
        }
    }
 
    public function ajax_comment_delete() {
        if ( @$this -> session -> userdata('logged_in'== TRUE) {
            $this -> load -> model('board_m');
            
            $table = $this -> input -> post("table", TRUE);
            $board_id = $this -> input -> post("board_id", TRUE);
            
            $writer_id = $this -> board_m -> writer_check2($table$board_id);
            
            if ( $writer_id -> user_id != $this -> session -> userdata('username')) {
                echo "8000";
            } else {
                $result = $this -> board_m -> delete_content($table$board_id);
                
                if ($result) {
                    echo $board_id;
                } else {
                    echo "2000"// 글 실패
                }
            }
        } else {
            echo "9000"// 로그인 에러
        }
    }
 
}
 
cs









 


 댓글 쓰기, 삭제를 jQuery의 $.ajax를 이용해 구현했습니다. 뷰에서 Ajax 요청 -> 서버에서 데이터 처리, 가공 후 반환 -> 뷰에 응답 데이터 적용하는 패턴을 익혀두시기 바랍니다. 대부분의 AJAX 액션에서 사용되는 패턴입니다. 





* 이 포스트는 서적 '만들면서 배우는 CodeIgniter 프레임워크'를 참고하여 작성하였습니다.

다른 카테고리의 글 목록

Web/CodeIgniter 카테고리의 포스트를 톺아봅니다
조회수 확인

8장에서는 AJAX(Asynchronous Javascript And XML) 방식을 이용해 게시판의 댓글을 구현해보곘습니다.


jQuery 같은 자바스크립트 프레임워크를 사용하지 않고 XMLHttpRequest 를 이용해 구현합니다.


들어가기 전에 AJAX에 대해 조금 알아보면 기존 방식의 사이트는 다음과 같습니다.

 - 웹 브라우저가 웹 서버에 요청을 전송

 - 웹 서버는 JSP/PHP/ASP 등 서버측 애플리케이션을 이용해 사용자의 요청을 처리한 뒤, 처리 결과를 HTML로 웹 브라우저에 전송

 - 웹 브라우저는 응답으로 받은 HTML을 화면에 출력


AJAX 방식은 아래와 같습니다.

 - 사용자가 마우스 클릭 같은 이벤트를 발생시키면 자바스크립트는 DOM을 이용해서 필요한 정보를 구한 뒤, XMLHttpRequest 객체를 통해 웹 서버에 요청을 전달

 - 웹 서버는 요청에 대해 처리한 뒤 그 결과를 XML이나 JSON, HTML 또는 단순 텍스트로 생성해서 XMLHttpRequest에 전송

 - 서버로부터 응답이 도착하면 XMLHttpRequest 객체는 자바스크립트에 도착 사실을 알리고 자바스크립트는 응답 데이터와 DOM을 조작하여 사용자 화면에 반영


AJAX는 웹 브라우저가 아닌 XMLHttpRequest 객체가 웹 서버와 통신을 하며 페이지 이동 없이(화면 깜빡임 없이) 결과가 화면에 반영됩니다.





8.1 XMLHttpRequest 구현하기

 CodeIgniter에 적용하기 전에 매번 반복되는 XMLHttpRequest 객체를 사용하여 코드를 작성하기 번거롭기 때문에 해당 부분을 httpRequest.js 파일로 만들어 사용하겠습니다.


 bbs/include 디렉터리 내부에 js 폴더를 생성한 뒤, 그 안에 httpRequest.js 파일을 생성하여 작성하세요.


 * bbs/include/js/httpRequest.js


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
function getXMLHttpRequest() {
    if (window.ActivXObject) {
        try {
            return new ActiveXObject("Msxml2.XMLHTTP");
        } catch(e) {
            try {
                return ActiveXObject("Microsoft.XMLHTTP");
            } catch(e1) {
                return null;
            }
        }
    } else if (window.XMLHttpRequest) {
        return new XMLHttpRequest();
    } else {
        return null;
    }
}
 
var httpRequest = null;
 
function sendRequest(url, params, callback, method) {
    httpRequest = getXMLHttpRequest();
    var httpMethod = method ? method : 'GET';
 
    if (httpMethod != 'GET' && httpMethod != 'POST') {
        httpMethod = 'GET';
    }
 
    var httpParams = (params == null || params == '') ? null : params;
    var httpUrl = url;
 
    if (httpMethod == 'GET' && httpParams != null) {
        httpUrl = httpUrl + "?" + httpParams;
    }
 
    httpRequest.open(httpMethod, httpUrl, true);
    httpRequest.setRequestHeader('Content-Type''application/x-www-form-urlencoded');
    httpRequest.onreadystatechange = callback;
    httpRequest.send(httpMethod == 'POST' ? httpParams : null);
}
 
cs








8.2 댓글 쓰기 AJAX로 구현하기

 댓글 쓰기 AJAX 처리에서 컨트롤러는 데이터를 입력하는 역할만 하고 뷰에서 화면 제어 등 많은 부분이 중요하기 때문에 뷰를 먼저 만듭니다.


 * bbs/application/views/board/view_v.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
 
<script type="text/javascript" src="/bbs/include/js/httpRequest.js"></script>
<script>
    $(document).ready(function() {
        $("#search_btn").click(function() {
            if ($("#q").val() == '') {
                alert("검색어를 입력하세요!");
                return false;
            } else {
                var act = "/bbs/board/lists/ci_board/q/" + $("#q").val() + "/page/1";
                $("#bd_search").attr('action', act).submit();
            }
        });
    });
 
    function board_search_enter(form) {
        var keycode = window.event.keyCode;
        if (keycode == 13)
            $("#search_btn").click();
    }
    
    function comment_add() {
        var csrf_token = getCookie('csrf_cookie_name');
        var name = "comment_contents=" + encodeURIComponent(document.com_add.comment_contents.value) + 
            "&csrf_test_name=" + csrf_token + "&table=<?php echo $this->uri->segment(3); ?>&board_id=<?php echo $this->uri->segment(5); ?>";
        sendRequest("/bbs/ajax_board/ajax_comment_add"name, add_action, "POST");
    }
    
    function add_action() {
        if ( httpRequest.readyState == 4) {
            if ( httpRequest.status == 200) {
                if ( httpRequest.responseText == 1000) {
                    alert("댓글의 내용을 입력하세요.");
                } else if ( httpRequest.responseText == 2000) {
                    alert("다시 입력하세요.");
                } else if ( httpRequest.responseText == 9000) {
                    alert("로그인하여야 합니다.");
                } else {
                    var contents = document.getElementById("comment_area");
                    contents.innerHTML = httpRequest.responseText;
                    
                    var textareas = document.getElementById("input01");
                    textareas.value = '';
                }
            }
        }
    }
    
    function getCookie(name) {
        var nameOfCookie = name + "=";
        var x = 0;
        
        while ( x <= document.cookie.length) {
            var y = (x + nameOfCookie.length);
            
            if (document.cookie.substring(x, y) == nameOfCookie) {
                if (( endOfCookie = document.cookie.indexOf(";", y)) == -1
                    endOfCookie = document.cookie.length;
                
                return unescape(document.cookie.substring(y, endOfCookie));
            }
            
            x = document.cookie.indexOf(" ", x) + 1;
            
            if ( x == 0
            
            break;
        }
    }
</script>
<article id="board_area">
    <header>
        <h1></h1>
    </header>
    <table cellspacing="0" cellpadding="0" class="table table-striped">
        <thead>
            <tr>
                <th scope="col"><?php echo $views -> subject;?></th>
                <th scope="col">이름: <?php echo $views -> user_name;?></th>
                <th scope="col">조회수: <?php echo $views -> hits;?></th>
                <th scope="col">등록일: <?php echo $views -> reg_date;?></th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th colspan="4">
                    <?php echo $views -> contents;?>
                </th>
            </tr>
        </tbody>
        <tfoot>
            <tr>
                <th colspan="4">
                    <a href="/bbs/board/lists/<?php echo $this -> uri -> segment(3); ?>/
                        page/<?php echo $this -> uri -> segment(7); ?>" class="btn btn-primary">목록 </a>
                    <a href="/bbs/board/modify/<?php echo $this -> uri -> segment(3); ?>/board_id/
                        <?php echo $this -> uri -> segment(4); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-warning"> 수정     </a>
                    <a href="/bbs/board/delete/<?php echo $this -> uri -> segment(3); ?>/board_id/
                        <?php echo $this -> uri -> segment(4); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-danger"> 삭제 </a>
                    <a href="/bbs/board/write/<?php echo $this -> uri -> segment(3); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-success">쓰기</a>                    
                </th>
            </tr>
        </tfoot>
    </table>
    
    <form class="form-horizontal" method="POST" action="" name="com_add">
        <fieldset>
            <div class="control-group">
                <label class="control-label" for="input01">댓글</label>
                <div class="controls">
                    <textarea class="input-xlarge" id="input01" name="comment_contents" rows="3"></textarea>
                    <input class="btn btn-primary" type="button" onclick="comment_add()" value="작성" />
                    <p class="help-block"></p>
                </div>
            </div>
        </fieldset>
    </form>
    <div id="comment_area">
        <table cellspacing="0" cellpadding="0" class="table table-striped">
            <tbody>
<?php
    foreach ($comment_list as $lt) {
?>
                <tr>
                    <th scope="row">
                        <?php echo $lt->user_id;?>
                    </th>
                    <td><?php echo $lt->contents;?></td>
                    <td>
                        <time datetime="<?php echo mdate("%Y-%M-%j", human_to_unix($lt->reg_date)); ?>">
                            <?php echo $lt->reg_date;?>
                        </time>
                    </td>
                </tr>
<?php
    }
?>
            </tbody>
        </table>
    </div>
</article
cs



 Line 2: XMLHttpRequest 객체를 사용하기 위해 httpRequest.js 를 로드합니다.

 Line 22: 데이터를 XMLHttpRequest 객체를 이용해 어떤 주소에 전달하고 가공된 데이터를 받아 특정 함수를 실행합니다.

 Line 24: XMLHttpRequest 객체에 전달할 데이터를 만듭니다. 데이터는 쿼리스트링 방식으로 만듭니다. 게시글 입력을 위해 테이블 명, 원글 번호가 추가로 필요합니다.

 






 AJAX 컨트롤러에서는 POST 전송된 댓글 내용, 테이블 명, 테이블 번호를 이용해 데이터베이스에 입력하고, 입력된 결과를 HTML 형태로 만들어서 화면에 출력합니다.


 * bbs/application/controllers/ajax_board.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
 
/**
 * AJAX 처리 컨트롤러
 */
 
class Ajax_board extends CI_Controller {
 
    function __construct() {
        parent::__construct();
    }
 
    /**
     * AJAX 테스트
     */
    public function test() {
        $this -> load -> view('ajax/test_v');
    }
 
    public function ajax_action() {
        echo '<meta http-equiv="Content-Type" content="test/html; charset=utf-8" />';
 
        $name = $this -> input -> post("name");
 
        echo $name . "님 반갑습니다 !";
    }
 
    public function ajax_comment_add() {
        if (@$this -> session -> userdata('logged_in'== TRUE) {
            $this -> load -> model('board_m');
            
            $table = $this -> input -> post('table', TRUE);
            $board_id = $this -> input -> post('board_id', TRUE);
            $comment_contents = $this -> input -> post('comment_contents', TRUE);
            
            if ($comment_contents != '' ){
                $write_data = array(
                    "table" => $table,
                    "board_pid" => $board_id,
                    "subject" => '',
                    "contents" => $comment_contents,
                    "user_id" => $this -> session -> userdata('username')
                );
                
                $result = $this -> board_m -> insert_comment($write_data);
                
                if ($result) {
                    $sql = "SELECT * FROM "$table ." WHERE board_pid = '"$board_id . "' ORDER BY board_id DESC";
                    $query = $this -> db -> query($sql);
?>
<table cellspacing="0" cellpadding="0" class="table table-striped">
    <tbody>
<?php
                    foreach ($query -> result() as $lt) {
?>
        <tr>
            <th scope="row">
                <?php echo $lt -> user_id;?>
            </th>
            <td><?php echo $lt -> contents;?></td>
            <td>
                <time datetime="<?php echo mdate("%Y-%M-%j", human_to_unix($lt->reg_date));?>">
                    <?php echo $lt -> reg_date;?>
                </time>
            </td>
        </tr>
<?php
                    }
?>
    </tbody>
</table>
<?php
                } else {
                    // 글 실패시
                    echo "2000";
                }
            } else {
                // 글 내용이 없을 경우
                echo "1000";
            }
        } else {
            // 로그인 필요 에러
            echo "9000";
        }
    }
 
}
 
cs



 Line 30: XMLHttpRequest 객체를 통해 전달받은 데이터를 가공하고, 댓글 리스트를 HTML 형태로 반환하는 ajax_comment_add() 함수를 작성합니다.

 Line 34: XMLHttpRequest 객체를 통해 전달받은 각 데이터를 인식하기 편한 변수명으로 바꿉니다.

 




 게시판 메인 컨트롤러인 board 컨트롤러에도 한 군데 추가해야 합니다. AJAX로 댓글을 쓸 때 비동기식으로 댓글을 화면에 표시해 주는데 그 상태에서 새로고침을 하거나 게시물 목록으로 나갔다 들어오면 댓글이 표시되지 않습니다. 이와 같은 현상을 막기위해 아래 부분을 추가, 수정합니다.



 * board.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
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  게시판 메인 컨트롤러
 */
 
class Board extends CI_Controller {
 
 
    ....
 
 
 
    /**
     * 게시물 보기
     */
    function view() {
        
        $table = $this -> uri -> segment(3);
        $board_id = $this -> uri -> segment(5);
        
        // 게시판 이름과 게시물 번호에 해당하는 게시물 가져오기
        $data['views'= $this -> board_m -> get_view($this -> uri -> segment(3), $this -> uri -> segment(4));
 
        // 게시판 이름과 세미루 번호에 해당하는 댓글 리스트 가져오기
        $data['comment_list'= $this -> board_m -> get_comment($table$board_id);
 
        // view 호출
        $this -> load -> view('board/view_v'$data);
    }
 
   
    ....
 
}
 
cs




 






 댓글 입력하는 모델은 게시물 입력 모델 함수와 거의 같습니다.



 * board_m.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
 
/**
 * 공통 게시판 모델
 */
 
class Board_m extends CI_Model {
    function __construct() {
        parent::__construct();
    }
 
    function get_list($table = 'ci_board'$type = ''$offset = ''$limit = ''$search_word = '') {
 
        $sword = '';
 
        if ($search_word != '') {
            // 검색어 있을 경우
            $sword = ' WHERE subject like "%' . $search_word . '%" or contents like "%' . $search_word . '%" ';
        }
 
        $limit_query = '';
 
        if ($limit != '' OR $offset != '') {
            // 페이징이 있을 경우 처리
            $limit_query = ' LIMIT ' . $offset . ', ' . $limit;
        }
 
        $sql = "SELECT * FROM " . $table . $sword . " ORDER BY board_id DESC " . $limit_query;
        $query = $this -> db -> query($sql);
 
        if ($type == 'count') {
            $result = $query -> num_rows();
        } else {
            $result = $query -> result();
        }
 
        return $result;
    }
 
    /**
     * 게시물 상세보기 가져오기
     *
     * @param string $table 게시판 테이블
     * @param string $id 게시물 번호
     * @return array
     */
    function get_view($table$id) {
        // 조횟수 증가
        $sql0 = "UPDATE " . $table . " SET hits = hits + 1 WHERE board_id='" . $id . "'";
        $this -> db -> query($sql0);
 
        $sql = "SELECT * FROM " . $table . " WHERE board_id = '" . $id . "'";
        $query = $this -> db -> query($sql);
 
        // 게시물 내용 반환
        $result = $query -> row();
 
        return $result;
 
    }
    
    /**
     * 게시물 입력
     * 
     * @param array $arrays 테이블 명, 게시물 제목, 게시물 내용 1차 배열
     * @return boolean 입력 성공여부
     */
    function insert_board($arrays) {
        $insert_array = array(
            'board_pid' => 0,
            'user_id' => $arrays['userid'],
            'user_name' => 'palpit',
            'subject' => $arrays['subject'],
            'contents' => $arrays['contents'],
            'reg_date' => date("Y-m-d H:i:s")
        );
        
        $result = $this->db->insert($arrays['table'], $insert_array);
        
        return $result;
    }
    
    /**
     * 게시물 수정
     * 
     * @param array $arrays 테이블 명, 게시물 번호, 게시물 제목, 게시물 내용
     * @return boolean 성공 여부
     */
    function modify_board($arrays) {
        $modify_array = array(
            'subject' => $arrays['subject'],
            'contents' => $arrays['contents']
        );
        
        $where = array(
            'board_id' => $arrays['board_id']
        );
        
        $result = $this->db->update($arrays['table'], $modify_array$where);
        
        return $result;
    }
    
    /**
     * 게시물 삭제
     * 
     * @param string $table 테이블 명
     * @param string $no 게시물 번호
     * @return boolean 성공 여부
     * 
     */
    function delete_content($table$no) {
        $delete_array = array(
            'board_id' => $no
        );
        
        $result = $this->db->delete($table$delete_array);
        
        return $result;
    }
    
    
    /**
     * 게시물 작성자 아이디 반환
     * 
     * @return string 작성자 아이디
     */
    function writer_check() {
        $table = $this->uri->segment(3);
        $board_id = $this->uri->segment(5);
        
        $sql = "SELECT user_id FROM ".$table." WHERE board_id = '".$board_id."'";
        $query = $this->db->query($sql);
        
        return $query->row();
        
    }
    
    /**
     * 댓글 입력
     * 
     * @param array $arrays 테이블 명, 게시물 제목, 게시물 내용, 아이디 
     * @return boolean 성공 여부
     */
    function insert_comment($arrays) {
        $insert_array = array
            'board_pid' => $arrays['board_pid'],
            'user_id' => $arrays['user_id'],
            'user_name' => $arrays['user_id'],
            'subject' => $arrays['subject'],
            'contents' => $arrays['contents'],
            'reg_date' => date('Y-m-d H:i:s')
        );
        
        $this -> db -> insert($arrays['table'], $insert_array);
        
        $board_id = $this -> db -> insert_id();
        
        return $board_id;
    }
    
    /**
     * 댓글 리스트 가져오기
     * 
     * @param string $table 테이블 
     * @param string $id 게시물 번호
     * @return array
     * 
     */
    function get_comment($table$id) {
        $sql = "SELECT * FROM "$table . " WHERE board_pid = '"$id . "' ORDER BY board_id DESC";
        $query = $this -> db -> query($sql);
        
        $result = $query -> result();
        
        return $result;
    }
    
}
 
cs










8.3 댓글 삭제 AJAX로 구현하기

 게시물 삭제도 뷰를 먼저 보겠습니다. 작동 순서는 삭제 버튼 클릭 -> AJAX 로 삭제할 테이블, 게시물 번호 전송 -> AJAX 컨트롤러에서 처리 후 결과 전송 -> 자바스크립트에서 후 처리입니다.









 * view_v.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
 
<script type="text/javascript" src="/bbs/include/js/httpRequest.js"></script>
<script>
    $(document).ready(function() {
        $("#search_btn").click(function() {
            if ($("#q").val() == '') {
                alert("검색어를 입력하세요!");
                return false;
            } else {
                var act = "/bbs/board/lists/ci_board/q/" + $("#q").val() + "/page/1";
                $("#bd_search").attr('action', act).submit();
            }
        });
    });
 
    function board_search_enter(form) {
        var keycode = window.event.keyCode;
        if (keycode == 13)
            $("#search_btn").click();
    }
    
    function comment_add() {
        var csrf_token = getCookie('csrf_cookie_name');
        var name = "comment_contents=" + encodeURIComponent(document.com_add.comment_contents.value) + 
            "&csrf_test_name=" + csrf_token + "&table=<?php echo $this->uri->segment(3); ?>&board_id=<?php echo $this->uri->segment(4); ?>";
        sendRequest("/bbs/ajax_board/ajax_comment_add"name, add_action, "POST");
    }
    
    function add_action() {
        if ( httpRequest.readyState == 4) {
            if ( httpRequest.status == 200) {
                if ( httpRequest.responseText == 1000) {
                    alert("댓글의 내용을 입력하세요.");
                } else if ( httpRequest.responseText == 2000) {
                    alert("다시 입력하세요.");
                } else if ( httpRequest.responseText == 9000) {
                    alert("로그인하여야 합니다.");
                } else {
                    var contents = document.getElementById("comment_area");
                    contents.innerHTML = httpRequest.responseText;
                    
                    var textareas = document.getElementById("input01");
                    textareas.value = '';
                }
            }
        }
    }
    
    function comment_delete(no) {
        var csrf_token = getCookie('csrf_cookie_name');
        var name = "csrf_test_name=" + csrf_token + "&table=<?php echo $this->uri->segment(3);?>&board_id=" + no;
 
        sendRequest("/bbs/ajax_board/ajax_comment_delete"name, delete_action, "POST");
    }
    
    function delete_action() {
        if (httpRequest.readyState == 4) {
            if (httpRequest.status == 200) {
                if (httpRequest.responseText == 9000) {
                    alert('로그인해야 합니다');
                } else if (httpRequest.responseText == 8000) {
                    alert('본인의 댓글만 삭제할 수 있습니다.');
                } else if (httpRequest.responseText == 2000) {
                    alert('다시 삭제하세요.');
                } else {
                    var no = httpRequest.responseText;
                    var delete_tr = document.getElementById("row_num_" + no);
                    
                    delete_tr.parentNode.removeChild(delete_tr);
                    alert('삭제되었습니다');
                    
                }
            }
        }
    }
    
    function getCookie(name) {
        var nameOfCookie = name + "=";
        var x = 0;
        
        while ( x <= document.cookie.length) {
            var y = (x + nameOfCookie.length);
            
            if (document.cookie.substring(x, y) == nameOfCookie) {
                if (( endOfCookie = document.cookie.indexOf(";", y)) == -1
                    endOfCookie = document.cookie.length;
                
                return unescape(document.cookie.substring(y, endOfCookie));
            }
            
            x = document.cookie.indexOf(" ", x) + 1;
            
            if ( x == 0
            
            break;
        }
    }
</script>
<article id="board_area">
    <header>
        <h1></h1>
    </header>
    <table cellspacing="0" cellpadding="0" class="table table-striped">
        <thead>
            <tr>
                <th scope="col"><?php echo $views -> subject;?></th>
                <th scope="col">이름: <?php echo $views -> user_name;?></th>
                <th scope="col">조회수: <?php echo $views -> hits;?></th>
                <th scope="col">등록일: <?php echo $views -> reg_date;?></th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th colspan="4">
                    <?php echo $views -> contents;?>
                </th>
            </tr>
        </tbody>
        <tfoot>
            <tr>
                <th colspan="4">
                    <a href="/bbs/board/lists/<?php echo $this -> uri -> segment(3); ?>/
                        page/<?php echo $this -> uri -> segment(7); ?>" class="btn btn-primary">목록 </a>
                    <a href="/bbs/board/modify/<?php echo $this -> uri -> segment(3); ?>/board_id/
                        <?php echo $this -> uri -> segment(4); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-warning"> 수정     </a>
                    <a href="/bbs/board/delete/<?php echo $this -> uri -> segment(3); ?>/board_id/
                        <?php echo $this -> uri -> segment(4); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-danger"> 삭제 </a>
                    <a href="/bbs/board/write/<?php echo $this -> uri -> segment(3); ?>/page/<?php echo $this -> uri -> segment(7); ?>"
                        class="btn btn-success">쓰기</a>                    
                </th>
            </tr>
        </tfoot>
    </table>
    
    <form class="form-horizontal" method="POST" action="" name="com_add">
        <fieldset>
            <div class="control-group">
                <label class="control-label" for="input01">댓글</label>
                <div class="controls">
                    <textarea class="input-xlarge" id="input01" name="comment_contents" rows="3"></textarea>
                    <input class="btn btn-primary" type="button" onclick="comment_add()" value="작성" />
                    <p class="help-block"></p>
                </div>
            </div>
        </fieldset>
    </form>
    <div id="comment_area">
        <table cellspacing="0" cellpadding="0" class="table table-striped">
            <tbody>
<?php
    foreach ($comment_list as $lt) {
?>
                <tr id="row_num_<?php echo $lt->board_id; ?>">
                    <th scope="row">
                        <?php echo $lt->user_id;?>
                    </th>
                    <td><?php echo $lt->contents;?></a></td>
                    <td>
                        <time datetime="<?php echo mdate("%Y-%M-%j", human_to_unix($lt->reg_date)); ?>">
                            <?php echo $lt->reg_date;?>
                        </time>
                    </td>
                    <td>
                        <a href="#" onclick="javascript:comment_delete('<?php echo $lt->board_id; ?>')">
                            <i class="icon-trash"></i> 삭제
                        </a>
                    </td>
                </tr>
<?php
    }
?>
            </tbody>
        </table>
    </div>
</article
cs





 AJAX 컨트롤러에서는 POST 전송된 테이블 명, 테이블 번호를 이용해 데이터베이스에서 해당 댓글을 삭제하고 그 결과를 번호로 화면에 출력합니다.



 * ajax_board.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
 
/**
 * AJAX 처리 컨트롤러
 */
 
class Ajax_board extends CI_Controller {
 
    function __construct() {
        parent::__construct();
    }
 
    /**
     * AJAX 테스트
     */
    public function test() {
        $this -> load -> view('ajax/test_v');
    }
 
    public function ajax_action() {
        echo '<meta http-equiv="Content-Type" content="test/html; charset=utf-8" />';
 
        $name = $this -> input -> post("name");
 
        echo $name . "님 반갑습니다 !";
    }
 
    public function ajax_comment_add() {
        if (@$this -> session -> userdata('logged_in'== TRUE) {
            $this -> load -> model('board_m');
            
            $table = $this -> input -> post('table', TRUE);
            $board_id = $this -> input -> post('board_id', TRUE);
            $comment_contents = $this -> input -> post('comment_contents', TRUE);
            
            if ($comment_contents != '' ){
                $write_data = array(
                    "table" => $table,
                    "board_pid" => $board_id,
                    "subject" => '',
                    "contents" => $comment_contents,
                    "user_id" => $this -> session -> userdata('username')
                );
                
                $result = $this -> board_m -> insert_comment($write_data);
                
                if ($result) {
                    $sql = "SELECT * FROM "$table ." WHERE board_pid = '"$board_id . "' ORDER BY board_id DESC";
                    $query = $this -> db -> query($sql);
?>
<table cellspacing="0" cellpadding="0" class="table table-striped">
    <tbody>
<?php
                    foreach ($query -> result() as $lt) {
?>
        <tr>
            <th scope="row">
                <?php echo $lt -> user_id;?>
            </th>
            <td><?php echo $lt -> contents;?></td>
            <td>
                <time datetime="<?php echo mdate("%Y-%M-%j", human_to_unix($lt->reg_date));?>">
                    <?php echo $lt -> reg_date;?>
                </time>
            </td>
        </tr>
<?php
                    }
?>
    </tbody>
</table>
<?php
                } else {
                    // 글 실패시
                    echo "2000";
                }
            } else {
                // 글 내용이 없을 경우
                echo "1000";
            }
        } else {
            // 로그인 필요 에러
            echo "9000";
        }
    }
 
    public function ajax_comment_delete() {
        if ( @$this -> session -> userdata('logged_in'== TRUE) {
            $this -> load -> model('board_m');
            
            $table = $this -> input -> post("table", TRUE);
            $board_id = $this -> input -> post("board_id", TRUE);
            
            $writer_id = $this -> board_m -> writer_check2($table$board_id);
            
            if ( $writer_id -> user_id != $this -> session -> userdata('username')) {
                echo "8000";
            } else {
                $result = $this -> board_m -> delete_content($table$board_id);
                
                if ($result) {
                    echo $board_id;
                } else {
                    echo "2000"// 글 실패
                }
            }
        } else {
            echo "9000"// 로그인 에러
        }
    }
 
}
 
cs











 XMLHttpRequest 객체를 이용해 AJAX로 처리하는 방법을 알아봤습니다.


 데이터를 주고받고 DOM 객체를 이용해 댓글 내용을 삽입하거나 삭제했습니다. 


 다음 장에서는 보다 손쉽게 처리할 수 있는 jQuery 프레임워크를 통해 댓글 기능을 보완해보도록 하겠습니다.





* 이 포스트는 서적 '만들면서 배우는 CodeIgniter 프레임워크'를 참고하여 작성하였습니다



다른 카테고리의 글 목록

Web/CodeIgniter 카테고리의 포스트를 톺아봅니다
조회수 확인

7장에서는 로그인에 관한 처리를 해보겠습니다. 거의 모든 사이트에서 중요한 부분이 회원가입 후의 사용자 인증 부분입니다.


사이트의 첫 시작이라고 해도 과언이 아닙니다. 사이트 개발 시 제일 먼저 하는 작업이 가입, 로그인, 회원 관리입니다.






7.1 세션 구조

 CodeIgniter의 세션 라이브러리는 PHP의 세션과 작동 형태가 조금 다릅니다. 세션이 생성되는 것은 동일한데 실제 사용자 데이터는 쿠키에 담깁니다.



 






 이렇게 복잡하게 구성된 이유는 사용자 데이터 보안이 강화된 데이터베이스 세션을 구현하기 위해서입니다.


 CodeIgniter의 데이터베이스 세션은 위 그림의 1, 2번 절차는 동일하고 3번의 사용자 데이터가 저장되는 곳이 데이터베이스로 바뀝니다. 그렇게 되면 해커나 사용자가 PC의 쿠키를 볼수 없기 때문에 보안 측면이 강화됩니다. 


 일반적인 경우 쿠키를 암호화하여 저장하지 않아서 쿠키 파일을 열어보면 사용자 아이디, 이름, 전화번호 등을 볼 수 있습니다.


 무조건 데이터베이스 세션을 사용할 필요는 없지만 보안 강화를 위해 서버 자원을 조금 더 사용하더라도 사용하는 것이 좋습니다.




 먼저, 데이터베이스 세션을 사용하기 위해 설정을 바꿔줍니다.


 * bbs/application/config/config.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
<?php
/*
|--------------------------------------------------------------------------
| Session Variables
|--------------------------------------------------------------------------
|
| 'sess_cookie_name'        = the name you want for the cookie
| 'sess_expiration'            = the number of SECONDS you want the session to last.
|   by default sessions last 7200 seconds (two hours).  Set to zero for no expiration.
| 'sess_expire_on_close'    = Whether to cause the session to expire automatically
|   when the browser window is closed
| 'sess_encrypt_cookie'        = Whether to encrypt the cookie
| 'sess_use_database'        = Whether to save the session data to a database
| 'sess_table_name'            = The name of the session database table
| 'sess_match_ip'            = Whether to match the user's IP address when reading the session data
| 'sess_match_useragent'    = Whether to match the User Agent when reading the session data
| 'sess_time_to_update'        = how many seconds between CI refreshing Session Information
|
*/
$config['sess_cookie_name']        = 'ci_session';
$config['sess_expiration']        = 7200;
$config['sess_expire_on_close']    = FALSE;
$config['sess_encrypt_cookie']    = FALSE;
$config['sess_use_database']    = TRUE;
$config['sess_table_name']        = 'ci_sessions';
$config['sess_match_ip']        = FALSE;
$config['sess_match_useragent']    = TRUE;
$config['sess_time_to_update']    = 300;
 
 
cs




 config.php의 Session 부분을 찾아서 아래와 같이 수정해 줍니다.


 다음으로 Encrypt key 설정이 필요합니다. config.php 에서 아래 부분을 찾아서 수정합니다.


1
2
3
4
5
6
7
8
9
10
11
12
<?
/*
|--------------------------------------------------------------------------
| Encryption Key
|--------------------------------------------------------------------------
|
| If you use the Encryption class or the Session class you
| MUST set an encryption key.  See the user guide for info.
|
*/
$config['encryption_key'= 'bbs_system';
 
cs






 


 다음은 MySQL ci_book DB에 ci_sessions 테이블을 생성해야 합니다. MySQL 콘솔에 접속하여 테이블을 생성합니다.






 ci_sessions 테이블 생성


 use ci_book;


 CREATE TABLE IF NOT EXISTS ci_sessions (

session_id varchar(40) DEFAULT 0 NOT NULL PRIMARY KEY,

ip_address varchar(40) DEFAULT 0 NOT NULL,

user_agent varchar(120) NOT NULL,

last_activity int(10) unsigned DEFAULT 0 NOT NULL,

user_data text NOT NULL,

KEY last_activity_idx (last_activity)

 );







 그리고 세션과 데이터베이스를 계속 이용해 프로그램을 할 것이라 이 라이브러리를 자동 로드하도록 하겠습니다.



 * bbs/application/config/autoload.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
 
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/*
| -------------------------------------------------------------------
| AUTO-LOADER
| -------------------------------------------------------------------
| This file specifies which systems should be loaded by default.
|
| In order to keep the framework as light-weight as possible only the
| absolute minimal resources are loaded by default. For example,
| the database is not connected to automatically since no assumption
| is made regarding whether you intend to use it.  This file lets
| you globally define which systems you would like loaded with every
| request.
|
| -------------------------------------------------------------------
| Instructions
| -------------------------------------------------------------------
|
| These are the things you can load automatically:
|
| 1. Packages
| 2. Libraries
| 3. Helper files
| 4. Custom config files
| 5. Language files
| 6. Models
|
*/
 
/*
| -------------------------------------------------------------------
|  Auto-load Packges
| -------------------------------------------------------------------
| Prototype:
|
|  $autoload['packages'] = array(APPPATH.'third_party', '/usr/local/shared');
|
*/
 
$autoload['packages'= array();
 
 
/*
| -------------------------------------------------------------------
|  Auto-load Libraries
| -------------------------------------------------------------------
| These are the classes located in the system/libraries folder
| or in your application/libraries folder.
|
| Prototype:
|
|    $autoload['libraries'] = array('database', 'session', 'xmlrpc');
*/
 
$autoload['libraries'= array('database''session');
 
 
/*
| -------------------------------------------------------------------
|  Auto-load Helper Files
| -------------------------------------------------------------------
| Prototype:
|
|    $autoload['helper'] = array('url', 'file');
*/
 
$autoload['helper'= array();
 
 
/*
| -------------------------------------------------------------------
|  Auto-load Config files
| -------------------------------------------------------------------
| Prototype:
|
|    $autoload['config'] = array('config1', 'config2');
|
| NOTE: This item is intended for use ONLY if you have created custom
| config files.  Otherwise, leave it blank.
|
*/
 
$autoload['config'= array();
 
 
/*
| -------------------------------------------------------------------
|  Auto-load Language files
| -------------------------------------------------------------------
| Prototype:
|
|    $autoload['language'] = array('lang1', 'lang2');
|
| NOTE: Do not include the "_lang" part of your file.  For example
| "codeigniter_lang.php" would be referenced as array('codeigniter');
|
*/
 
$autoload['language'= array();
 
 
/*
| -------------------------------------------------------------------
|  Auto-load Models
| -------------------------------------------------------------------
| Prototype:
|
|    $autoload['model'] = array('model1', 'model2');
|
*/
 
$autoload['model'= array();
 
 
/* End of file autoload.php */
/* Location: ./application/config/autoload.php */
cs




 Line 56 부분에 database와 session 라이브러리를 자동으로 로드하도록 설정하였습니다.


 다음 절부터 게시판 글쓰기 할 때 로그인한 사용자만 글을 쓸 수 있도록 하겠습니다.









7.2 로그인

 5.4절에서 users 테이블을 만들고 사용자 1명을 입력했습니다. 그 데이터를 이용해 로그인을 구현하겠습니다.


 로그인 절차는 아래와 같습니다.

  - 1. 로그인 페이지에서 아이디, 비밀번호를 입력 후 폼을 전송

  - 2. 로그인 컨트롤러에서 전송받은 아이디, 비밀번호와 매치되는 데이터가 있는지 검증

  - 3. 검증된 아이디가 있다면 아이디, 이메일 등 개인정보를 넣어서 세션을 생성

  - 4. 이후 사용자 인증이 필요한 페이지에서 세션으로 인증 여부를 체크하여 실행


 로그인된 이후에는 세션에 사용자 정보가 있어서 그 정보를 가지고 로그인 여부를 체크합니다. 로그인 컨트롤러부터 만들어 보겠습니다.









 * bbs/application/controllers/auth.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
 
/**
 * 사용자 인증 컨트롤러
 */
 
class Auth extends CI_Controller {
 
    function __construct() {
        parent::__construct();
        $this -> load -> model('auth_m');
        $this -> load -> helper('form');
    }
 
    public function index() {
        $this -> login();
    }
 
    public function _remap($method) {
        $this -> load -> view('header_v');
 
        if (method_exists($this$method)) {
            $this -> {"{$method}"}();
        }
 
        $this -> load -> view('footer_v');
    }
 
    /**
     * 로그인 처리
     */
    public function login() {
        $this -> load -> library('form_validation');
 
        $this -> load -> helper('alert');
 
        $this -> form_validation -> set_rules('username''아이디''required|alpha_numeric');
        $this -> form_validation -> set_rules('password''비밀번호''required');
 
        echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
 
        if ($this -> form_validation -> run() == TRUE) {
            $auth_data = array(
                'username' => $this -> input -> post('username', TRUE),
                'password' => $this -> input -> post('password', TRUE)
            );
            
            $result = $this -> auth_m -> login($auth_data);
            
            if ($result) {
                $newdata = array(
                    'username' => $result -> username,
                    'email' => $result -> email,
                    'logged_in' => TRUE
                );
                
                $this -> session -> set_userdata($newdata);
                
                alert('로그인 되었습니다.''/bbs/board/lists/ci_board/page/1');
                exit;
            } else {
                alert('아이디나 비밀번호를 확인해 주세요.''/bbs/board/lists/ci_board/page/1');
                exit;
            }
        } else {
            $this -> load -> view('auth/login_v');
        }
    }
 
    public function logout() {
        $this -> load -> helper('alert');
        
        $this -> session -> sess_destroy();
        
        echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
        alert('로그아웃 되었습니다.''/bbs/board/lists/ci_board/page/1');
        exit;
        
    }
 
}
 
cs




 Line 53: 아이디, 비밀번호가 맞는 경우의 처리이며 세션을 생성하기 위해 아이디와 이메일, 로그인 여부를 배열로 만듭니다.

 Line 60: 위에서 만든 배열을 가지고 세션을 생성합니다.



 

 다음은 모델으로, 아이디와 비밀번호를 전송하여 데이터베이스의 데이터와 일치하면 세션을 생성하는 간단한 구조입니다.


 로그인 후의 세션 데이터를 가져오는 부분은 뷰에서 설명하겠습니다.



 * bbs/application/models/auth_m.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
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
 
Class Auth_m extends CI_Model {
    function __construct() {
        parent::__construct();
    }
 
    /**
     * 아이디 비밀번호 체크
     *
     * @param array $auth 폼 전송받은 아이디, 비밀번호
     * @return array
     */
    function login($auth) {
        $sql = "SELECT username, email FROM users WHERE username = '" . $auth['username'] . "' AND password = '" . $auth['password'] . "' ";
 
        $query = $this -> db -> query($sql);
 
        if ($query -> num_rows() > 0) {
            return $query -> row();
        } else {
            return FALSE;
        }
    }
 
}
 
cs









 뷰는 로그인 폼 페이지와 헤더 페이지를 작업합니다. 헤더 페이지에는 로그인 여부에 따라 로그인, 로그아웃 버튼을 표시하도록 수정합니다.



 * header_v.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
 
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
        <title>CodeIgniter</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <link type="text/css" rel='stylesheet' href="/bbs/include/css/bootstrap.css" />
    </head>
    <body>
        <div id="main">
            <header id="header" data-role="header" data-position="fixed">
                <blockquote>
                    <p>
                        만들면서 배우는 CodeIgniter
                    </p>
                    <small>실행 예제</small>
                    <p>
<?php
    if ( @$this -> session -> userdata('logged_in'== TRUE) {
?>
<?php echo $this -> session -> userdata('username');?> 님 환영합니다. <a href="/bbs/auth/logout" class="btn">로그아웃</a>
<?php
    } else {
?>
<a href="/bbs/auth/login" class="btn btn-primary"> 로그인 </a>
<?php
    }
?>
                    </p>
                </blockquote>
            </header>
            <nav id="gnb">
                <ul>
                    <li>
                        <a rel="external" href="/bbs/<?php echo $this -> uri -> segment(1); ?>/lists/<?php echo $this -> uri -> segment(3); ?>"> 게시판 프로젝트 </a>
                    </li>
                </ul>
            </nav>
 
cs




 


 헤더에 로그인 여부에 따라 처리했으면 로그인 폼 페이지를 만듭니다.


 * bbs/application/views/auth/login_v.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
 
<article id="board_area">
    <header><h1></h1></header>
<?php
    $attributes = array(
        'class' => 'form-horizontal',
        'id' => 'auth_login'
    );
    echo form_open('/auth/login'$attributes);
?>
    <fieldset>
        <legend>로그인</legend>
        <div class="control-group">
            <label class="control-label" for="input1">아이디</label>
            <div class="controls">
                <input type="text" class="input-xlarge" id="input1" name="username"
                    value="<?php echo set_value('username'); ?>" />
                <p class="help-block"></p>
            </div>
            <label class="control-label" for="input2">비밀번호</label>
            <div class="controls">
                <input type="password" class="input-xlarge" id="input2" name="password"
                    value="<?php echo set_value('password'); ?>" />
                <p class="help-block"></p>
            </div>
            <div class="controls">
                <p class="help-block"><?php echo validation_errors();?></p>
            </div>
            
            <div class="form_actions">
                <button type="submit" class="btn btn-primary">확인</button>
                <button class="btn" onclick="document.location.reload()">취소</button>
            </div>
        </div>
    </fieldset>
</article>
 
cs




 위와 같이 작성하고 확인을 하기위해 웹 페이지에 접속합니다.



 초기 화면에서 로그인 버튼을 클릭하여 로그인 뷰(login_v.php)로 넘어갑니다.




















 로그인 뷰에서 아이디와 비밀번호를 입력한 뒤 확인 버튼을 클릭합니다.
























 로그인 후, 세션을 통하여 로그인된 정보가 상단에 비치되는 것을 확인 할 수 있습니다.









 


 



 로그인에 성공하면 데이터베이스의 ci_sessions 테이블에 아래와 같이 데이터가 입력됩니다.













7.3 로그아웃

 로그아웃은 모델과 뷰가 필요없고 컨트롤러에서 세션 삭제하는 소스로 되어있습니다. 

 * 위에서 작성했습니다.








7.4 게시판 소스에 사용자 인증 적용하기

 이번 절에서는 board 컨트롤러의 write() 함수와 modify() 함수, delete() 함수에 사용자 인증을 적용시켜 보겠습니다.


 로그인 여부를 체크하여 로그인되어 있지 않으면 로그인 페이지로 이동시키도록 하겠습니다.


 write() 함수는 로그인 여부만 체크하면 되지만 modify() 함수와 delete() 함수는 본인이 작성한 글만 수정, 삭제할 수 있기에 본인 여부도 확인합니다.



 

 7.4.1 게시물 쓰기에 사용자 인증 적용하기

  쓰기는 로그인되어 있는지 체크하는 부분데이터베이스에 입력할 때 username을 입력하는 소스를 추가합니다.


  board.php의 write 함수 부분만 수정해주시면 됩니다.


  * bbs/application/controllers/board.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
65
66
67
68
69
70
71
72
73
74
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  게시판 메인 컨트롤러
 */
 
class Board extends CI_Controller {
 
    .......
 
 
    /**
     * 게시물 쓰기
     */
    function write() {
 
        $this -> load -> helper('alert');
        echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />';
 
        if (@$this -> session -> userdata('logged_in'== TRUE) {
            // 폼 검증 라이브러리 로드
            $this -> load -> library('form_validation');
 
            // 폼 검증할 필드와 규칙 사전 정의
            $this -> form_validation -> set_rules('subject''제목''required');
            $this -> form_validation -> set_rules('contents''내용''required');
 
            if ($this -> form_validation -> run() == TRUE) {
                // 글쓰기 POST 전송 시
 
                // 주소 중에서 page 세그먼트가 있는지 검사하기 위해 주소를 배열로 반환
                $uri_array = $this -> segment_explode($this -> uri -> uri_string());
 
                if (in_array('page'$uri_array)) {
                    $pages = urldecode($this -> url_explode($uri_array'page'));
                } else {
                    $pages = 1;
                }
 
                $write_data = array(
                    'table' => $this -> uri -> segment(3),
                    'subject' => $this -> input -> post('subject', TRUE), 
                    'contents' => $this -> input -> post('contents', TRUE),
                    'user_id' => $this -> session -> userdata('username'
                );
 
                $result = $this -> board_m -> insert_board($write_data);
 
                if ($result) {
                    alert("입력되었습니다."'/bbs/board/lists/' . $this -> uri -> segment(3) . '/page/' . $pages);
                    exit ;
                } else {
                    alert("다시 입력해주세요."'/bbs/board/lists/' . $this -> uri -> segment(3) . '/page/' . $pages);
                    exit ;
                }
            } else {
                // 쓰기 폼 view 호출
                $this -> load -> view('board/write_v');
            }
 
        } else {
            alert('로그인 후 작성하세요''/bbs/auth/login/');
            exit;
        }
 
    }
 
 
    ...
 
}
 
 
cs




  로그인하지 않은 경우에 글 쓰기를 시도하면 아래와 같은 화면이 출력됩니다.






 


  다음으로 게시판 모델도 한 군데 수정해야합니다. insert_board() 함수를 수정하시길 바랍니다.




  * board_m.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
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
 
/**
 * 공통 게시판 모델
 */
 
class Board_m extends CI_Model {
 
 
 
    ......
 
    
    /**
     * 게시물 입력
     * 
     * @param array $arrays 테이블 명, 게시물 제목, 게시물 내용 1차 배열
     * @return boolean 입력 성공여부
     */
    function insert_board($arrays) {
        $insert_array = array(
            'board_pid' => 0,
            'user_id' => $arrays['userid'],
            'user_name' => 'palpit',
            'subject' => $arrays['subject'],
            'contents' => $arrays['contents'],
            'reg_date' => date("Y-m-d H:i:s")
        );
        
        $result = $this->db->insert($arrays['table'], $insert_array);
        
        return $result;
    } 
 
 
    ....
 
 
}
 
cs








 7.4.2 게시물 수정에 사용자 인증 적용하기

  게시물 수정은 로그인 여부뿐만 아니라 본인 여부도 확인해야 합니다. 보통 사이트 관리자를 제외하고 본인이 작성한 글만 수정할 수가 있습니다. 


  컨트롤러에 소스를 추가합니다.



 * /controllers/board.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  게시판 메인 컨트롤러
 */
 
class Board extends CI_Controller {
 
 
    ....
 
 
    /**
     * 게시물 수정
     */
    function modify() {
        $this -> load -> helper('alert');
        echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
 
        $uri_array = $this -> segment_explode($this -> uri -> uri_string());
 
        if (in_array('page'$uri_array)) {
            $pages = urldecode($this -> url_explode($uri_array'page'));
        } else {
            $pages = 1;
        }
 
        if ( @$this->session->userdata['logged_in'== TRUE) {
            $write_id = $this->board_m->writer_check();
            
            if ( $write_id-> user_id != $this->session->userdata('username')) {
                alert('본인이 작성한 글이 아닙니다.''/bbs/board/view/'.$this->uri->segment(3).'/'.$this->uri->segment(5).'/page/'.$pages);
                exit;
            }
            
            $this->load->library('form_validation');
            
            // 폼 검증할 필드와 규칙 사전 정의
            $this -> form_validation -> set_rules('subject''제목''required');
            $this -> form_validation -> set_rules('contents''내용''required');
            
            if ( $this->form_validation->run() == TRUE) {
                
                
                if (!$this -> input -> post('subject', TRUE) AND !$this -> input -> post('contents', TRUE)) {
                    alert('비정상적인 접근입니다.''bbs/board/lists/' . $this -> uri -> segment(3) . '/page/' . $pages);
                    exit ;
                }
                
                $modify_data = array(
                    'table' => $this -> uri -> segment(3), 
                    'board_id' => $this -> uri -> segment(5), 
                    'subject' => $this -> input -> post('subject', TRUE), 
                    'contents' => $this -> input -> post('contents', TRUE)
                );
                
                $result = $this -> board_m -> modify_board($modify_data);
                        
                if ($result) {
                    alert('수정되었습니다.''bbs/board/lists/' . $this -> uri -> segment(3) . '/page/' . $pages);
                    exit ;
                } else {
                    alert('다시 수정해 주세요.''bbs/board/view/' . $this -> uri -> segment(3) . '/board_id/' . $this -> uri -> segment(5) . '/page/' . $pages);
                    exit ;
                }
                
            } else {
                $data['views'= $this->board_m->get_view($this->uri->segment(3), $this->uri->segment(5));
                $this->load->view('board/modify_v'$data);
            }
        } else {
            alert('로그인 후 수정하세요''/bbs/auth/login/');
            exit;
        }
    }
 
    ......
 
 
}
 
cs







  다음으로 모델에서 writer_check() 함수를 추가합니다.


  * board_m.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
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
 
/**
 * 공통 게시판 모델
 */
 
class Board_m extends CI_Model {
 
 
    ...
 
    
    /**
     * 게시물 작성자 아이디 반환
     * 
     * @return string 작성자 아이디
     */
    function writer_check() {
        $table = $this->uri->segment(3);
        $board_id = $this->uri->segment(5);
        
        $sql = "SELECT user_id FROM ".$table." WHERE board_id = '".$board_id."'";
        $query = $this->db->query($sql);
        
        return $query->row();
        
    }
}
 
cs










  임시로 만든 계정으로 로그인하여 기존의 게시물을 수정하려는 결과 아래와 같이 나옵니다.














 7.4.3 게시물 삭제에 사용자 인증 적용하기

  이번에는 게시물 삭제에 로그인 여부와 본인 인증을 추가하겠습니다.



  * board.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
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  게시판 메인 컨트롤러
 */
 
class Board extends CI_Controller {
 
 
    ....
 
 
    /**
     * 게시물 삭제
     */
 
    function delete() {
 
        $this -> load -> helper('alert');
        echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
 
        if ( @$this->session->userdata('logged_in'== TRUE) {
            $writer_id = $this->board_m->writer_check();
            
            if ( $writer_id-> user_id != $this->session->userdata('username')) {
                alert('본인이 작성한 글이 아닙니다.''/bbs/board/view/'.$this->uri->segment(3).'/'.$this->uri->segment(5).'/page/'.$pages);
                exit;
            }
            
            $return = $this->board_m->delete_content($this->uri->segment(3), $this->uri->segment(5));
            
            if ($return) {
                alert('삭제되었습니다.''bbs/board/lists/' . $this -> uri -> segment(3) . '/page/' . $this -> uri -> segment(7));
                exit ;
            } else {
                alert('삭제 실패하였습니다.''bbs/board/view/' . $this -> uri -> segment(3) . '/board_id/' . $this -> uri -> segment(5) . '/page/' . $this -> uri -> segment(7));
                exit ;
            }
            
        } else {
            alert('로그인 후 삭제하세요.''/bbs/auth/login/');
            exit;
        }
    }
 
}
 
cs










* 이 포스트는 서적 '만들면서 배우는 CodeIgniter 프레임워크'를 참고하여 작성하였습니다



다른 카테고리의 글 목록

Web/CodeIgniter 카테고리의 포스트를 톺아봅니다

[CodeIgniter] 6. 놓치기 쉬운 보안

2015.08.24 15:40 - Palpit
조회수 확인

6.1 SQL 삽입 공격(SQL Injection Attack)

 SQL 삽입 공격을 이용한 여러 가지 사례가 있지만 하나의 예를 들어 CodeIgniter에서 어떻게 막을 수 있는지 살펴 보도록 하겠습니다.


 다음과 같이 user 테이블이 있다고 가정합니다.



  id 

  user_id 

  password 

  1 

  advisor 

  1234 




 SQL 삽입 공격에 대해 취약한 사이트에 아이디 advisor' #, 비밀번호 2222로 로그인합니다.



 * 로그인 체크 쿼리

  SELECT * FROM user WHERE id = '$id' AND passwd = '$passwd';


 *SQL 삽입 공격에 의한 변조된 쿼리

  SELECT * FROM user WHERE id = 'advisor';


  

 변조된 쿼리를 보면 쿼리 중간에 #이 들어가 있습니다. 


 MySQL 에서 #은 주석처리의 의미입니다. 그래서 AND 뒤쪽 부분의 조건은 실행되지 않습니다. 결국 비밀번호를 몰라도 사이트에 로그인이 됩니다.


 CodeIgniter에서 SQL 삽입 공격을 막을 수 있는 방법에 대해 알아보겠습니다.


 



 $sql = "SELECT * FROM user WHERE id = '".$this->db->escape_str($id)." ' AND passwd = '".$this->db->escape_str($passwd)." ' ";


 $sql = "SELECT * FROM user WHERE id = ? AND passwd = ?";

 $this->db->query($sql, array($id, $passwd);

 

 $this->db->where(array('id => $this->input->post('id', TRUE), 'passwd' => $this->input->post('passwd', TRUE)));

 $this->db->get('user');




 첫 번째 방법은 $this->db->escape_str() 함수를 이용해 '(작은 따옴표)를 처리합니다.


 두 번째 방법은 CodeIgniter의 SQL 바인딩을 이용해 처리할 수 있습니다.


 세 번째 방법은 $this->input->post() 함수를 이용하는 방법입니다. CodeIgniter에서는 $_POST 형태로 폼 데이터를 받는 것이 아니라 $this->input->post() 함수를 이용합니다. 폼 데이터를 받을 때 예제처럼 두 번째 파라미터에 TRUE를 주면 SQL 삽입 공격 뿐 아니라 XSS에 대한 처리도 한꺼번에 처리합니다. 


 

 마지막 방법보다 더 간단하고 강력한 설정이 있습니다. 바로 config.php에 다음과 같이 설정하는 것입니다.



 * bbs/application/config/config.php


1
2
3
4
5
6
7
8
9
10
11
12
 
/*
|--------------------------------------------------------------------------
| Global XSS Filtering
|--------------------------------------------------------------------------
|
| Determines whether the XSS filter is always active when GET, POST or
| COOKIE data is encountered
|
*/
// $config['global_xss_filtering'] = FALSE;
$config['global_xss_filtering'] = TRUE;
cs



 

 위의 FALSE 값을 TRUE로 바꾸면 두 번째 파라미터 없이 $this->input->post('변수명')으로만 사용해도 자동으로 보안 처리를 해줍니다.








6.2 XSS

 XSS는 cross-Site Scripting의 약어로 사이트간 스크립팅 또는 크로스 사이트 스크립팅이라 합니다.


 해커가 웹 페이지에 악성 스크립트를 삽입할 수 있는 취약점입니다. 이 취약점을 이용해 다른 사람의 쿠키나 세션 정보를 가로챌 수 있어 해커가 그 사용자의 관리 페이지에 접근 할 수 있습니다.


 게시판에 <script> alert('XSS!!');</script>라고 올리고 글을 봤을 때 경고창으로  XSS!!라고 뜬다면 XSS에 대비되지 않은 게시판입니다.


 4장에서 만든 게시판을 통해 실험해보겠습니다.



 게시글에 스크립트를 삽입하는 글을 올리겠습니다.







  확인 결과 [removed]로 대체 되었습니다.








 


 위와 같이 필터링이 되는 이유는 컨트롤러의 $this->input->post('변수명', TRUE)가 나옵니다. 두 번째 파라미터가 TRUE이면 POST 전송받은 변수의 값을 자동으로 XSS가 필터링해줍니다.











6.3 CSRF

 CSRF(Cross-Site Request Forgery)는 크로스 사이트 요청 위조의 약어이며, 사이트의 인증된 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위를 특정 사이트에 요청합니다.


 이를 막기 위해서 서버의 상태를 변경하는 요청은 GET을 사용하지 않고 POST 전송의 경우에도 hidden 필드에 임의의 값을 전달하고 컨트롤러에서 그 키 값이 맞는 지 확인해야 합니다.


 CodeIgniter에서는 다음과 같은 방법으로 CSRF 공격을 막을 수 있습니다.



 * bbs/application/config/config.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
/*
|--------------------------------------------------------------------------
| Cross Site Request Forgery
|--------------------------------------------------------------------------
| Enables a CSRF cookie token to be set. When set to TRUE, token will be
| checked on a submitted form. If you are accepting user data, it is strongly
| recommended CSRF protection be enabled.
|
| 'csrf_token_name' = The token name
| 'csrf_cookie_name' = The cookie name
| 'csrf_expire' = The number in seconds the token should expire.
*/
// $config['csrf_protection'] = FALSE;
$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = 'csrf_test_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;
 
cs



 Line 14번째를 TRUE로 변경합니다. 


 그리고 폼 전송 부분의 <form> 선언 부분을 form helper의 form_open() 함수로 바꿔주면 CSRF 방지를 위한 hidden 필드를 자동으로 삽입해줍니다. 컨트롤러에서의 체크 부분은 코어에서 자동으로 처리합니다.

 








 컨트롤러에서 폼 헬퍼를 로딩합니다.



 * board.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
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  게시판 메인 컨트롤러
 */
 
class Board extends CI_Controller {
 
    function __construct() {
        parent::__construct();
        $this -> load -> database();
        $this -> load -> model('board_m');
        $this -> load -> helper(array('url''date'));
        $this -> load -> helper('form');
    }
 
 
    ........
 
 
 
}
 
cs




  * write_v.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
 
<article id="board_area">
    <header>
        <h1></h1>
    </header>
    <!-- <form class="form-horizontal" method="post" action="" id="write_action"> -->
    <?php
        $attributes = array('class' => 'form-horizontal''id' => 'write_action');
        echo form_open('board/write/ci_board'$attributes);
   ?>
        <fieldset>
            <legend>
                게시물 쓰기
            </legend>
            <div class="control-group">
                <label class="control-label" for="input01">제목</label>
                <div class="controls">
                    <input type="text" class="input-xlarge" id="input01" name="subject"
                        value="<?php echo set_value('subject'); ?>">
                    <p class="help-block">
                        게시물의 제목을 써주세요.
                    </p>
                </div>
                <label class="control-label" for="input02">내용</label>
                <div class="controls">
                    <textarea class="input-xlarge" id="input02" name="contents" rows="5"><?php echo set_value('contents');?></textarea>
                    <p class="help-block">
                        게시물의 내용을 써주세요.
                    </p>
                </div>
 
                <div class="controls">
                    <p class="help-block"><?php echo validation_errors();?></p>
                </div>
 
                <div class="form-actions">
                    <button type="submit" class="btn btn-primary" id="write_btn">
                        작성
                    </button>
                    <button class="btn" onclick="document.location.reload()">
                        취소
                    </button>
                </div>
            </div>
        </fieldset>
    </form>
</article>
 
cs



 기존의 폼 태그는 주석처리 후, 추가해야할 속성 값을 배열로 작성해서 form_open() 함수의 두 번째 파라미터로 전달합니다.





* 이 포스트는 서적 '만들면서 배우는 CodeIgniter 프레임워크'를 참고하여 작성하였습니다


다른 카테고리의 글 목록

Web/CodeIgniter 카테고리의 포스트를 톺아봅니다

[CodeIgniter] 5. 폼 검증하기

2015.08.24 15:00 - Palpit
조회수 확인

4장에서 게시판의 기본 골격을 만들었습니다. 5장에서는 CodeIgniter의 라이브러리 중 하나인 form_validation 을 이용해 값의 존재유무, 데이터 형식(한글, 영문, 숫자 등), 최소, 최대 길이 제한, 중복 아이디 체크나 비밀번호 입력 여부 등을 검증해보겠습니다.





5.1 기본 형태

 4장의 검색이나 글쓰기 소스에서는 자바스크립트를 이용해 뷰 단에서 체크했습니다.


 CodeIgniter 폼 검증은 프로그램 단에서 검증하는 것이라 전송 후에 체크하고 설정된 룰을 통과하지 못할 경우 다시 뷰에 에러 메세지를 표시하는 형태입니다.


 자바스크립트로 뷰 단에서 체크하는 것보다 한번 전송되고 다시 폼이 표시되는 형태라 서버 리소스를 차지할 수 있습니다. 


 그럼에도 프로그램 단에서 체크하는 폼 전송 형태를 사용하는 것은 뷰 단에서의 체크는 변조가 가능하기 때문입니다. 그렇기 때문에 뷰 단에서 체크했다고 하더라도 프로그램 단에서 한 번 더 체크해야 합니다.


 테스트할 소스는 아래와 같습니다. 아래 경로의 test.php 파일을 만들어서 작성하세요.




 * bbs/application/controllers/test.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
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  기타 테스트용 컨트롤러
 */
 
class Test extends CI_Controller {
 
    function __construct() {
        parent::__construct();
    }
 
    public function index() {
        $this -> forms();
    }
 
    public function _remap($method) {
        $this -> load -> view('header_v');
 
        if (method_exists($this$method)) {
            $this -> {"{$method}"}();
        }
 
        $this -> load -> view('footer_v');
    }
    
    /**
     * 폼 검증 테스트
     */
    public function forms() {
        $this->output->enable_profiler(TRUE);
        
        // Form validation 라이브러리 로드
        $this->load->library('form_validation');
        
        // 폼 검증 필드와 규칙 사전 정의
        $this->form_validation->set_rules('username''아이디''required');        
        $this->form_validation->set_rules('password''비밀번호''required');        
        $this->form_validation->set_rules('passconf''비밀번호 확인''required');        
        $this->form_validation->set_rules('email''이메일''required');        
        
        if ($this->form_validation->run() == FALSE) {
            $this->load->view('test/forms_v');
        } else {
            $this->load->view('test/form_success_v');
        }
    }
 
}
 
cs



 Line 35: 폼 검증 라이브러리를 로드합니다.

 Line 38 ~ 41: 검증 룰을 선언합니다. 프로그램 단에서 체크하는 것이라 이곳에서 선언합니다.



 뷰에서 다시 돌려받은 값을 어떻게 표시하고 에러 메세지를 표시하는지 알아봅니다.




 * bbs/application/views/test/forms_v.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
 
<article id="board_area">
    <header><h1></h1></header>
    <?php echo validation_errors();?>
    
    <form method="POST" class="form-horizontal">
        <fieldset>
            <legend> 폼 검증</legend>
            <div class="control-group">
                <label class="control-label" for="input01">아이디</label>
                <div class="controls">
                    <input type="text" name="username" class="input-xlarge" id="input01" />
                    <p class="help-block">아이디를 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input02">비밀번호</label>
                <div class="controls">
                    <input type="password" name="password" class="input-xlarge" id="input02" />
                    <p class="help-block">비밀번호를 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input03">비밀번호 확인</label>
                <div class="controls">
                    <input type="password" name="passconf" class="input-xlarge" id="input03" />
                    <p class="help-block">비밀번호를 한 번 더 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input04">이메일</label>
                <div class="controls">
                    <input type="text" name="email" class="input-xlarge" id="input04" />
                    <p class="help-block">이메일을 입력하세요.</p>
                </div>
            </div>
        </fieldset>
        
        <div><input type="submit" value="전송" class="btn btn-primary"/></div>
    </form>
</article>
 
cs





 * bbs/application/views/test/form_success_v.php


1
2
3
4
5
6
 
<article id="board_area">
    <header><h1></h1></header>
    <h1> 전송 성공 !</h1>
</article>
 
cs





 주소 http://localhost/bbs/test/ 에 접속하여 검증절차를 진행해봅니다.

















 

 username, password, passconf, email 필드의 룰 설정이 required 로 되어 있기 때문에 4개의 필드에 모두 내용이 있어야 성공 화면을 볼 수 있습니다.


 


 









 이상으로 폼 검증의 기본 형태에 대해 알아보았습니다. 다음 절에서는 다양한 검증 규칙(길이, 입력 형식 검토, 이메일, IP 체크 등)을 적용하는 방법에 대해 알아보겠습니다.








5.2 검증 규칙 설정

 검증 규칙은 원하는 순서대로 원하는 만큼 선언할 수 있습니다. callback 함수를 지원하여 데이터 중복 여부 체크 등 전처리를 할 수도 있습니다.


 검사 규칙은 set_rules() 함수를 사용해 설정합니다.





  $this->form_validation->set_rules('field_name', 'err_msg', 'valid_rules');





 set_rules() 함수는 세 가지 파라미터를 사용합니다.


 첫 번째 파라미터는 필드 이름이고 뷰의 폼에서 설정한 필드 이름과 일치해야 합니다. 두 번째 파라미터는 필드 이름에 대해 에러 메세지를 표시할 내용입니다. 세 번째 파라미터에 폼 검증에 필요한 검사 규칙을 선언합니다.


 기존 컨트롤러의 검증 규칙을 아래와 같이 수정하도록 하겠습니다.



 * test.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
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  기타 테스트용 컨트롤러
 */
 
class Test extends CI_Controller {
 
    function __construct() {
        parent::__construct();
    }
 
    public function index() {
        $this -> forms();
    }
 
    public function _remap($method) {
        $this -> load -> view('header_v');
 
        if (method_exists($this$method)) {
            $this -> {"{$method}"}();
        }
 
        $this -> load -> view('footer_v');
    }
    
    /**
     * 폼 검증 테스트
     */
    public function forms() {
        $this->output->enable_profiler(TRUE);
        
        // Form validation 라이브러리 로드
        $this->load->library('form_validation');
        
        // 폼 검증 필드와 규칙 사전 정의
        $this->form_validation->set_rules('username''아이디''required|min_length[5]|max_length[12]');        
        $this->form_validation->set_rules('password''비밀번호''required|matches[passconf]');        
        $this->form_validation->set_rules('passconf''비밀번호 확인''required');        
        $this->form_validation->set_rules('email''이메일''required|valid_email');        
        
        if ($this->form_validation->run() == FALSE) {
            $this->load->view('test/forms_v');
        } else {
            $this->load->view('test/form_success_v');
        }
    }
 
}
 
cs




 Line 39: 아이디 검증 규칙에 최소 5 글자, 최대 12 글자 이내로 제한하는 규칙을 추가했습니다.

 Line 40: passconf 필드와 일치하는지의 여부를 체크하는 규칙을 추가했습니다.

 Line 42: 입력한 이메일이 이메일 규칙에 맞는지 체크하는 규칙을 추가했습니다.







 5.2.1 형식 검토

  폼에서 입력한 필드의 내용에 대해 적용되는 검토의 종류는 다음 표와 같습니다.





 규칙

 파라미터 

  설명 

 required

 No 

  검사 대상이 비어있으면 FALSE

 matches

 Yes 

  검사 대상이 파라미터 값과 일치하지 않으면 FALSE 

 is_unique

 Yes 

  파라미터에서 테이블 및 필드 이름이 유일하지 않으면 FALSE 

 alpha

 No

  검사 대상이 알파벳 이외의 문자를 포함할 때 FALSE 

 alpha_numeric

 No

  검사 대상이 알파벳이나 숫자가 아닌 문자를 포함할때 FALSE 

 alpha_dash

 No

  검사 대상이 알파벳, 숫자, 밑줄(_), 대시(-) 이외의 문자를 포함할 때 FALSE 

 numeric

 No

  검사 대상이 숫자 이외의 문자를 포함할 때 FALSE 

 integer

 No

  검사 대상이 정수 이외의 문자를 포함할 때 FALSE 

 decimal

 Yes 

  검사 대상이 소수 이외의 문자를 포함할 때 FALSE 

 is_natural

 No

  검사 대상이 자연수 이외의 문자를 포함할 때 FALSE 

 is_natural_no_zero

 No

  검사 대상이 1 이상의 자연수 이외의 문자를 포함할 때 FALSE

 valid_email

 No

  유효한 이메일 주소가 아닐 때 FALSE 

 valid_emails

 No

  검사 대상이 콤마(,)로 구분된 이메일 주소일 경우에 사용하며 유효한 이메일 주소가 아닐 때 FALSE 

 valid_ip

 No

  유효한 IP 주소가 아닐 때 FALSE 



 다음으로는 각 규칙과 더불어 위에서 언급하지 않은 규칙들 중에 에러 메세지를 출력 할 때의 출력 메세지를 보여주는 php 파일입니다.




 * system/language/english/form_validation_lang.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
 
<?php
 
$lang['required']            = "The %s field is required.";
$lang['isset']                = "The %s field must have a value.";
$lang['valid_email']        = "The %s field must contain a valid email address.";
$lang['valid_emails']        = "The %s field must contain all valid email addresses.";
$lang['valid_url']            = "The %s field must contain a valid URL.";
$lang['valid_ip']            = "The %s field must contain a valid IP.";
$lang['min_length']            = "The %s field must be at least %s characters in length.";
$lang['max_length']            = "The %s field can not exceed %s characters in length.";
$lang['exact_length']        = "The %s field must be exactly %s characters in length.";
$lang['alpha']                = "The %s field may only contain alphabetical characters.";
$lang['alpha_numeric']        = "The %s field may only contain alpha-numeric characters.";
$lang['alpha_dash']            = "The %s field may only contain alpha-numeric characters, underscores, and dashes.";
$lang['numeric']            = "The %s field must contain only numbers.";
$lang['is_numeric']            = "The %s field must contain only numeric characters.";
$lang['integer']            = "The %s field must contain an integer.";
$lang['regex_match']        = "The %s field is not in the correct format.";
$lang['matches']            = "The %s field does not match the %s field.";
$lang['is_unique']             = "The %s field must contain a unique value.";
$lang['is_natural']            = "The %s field must contain only positive numbers.";
$lang['is_natural_no_zero']    = "The %s field must contain a number greater than zero.";
$lang['decimal']            = "The %s field must contain a decimal number.";
$lang['less_than']            = "The %s field must contain a number less than %s.";
$lang['greater_than']        = "The %s field must contain a number greater than %s.";
 
 
/* End of file form_validation_lang.php */
/* Location: ./system/language/english/form_validation_lang.php */
cs





 5.2.2 입력 길이

  폼에서 입력한 필드의 길이에 대한 검토표는 아래와 같습니다.



  규칙 

 파라미터 

  설명 

 min_length

 Yes 

   파라미터 값보다 작을 때 FALSE

 max_length

 Yes

   파라미터 값보다 클 때 FALSE 

 exact_length

 Yes

   파라미터 값과 다를 때 FALSE 

 greater_than

 Yes

   지정된 값보다 작거나 숫자가 아닌 경우 FALSE 

 less_than

 Yes

   지정된 값보다 크거나 숫자가 아닌 경우 FALSE 











5.3 폼 데이터 복원하기

 이전 절까지 진행하면서 폼 검증에서 필수 요소 중 하나인 폼 데이터 복원이 빠져 있습니다. 


 폼을 검증하고 에러 메세지를 화면에 출력하는 데 이전에 입력했던 폼 데이터는 복원되지 않았습니다.


 아래 소스와 같이 추가된 부분을 통해서 폼 데이터가 복원 됩니다.


 * bbs/application/views/test/forms_v.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
<article id="board_area">
    <header><h1></h1></header>
    <?php echo validation_errors();?>
    
    <form method="POST" class="form-horizontal">
        <fieldset>
            <legend> 폼 검증</legend>
            <div class="control-group">
                <label class="control-label" for="input01">아이디</label>
                <div class="controls">
                    <input type="text" name="username" class="input-xlarge" id="input01" 
                        value="<?php echo set_value('username'); ?>"/>
                    <p class="help-block">아이디를 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input02">비밀번호</label>
                <div class="controls">
                    <input type="password" name="password" class="input-xlarge" id="input02" />
                    <p class="help-block">비밀번호를 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input03">비밀번호 확인</label>
                <div class="controls">
                    <input type="password" name="passconf" class="input-xlarge" id="input03" />
                    <p class="help-block">비밀번호를 한 번 더 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input04">이메일</label>
                <div class="controls">
                    <input type="text" name="email" class="input-xlarge" id="input04" 
                        value="<?php echo set_value('email'); ?>"/>
                    <p class="help-block">이메일을 입력하세요.</p>
                </div>
            </div>
        </fieldset>
        
        <div><input type="submit" value="전송" class="btn btn-primary"/></div>
    </form>
</article>
 
cs












 위 소스의 set_value() 함수와 같이 폼 데이터 복원에 사용되는 함수 표는 다음과 같습니다.




 함수 종류

  설명 

 set_value()

 input 이나 textarea의 폼 데이터 복원에 사용합니다. 첫 번째 파라미터로 필드 이름을 넘겨줘야 합니다. 두 번째 파라미터에 값을 입력할 경우 폼이 처음 로드될 때 기본 값으로 사용됩니다. 

 set_select()

 <select> 태그를 사용할 때 선택했던 값을 표시해 줍니다. 첫 번째 파라미터는 select의 name 이며, 두 번째 파라미터는 각 아이템의 값이며, 세 번째 파라미터에는 TRUE 또는 FALSE를 설정할 경우 선택된 값이 됩니다. 

 set_checkbox()

 전송할 당시의 체크박스의 값을 복원합니다. 첫 번째 파라미터는 체크박스 필드 이름이며, 두 번째 파라미터는 선택된 값입니다. 세 번째 파라미터는 불리언 값으로 선택된 값을 나타냅니다.

 set_radio()

 라디오 버튼을 전송할 당시의 값으로 복원합니다. 사용법은 set_checkbox()와 동일합니다.




 다음은 set_select(), set_checkbox(), set_radio() 를 application/views/test/forms_v.php 에 적용한 결과는 다음과 같습니다.



 * test.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
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  기타 테스트용 컨트롤러
 */
 
class Test extends CI_Controller {
 
    function __construct() {
        parent::__construct();
    }
 
    public function index() {
        $this -> forms();
    }
 
    public function _remap($method) {
        $this -> load -> view('header_v');
 
        if (method_exists($this$method)) {
            $this -> {"{$method}"}();
        }
 
        $this -> load -> view('footer_v');
    }
    
    /**
     * 폼 검증 테스트
     */
    public function forms() {
        // $this->output->enable_profiler(TRUE);
        
        // Form validation 라이브러리 로드
        $this->load->library('form_validation');
        
        // 폼 검증 필드와 규칙 사전 정의
        $this->form_validation->set_rules('username''아이디''required|min_length[5]|max_length[12]');        
        $this->form_validation->set_rules('password''비밀번호''required|matches[passconf]');        
        $this->form_validation->set_rules('passconf''비밀번호 확인''required');        
        $this->form_validation->set_rules('email''이메일''required|valid_email');        
        $this->form_validation->set_rules('count''기본 값''numeric');
        $this->form_validation->set_rules('myselect''select 값''');
        $this->form_validation->set_rules('mycheck[]''체크 박스 값''');
        $this->form_validation->set_rules('myradio''라디오 버튼 값''');
        
        
        if ($this->form_validation->run() == FALSE) {
            $this->load->view('test/forms_v');
        } else {
            $this->load->view('test/form_success_v');
        }
    }
 
}
 
cs






 * forms_v.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
 
<article id="board_area">
    <header><h1></h1></header>
    <?php echo validation_errors();?>
    
    <form method="POST" class="form-horizontal">
        <fieldset>
            <legend> 폼 검증</legend>
            <div class="control-group">
                <label class="control-label" for="input01">아이디</label>
                <div class="controls">
                    <input type="text" name="username" class="input-xlarge" id="input01" 
                        value="<?php echo set_value('username'); ?>"/>
                    <p class="help-block">아이디를 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input02">비밀번호</label>
                <div class="controls">
                    <input type="password" name="password" class="input-xlarge" id="input02" />
                    <p class="help-block">비밀번호를 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input03">비밀번호 확인</label>
                <div class="controls">
                    <input type="password" name="passconf" class="input-xlarge" id="input03" />
                    <p class="help-block">비밀번호를 한 번 더 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input04">이메일</label>
                <div class="controls">
                    <input type="text" name="email" class="input-xlarge" id="input04" 
                        value="<?php echo set_value('email'); ?>"/>
                    <p class="help-block">이메일을 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input05">기본 값 설정</label>
                <div class="controls">
                    <input type="text" name="count" class="input-xlarge" id="input05" 
                        value="<?php echo set_value('count', 0); ?>"/>
                    <p class="help-block">기본 값이 출력됩니다.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input06">Select 값 복원</label>
                <div class="controls">
                    <select name="myselect" id="input06">
                        <option value="one" <?php echo set_select('myselect''one', TRUE);?>>
                            One
                        </option>
                        <option value="two" <?php echo set_select('myselect''two');?>>
                            Two
                        </option>
                        <option value="three" <?php echo set_select('myselect''three');?>>
                            Three
                        </option>
                    </select>
                    <p class="help-block">선택 하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input07">체크박스</label>
                <div class="controls">
                    1번 <input type="checkbox" name="mycheck[]" id="input07" value="1" 
                        <?php echo set_checkbox('mycheck[]''1', TRUE);?> />
                    2번 <input type="checkbox" name="mycheck[]" id="input07" value="2" 
                        <?php echo set_checkbox('mycheck[]''2');?> />
                    <p class="help-block">체크박스를 선택하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input08">라디오</label>
                <div class="controls">
                    1번 <input type="radio" name="myradio" id="input08" value="1" 
                        <?php echo set_radio('myradio''1', TRUE);?> />
                    2번 <input type="radio" name="myradio" id="input08" value="2" 
                        <?php echo set_radio('myradio''2');?> />
                    <p class="help-block">라디오 버튼을 선택하세요.</p>
                </div>
            </div>
        </fieldset>
        
        <div><input type="submit" value="전송" class="btn btn-primary"/></div>
    </form>
</article>
 
cs











5.4 콜백 함수

 콜백 함수(callback function)는 컨트롤러 set_rule() 의 세 번째 파라미터에 선언하여 사용합니다. 예를 들어 회원가입 시에 ID 중복 여부를 체크하는데 사용합니다. 


 콜백 함수는 접두사로 callback_을 사용합니다. callback_username_check라고 선언했을 경우 실제 사용되는 함수는 username_check() 입니다. 컨트롤러에 콜백 함수 체크 부분을 추가해보겠습니다.


 아이디 중복 여부를 체크하는 함수를 만들 것이라 MySQL 콘솔에 접속하여 users 테이블을 먼저 생성하고 샘플 유저를 입력합니다.






 CREATE TABLE users (

id INT(10) NULL AUTO_INCREMENT PRIMARY KEY,

username VARCHAR(50) NULL COMMENT '아이디',

password VARCHAR(50) NULL COMMENT '비밀번호',

name VARCHAR(50) NULL COMMENT '이름',

email VARCHAR(50) NULL COMMENT '이메일',

reg_date DATETIME NULL COMMENT '가입일'

 )


 COMMENT = '회원테이블'

 COLLATE = 'utf8_general_ci'

 ENGINE = MyISAM

 ROW_FORMAT = DEFAULT;


 INSERT INTO users(username, password, name, email, reg_date) VALUES ('advisor', '1234', 'palpit', 'zhfldi4@gmail.com', '2015-08-24 13:11:21');





 test 컨트롤러를 수정합니다.


 * test.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
65
66
67
68
69
70
71
72
73
74
75
76
77
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  기타 테스트용 컨트롤러
 */
 
class Test extends CI_Controller {
 
    function __construct() {
        parent::__construct();
    }
 
    public function index() {
        $this -> forms();
    }
 
    public function _remap($method) {
        $this -> load -> view('header_v');
 
        if (method_exists($this$method)) {
            $this -> {"{$method}"}();
        }
 
        $this -> load -> view('footer_v');
    }
    
    /**
     * 폼 검증 테스트
     */
    public function forms() {
        // $this->output->enable_profiler(TRUE);
        
        // Form validation 라이브러리 로드
        $this->load->library('form_validation');
        
        // 폼 검증 필드와 규칙 사전 정의
        $this->form_validation->set_rules('username''아이디''callback_username_check');        
        $this->form_validation->set_rules('password''비밀번호''required|matches[passconf]');        
        $this->form_validation->set_rules('passconf''비밀번호 확인''required');        
        $this->form_validation->set_rules('email''이메일''required|valid_email');        
        $this->form_validation->set_rules('count''기본 값''numeric');
        $this->form_validation->set_rules('myselect''select 값''');
        $this->form_validation->set_rules('mycheck[]''체크 박스 값''');
        $this->form_validation->set_rules('myradio''라디오 버튼 값''');
        
        
        if ($this->form_validation->run() == FALSE) {
            $this->load->view('test/forms_v');
        } else {
            $this->load->view('test/form_success_v');
        }
    }
    
    public function username_check($id) {
        $this->load->database();
        
        if ($id) {
            $result = array();
            $sql = "SELECT * FROM users WHERE username = '".$id."'";
            $query = $this->db->query($sql);
            $result = @$query->row();
            
            if ($result) {
                $this->form_validation->set_message('username_check'$id.'은(는) 중복된 아이디 입니다.');
                return FALSE;
            } else {
                return TRUE;
            }
        } else {
            return FALSE;
        }
    }
 
}
 
cs




 users 테이블에 아이디 advisor를 미리 입력해 놓은 상태라 아래와 같이 중복된 아이디라고 폼 검증을 볼 수 있습니다.


 










5.5 에러 메세지 설정과 표시

 CodeIgniter의 모든 내장 에러 메세지는 system/language/english에 위치하며 폼 검증 에러 메세지는 form_validation_lang.php 입니다.


 기본 언어는 영어로 설정되어 있습니다. 이번 절은 에러 메세지를 개별적으로 표시하기 위한 방법을 알아봅시다.



 5.5.1 에러 메세지 개별적으로 표시하기

  폼 검증의 에러 메세지를 표현하는 방법에는 두 가지가 있습니다. 


  지금까지 소스에 적용된 validation_errors() 를 이용해 에러 메세지를 한번에 리스트로 표현하는 방법과 form_error()를 이용해 개별적으로 표시하는 방법입니다.


  뷰 파일을 수정하여 에러 메세지를 각각 표시해보겠습니다.



 * forms_v.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
 
<article id="board_area">
    <header><h1></h1></header>
    <?php //echo validation_errors(); ?>
    <?php
        if ( form_error('username')) {
            $error_username = form_error('username');
        } else {
            $error_username = form_error('username_check');
        }
   ?>
    
    <form method="POST" class="form-horizontal">
        <fieldset>
            <legend> 폼 검증</legend>
            <div class="control-group">
                <label class="control-label" for="input01">아이디</label>
                <div class="controls">
                    <input type="text" name="username" class="input-xlarge" id="input01" 
                        value="<?php echo set_value('username'); ?>"/>
                    <p class="help-block">
                        <?php 
                        if ($error_username == FALSE) {
                            echo "아이디를 입력하세요";
                        } else {
                            echo $error_username;
                        }
                       ?>
                    </p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input02">비밀번호</label>
                <div class="controls">
                    <input type="password" name="password" class="input-xlarge" id="input02" />
                    <p class="help-block">
                        <?php
                            if (form_error('password'== FALSE) {
                                echo "비밀번호를 입력하세요.";
                            } else {
                                echo form_error('password');
                            }
                       ?>
                    </p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input03">비밀번호 확인</label>
                <div class="controls">
                    <input type="password" name="passconf" class="input-xlarge" id="input03" />
                    <p class="help-block">비밀번호를 한 번 더 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input04">이메일</label>
                <div class="controls">
                    <input type="text" name="email" class="input-xlarge" id="input04" 
                        value="<?php echo set_value('email'); ?>"/>
                    <p class="help-block">이메일을 입력하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input05">기본 값 설정</label>
                <div class="controls">
                    <input type="text" name="count" class="input-xlarge" id="input05" 
                        value="<?php echo set_value('count', 0); ?>"/>
                    <p class="help-block">기본 값이 출력됩니다.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input06">Select 값 복원</label>
                <div class="controls">
                    <select name="myselect" id="input06">
                        <option value="one" <?php echo set_select('myselect''one', TRUE);?>>
                            One
                        </option>
                        <option value="two" <?php echo set_select('myselect''two');?>>
                            Two
                        </option>
                        <option value="three" <?php echo set_select('myselect''three');?>>
                            Three
                        </option>
                    </select>
                    <p class="help-block">선택 하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input07">체크박스</label>
                <div class="controls">
                    1번 <input type="checkbox" name="mycheck[]" id="input07" value="1" 
                        <?php echo set_checkbox('mycheck[]''1', TRUE);?> />
                    2번 <input type="checkbox" name="mycheck[]" id="input07" value="2" 
                        <?php echo set_checkbox('mycheck[]''2');?> />
                    <p class="help-block">체크박스를 선택하세요.</p>
                </div>
            </div>
            <div class="control-group">
                <label class="control-label" for="input08">라디오</label>
                <div class="controls">
                    1번 <input type="radio" name="myradio" id="input08" value="1" 
                        <?php echo set_radio('myradio''1', TRUE);?> />
                    2번 <input type="radio" name="myradio" id="input08" value="2" 
                        <?php echo set_radio('myradio''2');?> />
                    <p class="help-block">라디오 버튼을 선택하세요.</p>
                </div>
            </div>
        </fieldset>
        
        <div><input type="submit" value="전송" class="btn btn-primary"/></div>
    </form>
</article>
 
cs











5.6 게시판 입력 기능에 폼 검증 추가하기

 이번 절에서는 4.4 절의 입력 기능에 폼 검증을 추가해 게시판의 완성도를 높여보겠습니다. 


 먼저 컨트롤러에 폼 검증 라이브러리(form_validation)를 로딩하고 룰을 설정합니다. board.php의 쓰기 부분을 수정합니다.



 * bbs/application/controllers/board.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
65
66
67
68
69
70
71
72
73
74
75
76
77
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  게시판 메인 컨트롤러
 */
 
class Board extends CI_Controller {
 
 
    ....
 
 
 
    /**
     * 게시물 쓰기
     */
    function write() {
        
        // 폼 검증 라이브러리 로드
        $this->load->library('form_validation');
        
        // 폼 검증할 필드와 규칙 사전 정의
        $this->form_validation->set_rules('subject''제목''required');
        $this->form_validation->set_rules('contents''내용''required');
        
        echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />';
 
        if ( $this->form_validation->run() == TRUE) {
            // 글쓰기 POST 전송 시
 
            $this -> load -> helper('alert');
 
            // 주소 중에서 page 세그먼트가 있는지 검사하기 위해 주소를 배열로 반환
            $uri_array = $this -> segment_explode($this -> uri -> uri_string());
 
            if (in_array('page'$uri_array)) {
                $pages = urldecode($this -> url_explode($uri_array'page'));
            } else {
                $pages = 1;
            }
 
            if (!$this -> input -> post('subject', TRUE) AND !$this -> input -> post('contents', TRUE)) {
                // 글 내용이 없을 경우, 프로그램 단에서 한 번 더 체크
                alert('비정상적인 접근입니다.''/bbs/board/lists/' . $this -> uri -> segment(3) . '/page/' . $pages);
                exit ;
            }
 
            // var_dump($_POST);
            $write_data = array(
                'subject' => $this -> input -> post('subject', TRUE), 
                'contents' => $this -> input -> post('contents', TRUE), 
                'table' => $this -> uri -> segment(3)
            );
 
            $result = $this -> board_m -> insert_board($write_data);
            
            if ($result) {
                alert("입력되었습니다.",'/bbs/board/lists/'.$this->uri->segment(3).'/page/'.$pages);
                exit;
            } else {
                alert("다시 입력해주세요.",'/bbs/board/lists/'.$this->uri->segment(3).'/page/'.$pages);
                exit;
            }
        } else {
            // 쓰기 폼 view 호출
            $this->load->view('board/write_v');
        }
    }
    
 
    .......
 
 
}
 
cs

 






 * write_v.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
 
<article id="board_area">
    <header>
        <h1></h1>
    </header>
    <form class="form-horizontal" method="post" action="" id="write_action">
        <fieldset>
            <legend>
                게시물 쓰기
            </legend>
            <div class="control-group">
                <label class="control-label" for="input01">제목</label>
                <div class="controls">
                    <input type="text" class="input-xlarge" id="input01" name="subject"
                        value="<?php echo set_value('subject'); ?>">
                    <p class="help-block">
                        게시물의 제목을 써주세요.
                    </p>
                </div>
                <label class="control-label" for="input02">내용</label>
                <div class="controls">
                    <textarea class="input-xlarge" id="input02" name="contents" rows="5"><?php echo set_value('contents');?></textarea>
                    <p class="help-block">
                        게시물의 내용을 써주세요.
                    </p>
                </div>
 
                <div class="controls">
                    <p class="help-block"><?php echo validation_errors();?></p>
                </div>
 
                <div class="form-actions">
                    <button type="submit" class="btn btn-primary" id="write_btn">
                        작성
                    </button>
                    <button class="btn" onclick="document.location.reload()">
                        취소
                    </button>
                </div>
            </div>
        </fieldset>
    </form>
</article>
 
cs




 뷰 부분 적용 방법은 간단합니다. 기존 소스 상단의 jQuery로 작성된 폼 검증 역할을 삭제하시고, 폼 데이터 복원과 에러 메세지 출력 부분을 추가하였습니다.









* 이 포스트는 서적 '만들면서 배우는 CodeIgniter 프레임워크'를 참고하여 작성하였습니다

다른 카테고리의 글 목록

Web/CodeIgniter 카테고리의 포스트를 톺아봅니다
조회수 확인

4.5 수정 기능 추가하기

 수정기능은 입력 기능을 수정하여 사용합니다. write 메서드를 복사하여 modify 메서드를 만들고 수정합니다.


 

 * bbs/application/controllers/board.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
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  게시판 메인 컨트롤러
 */
 
class Board extends CI_Controller {
 
 
     ....
 
 
    /**
     * 게시물 수정
     */
    function modify() {
        echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
        
        if ( $_POST ) {
            $this -> load -> helper('alert');
            
            $uri_array = $this->segment_explode($this->uri->uri_string());
            
            if ( in_array('page'$uri_array)) {
                $pages = urldecode($this->url_explode($uri_array'page'));
            } else {
                $pages = 1;
            }
            
            if ( !$this->input->post('subject', TRUE) AND !$this->input->post('contents', TRUE)) {
                alert('비정상적인 접근입니다.''bbs/board/lists/'.$this->uri->segment(3).'/page/'.$pages);
                exit;
            }
            
            
            $modify_data = array(
                'table' => $this->uri->segment(3),
                'board_id' => $this->uri->segment(5),
                'subject' => $this->input->post('subject', TRUE),
                'contents' => $this->input->post('contents', TRUE)
            );
            
            $result = $this->board_m->modify_board($modify_data);
            
            if ( $result ) {
                alert('수정되었습니다.''bbs/board/lists/'.$this->uri->segment(3).'/page/'.$pages);
                exit;
            } else {
                alert('다시 수정해 주세요.''bbs/board/view/'.$this->uri->segment(3).'/board_id/'.$this->uri->segment(5).'/page/'.$pages);
                exit;
            }
        } else {
            $data['views'= $this->board_m->get_view($this->uri->segment(3), $this->uri->segment(5));
            
            $this->load->view('board/modify_v'$data);
        }
    }
}
 
cs




 입력 메서드인 write()와 수정 메서드인 modify()를 비교해보면 약간의 소스 수정만으로 처리가 가능한 것을 알 수 있습니다.


 이제 모델을 살펴봅니다. 글 수정 모델 부분도 입력과 비슷합니다. insert_board() 함수를 복사하여 modify_board()를 만들고 수정합니다.


 * board_m.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
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
 
/**
 * 공통 게시판 모델
 */
 
class Board_m extends CI_Model {
    
 
    ....
 
 
    /**
     * 게시물 수정
     * 
     * @param array $arrays 테이블 명, 게시물 번호, 게시물 제목, 게시물 내용
     * @return boolean 성공 여부
     */
    function modify_board($arrays) {
        $modify_array = array(
            'subject' => $arrays['subject'],
            'contents' => $arrays['contents']
        );
        
        $where = array(
            'board_id' => $arrays['board_id']
        );
        
        $result = $this->db->update($arrays['table'], $modify_array$where);
        
        return $result;
    }
}
 
cs




 수정에서는 INSERT가 UPDATE로 바뀌고 where 절이 추가되었습니다. 간단하게 수정 처리가 끝났습니다.


 뷰를 살펴보겠습니다. 수정 뷰도 입력 뷰와 다른 점은 폼 태그의 value가 추가되어 내용이 보여진다는 점입니다.


 * modify_v.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
        <title>CodeIgniter</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <link type="text/css" rel="stylesheet" href="/bbs/include/css/bootstrap.css" />
        <script>
            $(document).ready(function() {
                $("#write_btn").click(function() {
                    if ($("#input01").val() == '') {
                        alert('제목을 입력해 주세요.');
                        $("#input01").focus();
                        return false;
                    } else if ($("#input02").val() == '') {
                        alert('내용을 입력해 주세요.');
                        $("#input02").focus();
                        return false;
                    } else {
                        $("#write_action").submit();
                    }
                });
            });
       </script>
    </head>
    <body>
        <div id="main">
            <header id="header" data-role="header" data-position="fixed">
                <blockquote>
                    <p>
                        만들면서 배우는 CodeIgniter
                    </p>
                    <small>실행 예제</small>
                </blockquote>
            </header>
            <nav id="gnb">
                <ul>
                    <li>
                        <a rel="external" href="/bbs/<?php echo $this -> uri -> segment(1); ?>/lists/<?php echo $this -> uri -> segment(3); ?>"> 게시판 프로젝트 </a>
                    </li>
                </ul>
            </nav>
            <article id="board_area">
                <header><h1></h1></header>
                <form class="form-horizontal" method="post" action="" id="write_action">
                    <fieldset>
                        <legend>게시물 수정</legend>
                        <div class="control-group">
                            <label class="control-label" for="input01">제목</label>
                            <div class="controls">
                                <input type="text" class="input-xlarge" id="input01" name="subject"
                                    value="<?php echo $views->subject; ?>" />
                            </div>
                            <label class="control-label" for="input02">내용</label>
                            <div class="controls">
                                <textarea class="input-xlarge" id="input02" name="contents" rows="5">
                                    <?php echo $views->contents;?>
                                </textarea>
                            </div>
                            
                            <div class="form-actions">
                                <button type="submit" class="btn btn-primary" id="write_btn"> 수정 </button>
                                <button class="btn" onclick="document.location.reload()">취소</button>
                            </div>
                        </div>
                    </fieldset>
                </form>
            </article>
            <footer id="footer">
                <dl>
                    <dt>
                        <a class="azubu" href="http://www.cikorea.net/" target="blank"> CodeIgniter 한국 사용자포럼 </a>
                    </dt>
                    <dd>
                        Copyright by <em class="black">Palpit</em>.
                    </dd>
                </dl>
            </footer>
        </div>
    </body>
</html>
 
cs



 

 


















4.6 삭제 기능 추가하기



 * board.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
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
/**
 *  게시판 메인 컨트롤러
 */
 
class Board extends CI_Controller {
 
 
    ......
 
 
    /**
     * 게시물 삭제
     */
     
    function delete() {
        echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
 
        $this->load->helper('alert');
        
        $return = $this->board_m->delete_content($this->uri->segment(3), $this->uri->segment(5));
        
        if ( $return ) {
            alert('삭제되었습니다.''bbs/board/lists/'.$this->uri->segment(3).'/page/'.$this->uri->segment(7));
            exit;
        } else {
            alert('삭제 실패하였습니다.''bbs/board/view/'.$this->uri->segment(3).'/board_id/'.$this->uri->segment(5).'/page/'.$this->uri->segment(7));
            exit;
        }
        
    }
}
 
cs






 * board_m.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
 
<?php
if (!defined('BASEPATH'))
    exit('No direct script access allowed');
 
/**
 * 공통 게시판 모델
 */
 
class Board_m extends CI_Model {
    function __construct() {
        parent::__construct();
    }
 
    function get_list($table = 'ci_board'$type = ''$offset = ''$limit = ''$search_word = '') {
 
        $sword = '';
 
        if ($search_word != '') {
            // 검색어 있을 경우
            $sword = ' WHERE subject like "%' . $search_word . '%" or contents like "%' . $search_word . '%" ';
        }
 
        $limit_query = '';
 
        if ($limit != '' OR $offset != '') {
            // 페이징이 있을 경우 처리
            $limit_query = ' LIMIT ' . $offset . ', ' . $limit;
        }
 
        $sql = "SELECT * FROM " . $table . $sword . " ORDER BY board_id DESC " . $limit_query;
        $query = $this -> db -> query($sql);
 
        if ($type == 'count') {
            $result = $query -> num_rows();
        } else {
            $result = $query -> result();
        }
 
        return $result;
    }
 
    /**
     * 게시물 상세보기 가져오기
     *
     * @param string $table 게시판 테이블
     * @param string $id 게시물 번호
     * @return array
     */
    function get_view($table$id) {
        // 조횟수 증가
        $sql0 = "UPDATE " . $table . " SET hits = hits + 1 WHERE board_id='" . $id . "'";
        $this -> db -> query($sql0);
 
        $sql = "SELECT * FROM " . $table . " WHERE board_id = '" . $id . "'";
        $query = $this -> db -> query($sql);
 
        // 게시물 내용 반환
        $result = $query -> row();
 
        return $result;
 
    }
    
    /**
     * 게시물 입력
     * 
     * @param array $arrays 테이블 명, 게시물 제목, 게시물 내용 1차 배열
     * @return boolean 입력 성공여부
     */
    function insert_board($arrays) {
        $insert_array = array(
            'board_pid' => 0,
            'user_id' => 'advisor',
            'user_name' => 'palpit',
            'subject' => $arrays['subject'],
            'contents' => $arrays['contents'],
            'reg_date' => date("Y-m-d H:i:s")
        );
        
        $result = $this->db->insert($arrays['table'], $insert_array);
   &