Model
View가 표현을 담당한다면 Model은 데이터를 담당한다. 여기서 데이터란 주로 데이터베이스를 의미한다. 즉 데이터를 다루는 로직을 모델에 모아둬서 데이터와 뷰를 격리 시키는 것이다. 이를 통해서 코드 관리의 편의성을 높일 수 있고, 향후 데이터베이스를 다른 타입으로 교체가 용이하다.
데이터베이스 설정
데이터베이스를 설정하기 위해서는 Application/config/database.php 파일을 수정한다. 이 중에서 주요한 몇가지 설정에 대해서만 언급하면 아래와 같다. (database.php 예제 참고 ,데이터베이스 설정 참고)
- hostname : 데이터베이스 서버의 주소 (localhost는 PHP와 같은 머신을 의미)
- username : 데이터베이스 사용자의 이름
- password : 데이터베이스 비밀번호
- database : 데이터베이스 명
- dbdriver : 데이터베이스의 종류로 지원되는 드라이브의 목록은 system/database/drivers 디렉토리명을 참고한다.
데이터베이스 설정 파일에는 서버에 접속 할 수 있는 기밀정보가 포함되어 있기 때문에 버전관리에 포함시키면 안된다. 버전관리를 할 때는 버전관리에서 제외하도록 하자.
데이터베이스 라이브러리 로드
데이터베이스를 사용하기 위해서는 우선 데이터베이스 라이브러리를 로드해야 한다. 이 라이브러리는 CI 에서 데이터베이스를 제어 하는 방법을 제공한다. 이것을 로드하는 방법은 두가지다. (topic.php 예제 참고, 데이터베이스 Quick Start 참고)
- application/config/autoload.php 파일의 $autoload['libraries'] 배열에 'database'를 추가한다.
- controller 내에서 $this->load->database()를 호출한다.
설정과 라이브러리 로드가 끝났다면 이제 모델 클래스 파일을 생성해야 한다.
모델 파일의 사용
Model 파일은 application/models 디렉토리 아래에 '모델명_model.php' 의 형식으로 파일을 만든다. 파일은 CI_Model 클래스를 상속 받아야 하고 클래스 명은 '대문자로 시작하는 모델명_model'이어야 한다. (topic_model.php 예제 참고 ,Anatomy Model 참고)
모델 내에서 쿼리를 사용하기 위해서는 $this->db를 이용한다. 예를들어 topic 테이블의 내용을 조회한다면 아래와 같이하면 된다.
$this->db->query("SELECT * FROM topic")
쿼리의 결과를 가져오려면 아래와 같이하면 된다.
$this->db->query("SELECT * FROM topic")->result();
쿼리 결과 생성
result()는 쿼리의 결과를 가져오는 방법을 정한다. 만약 연관배열의 형태로 데이터를 가져오고 싶다면 result_array()를 사용하고 결과가 한행이라면 row()를 사용한다. (쿼리 결과 생성 방법 참조)
Active Record
Active Record는 좀 더 프로그래밍적으로 데이터베이스를 제어하는 방법이다. 예를들어 topic 테이블에서 id 값이 3인 행을 조회하고 싶다면 아래와 같이 한다.
$this->db->get_where('topic', array('id'=>$topic_id))->row();
Active Record를 이용하면 표준 SQL을 이용할 수 있어서 에플리케이션을 좀 더 이식성 좋은 형태로 만들 수 있고, 프로그래밍적으로 쿼리를 생성 할 수 있기 때문에 SQL 문자열을 직접 다루는 수고를 덜 수 있다.
모델 사용
model은 데이터를 가져오는 로직을 메소드로 정의하고, 이 메소드는 controller를 통해서 사용된다. 아래는 모델을 사용하는 방법이다.
모델 로드
모델을 사용하기 위해서는 모델을 로드해야 하는데 아래의 형식을 사용한다.
형식 : $this->load->model('소문자로된 모델 클래스 명');
예제 : $this->load->model('topic_model');
모델 호출
이제부터는 아래의 형식으로 로드한 모델의 API를 호출 할 수 있다.
형식 : 모델 클래스 명'->'메소드 명'
예제 : $topics = $this->topic_model->gets();
예제
본 예제는 데이터베이스와 데이터가 필요하다. 필자는 MySQL을 DB로 사용하고, 데이터는 생활코딩 웹서비스 만들기 실습편의 내용에서 사용한 것을 사용할 것이다. 우선 opentutorials라는 데이터베이스를 만들고, topic이라는 테이블을 생성한 후에 데이터를 삽입하자.
CREATE DATABASE opentutorials CHARACTER SET utf8 COLLATE utf8_general_ci;
use opentutorials;
CREATE TABLE topic ( id int(11) NOT NULL AUTO_INCREMENT, title varchar(255) NOT NULL , description text NULL , created datetime NOT NULL , PRIMARY KEY (id) );
INSERT INTO `topic` (title,description,created) VALUES ('JavaScript란', '<h2>\r\n 자바스크립트는</h2>\r\n<ul>\r\n <li>\r\n 브라우저에서 실행되는 언어</li>\r\n <li>\r\n 가장 많이 사용되는 언어</li>\r\n <li>\r\n 주로 html을 프로그래밍적으로 조작하기 위해서 사용됨</li>\r\n</ul>\r\n<h2>\r\n 예제</h2>\r\n<ul>\r\n <li>\r\n 자바스크립트는 3가지 방식으로 사용됨</li>\r\n <li>\r\n 외부의 파일을 로드</li>\r\n <li>\r\n <script>태그 사이에 기술</li>\r\n <li>\r\n 태그에 직접 기술</li>\r\n</ul>\r\n<h2>\r\n 참고링크</h2>\r\n<ul>\r\n <li>\r\n <a href=\"http://www.maroon.pe.kr/webmaster/java/java_study.html\" target=\"_blank\">스크립트 세상</a></li>\r\n <li> \r\n</ul>\r\n', now()); INSERT INTO `topic` (title,description,created) VALUES ('변수와 상수', '<p>\r\n 변수란</p>\r\n<ul>\r\n <li>\r\n 변하는 값</li>\r\n <li>\r\n x = 10 일 때 왼쪽항인 x는 오른쪽 항인 10에 따라 다른 값이 지정된다.</li>\r\n</ul>\r\n<p>\r\n 상수란</p>\r\n<ul>\r\n <li>\r\n 변하지 않는 값</li>\r\n <li>\r\n x = 10 일 때 오른쪽항인 10이 상수가 된다.</li>\r\n</ul>\r\n<pre class=\"brush: xml\">\r\n<script type="text/javascript">\r\n // x의 값이 오른쪽 항에 따라서 변한다.\r\n // x가 변수라는 명시적인 의미\r\n var x = 10;\r\n alert(x);\r\n var x = 20;\r\n alert(x);\r\n</script></pre>\r\n<p>\r\n </p>\r\n', now()); INSERT INTO `topic` (title,description,created) VALUES ('연산자', '<p>\r\n 연산에 사용되는 기호들. (y = 5 일 때)</p>\r\n<table class=\"table\">\r\n <tbody>\r\n <tr>\r\n <th align=\"left\" width=\"15%\">\r\n Operator</th>\r\n <th align=\"left\" width=\"40%\">\r\n Description</th>\r\n <th align=\"left\" width=\"25%\">\r\n Example</th>\r\n <th align=\"left\" width=\"20%\">\r\n Result</th>\r\n </tr>\r\n <tr>\r\n <td valign=\"top\">\r\n +</td>\r\n <td valign=\"top\">\r\n 더하기</td>\r\n <td valign=\"top\">\r\n x=y+2</td>\r\n <td valign=\"top\">\r\n x=7</td>\r\n </tr>\r\n <tr>\r\n <td valign=\"top\">\r\n -</td>\r\n <td valign=\"top\">\r\n 빼기</td>\r\n <td valign=\"top\">\r\n x=y-2</td>\r\n <td valign=\"top\">\r\n x=3</td>\r\n </tr>\r\n </tbody>\r\n</table>\r\n', now()); INSERT INTO `topic` (title,description,created) VALUES ('JSON', '<h2>JSON이란?</h2>\r\n\r\n<p>서로 다른 언어들간에 데이터를 주고 받는 여러 방법이 있다. 대표적인 것이 XML인데, XML은 문법이 복잡하고, 엄격한 표현규칙으로 인해서 json 대비 데이터의 용량이 커진다는 단점이 있다.</p>\r\n\r\n<p>JSON은 경량의 데이터 교환 형식으로 JavaScript에서 숫자와 배열등을 만드는 형식을 차용해서 이것을 다른 언어에서도 사용할 수 있도록 한 텍스트 형식이다. </p>\r\n\r\n<p>아래 예제는 위의 예제에서 전송한 데이터를 받아서 몇가지 부가정보를 추가해서 json으로 인코드한 후에 다시 반환하는 PHP 코드다. </p>\r\n\r\n<p>json.php - (<a href=\"https://github.com/egoing/codingeverybody_javascript/blob/master/JSON/json.php\" target=\"_blank\">github</a>)</p>\r\n\r\n<pre class=\"brush: php\">\r\n<?php\r\n$userinfo = json_decode($_GET['data']);\r\n$userinfo->address = 'seoul';\r\n$userinfo->phonenumber = '01023456789';\r\necho json_encode($userinfo);\r\n?></pre>\r\n\r\n<h2>json의 형식</h2>\r\n\r\n<h3>object</h3>\r\n\r\n<p>객체는 아래와 같은 문법을 가지고 있다.</p>\r\n\r\n<p>예제</p>\r\n\r\n<p>{"userid":"egoing","pwd":"12345567"}</p>\r\n\r\n<p><img height=\"113\" src=\"http://www.json.org/object.gif\" width=\"598\" /></p>\r\n\r\n<h3>array</h3>\r\n\r\n<p>배열은 아래와 같은 문법을 가지고 있다. </p>\r\n\r\n<p>예제</p>\r\n\r\n<p>[1,2,3,4]</p>\r\n\r\n<p><img height=\"113\" src=\"http://www.json.org/array.gif\" style=\"line-height: 1.8em;\" width=\"598\" /></p>\r\n\r\n<h3>Value</h3>\r\n\r\n<p>위에서 사용된 Value는 값을 의미하는데 큰 따옴표로 묶인 문자나 숫자, 불린 값이 사용된다.</p>\r\n\r\n<p>예제</p>\r\n\r\n<ul>\r\n <li>문자 : "헬로우 월드"</li>\r\n <li>숫자 : 1</li>\r\n <li>불린 : true</li>\r\n</ul>\r\n\r\n<p><img height=\"278\" src=\"http://www.json.org/value.gif\" width=\"598\" /></p>\r\n', now());
application/config/database.php
일부 웹호스팅 환경에서는 pconnect true를 지원하지 않는 경우가 있다. pconnect에 대해서는 아래 링크를 참조하자. pconnect
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); $active_group = 'default'; $active_record = TRUE; $db['default']['hostname'] = 'localhost'; $db['default']['username'] = 'egoing'; $db['default']['password'] = '111111'; $db['default']['database'] = 'opentutorials'; $db['default']['dbdriver'] = 'mysql'; $db['default']['dbprefix'] = ''; $db['default']['pconnect'] = TRUE; $db['default']['db_debug'] = TRUE; $db['default']['cache_on'] = FALSE; $db['default']['cachedir'] = ''; $db['default']['char_set'] = 'utf8'; $db['default']['dbcollat'] = 'utf8_general_ci'; $db['default']['swap_pre'] = ''; $db['default']['autoinit'] = TRUE; $db['default']['stricton'] = FALSE;
application/controllers/topic.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Topic extends CI_Controller { function __construct() { parent::__construct(); $this->load->database(); $this->load->model('topic_model'); } function index(){ $this->load->view('head'); $topics = $this->topic_model->gets(); $this->load->view('topic_list', array('topics'=>$topics)); $this->load->view('main'); $this->load->view('footer'); } function get($id){ $this->load->view('head'); $topics = $this->topic_model->gets(); $this->load->view('topic_list', array('topics'=>$topics)); $topic = $this->topic_model->get($id); $this->load->view('get', array('topic'=>$topic)); $this->load->view('footer'); } } ?>
application/models/topic_model.php
<?php class Topic_model extends CI_Model { function __construct() { parent::__construct(); } function gets(){ return $this->db->query("SELECT * FROM topic")->result(); } function get($topic_id){ return $this->db->get_where('topic', array('id'=>$topic_id))->row(); } }
application/views/get.php
<article> <h1><?=$topic->title?></h1> <div> <?=$topic->description?> </div> </article>
위의 예제에서 <?=$topic->title?> 은 <?=htmlspecialchars($topic->title)?>으로 처리해야 한다. htmlspecialchars 는 HTML 코드를 HTML 코드를 인코딩해서 html 코드가 해석되지 않도록 한다. 예를들어 아래의 내용을 제목으로 입력해보자. (입력 한 후에 디비에서 직접 데이터를 직접 삭제할 수 있는 경우만 하자. 안그러면 페이지로 접근 자체가 불가능해질 것이다. ) <script>alert('haha');location.href="http://naver.com"</script> 해당 페이지로 방문한 사용자를 엉뚱한 페이지로 보내버린다. 이것을 방지하기 위한 기능이 htmlspecialchars다. 이것은 매우 중요한 부분이지만, 다소 복잡한 논의가 함의되어 있기 때문에 보안시간에 알아볼 생각이었는데 보안 수업이 예상보다 뒤에 배치되면서 임시로 언급만 해두겠다. 보안에 대한 내용은 다음 링크를 참조한다. http://opentutorials.org/module/327/3837
application/views/main.php
토픽메인
application/views/topic_list.php
<ul> <?php foreach($topics as $entry){ ?> <li><a href="/index.php/topic/get/<?=$entry->id?>"><?=$entry->title?></a></li> <?php } ?> </ul>
Tag
태그이름 : Model2
태그 주소 : https://github.com/egoing/codeigniter_codeingeverbody/tree/Model2