07. 컨트롤러 (Controllers)
목차
7. 컨트롤러 (Controllers)#
7.1. 컨트롤러란?#
컨트롤러는 애플리케이션의 특정 부분의 로직을 관리하기 위해 사용된다. 가장 일반적으로 단일 모델의 로직 관리로 사용한다. 예를 들면, 비디오 샵의 재고관리 사이트를 구축할 경우, VideoController (비디오 컨트롤러)와 RentalController (렌탈 컨트롤러) 로, 각각 비디오와 렌탈의 관리를 할 수 있다. Cake 에서 컨트롤러명은 항상 복수형이다.
애플리케이션의 컨트롤러는, Cake 의 AppController 클래스를 확장 (extend) 한 클래스이다. AppController 는 코어 라이브러리의 Controller 클래스를 확장하고 있다. 컨트롤러 내에서는 액션을 필요한 것만 포함시킬 수 있다. 액션은 뷰를 표시하기위해 웹 애플리케이션내에 사용되는 함수이다.
AppController 클래스는, /app/app_controller.php 에서 정의할 수 있고, 여러 컨트롤러에 공유하는 메소드를 포함한다. 그 AppController 자체도 표준 Cake 라이브러리에 포함되어 있는 Controller 클래스를 확장한 것이다.
액션은 컨트롤러의 하나의 기능이다. 들어온 페이지의 리퀘스트가 라우트를 설정하고 있는 경우, 디스패처에 의해 자동적으로 실행된다. 비디오 관리 예제로 되돌아 가, VideoController 는 view(), rent(), search() 액션이 필요할 것이다. 컨트롤러는 /app/controllers/videos_controller.php 내에 있으며, 아래와 같은 액션을 포함하고 있다 :
- class VideosController extends AppController
{
function view($id)
{
//액션의 로직은 여기에...
}
function rent($customer_id, $video_id)
{
//액션의 로직은 여기...
}
function search($query)
{
//액션의 로직은 여기...
}
}
이러한 액션에는, 아래와 같은 URL 예로 접속할 수 있다:
- http://www.example.com/videos/view/253
http://www.example.com/videos/rent/5124/0-235253
http://www.example.com/videos/search/hudsucker+proxy
이 페이지들은 어떻게 보여지는가? 각각의 액션에 대해 뷰를 정의해야한다 - 이에 관한 내용은 다음 장을 보면 되겠지만, 계속해서 이 장을 보기 바란다. 계속되는 섹션에서는 Cake 의 컨트롤러를 어떻게 활용하는지 보여준다. 특히, 데이터를 뷰에 어떻게 전달하는지, 유저를 어떻게 리다이렉트 하는지 등에 대해서 배운다.
7.2. 컨트롤러 함수#
이 섹션에서는 Cake 의 컨트롤러에서 자주 사용하는 함수에 대해서 다루지만, 전체 레퍼런스를 보기 위해선 http://api.cakephp.org 를 이용해야 하는 것을 주의한다.
7.2.1. 뷰와의 교류#
- set
- string $var
- mixed $value
이 함수는 컨트롤러에서 뷰로 데이터를 전달하는 주요한 방법이다. 하나의 값, 배열 전체등, 어떤 것도 전달해 줄 수 있다. set() 으로 한번 설정하면, 뷰안에서 변수를 사용할 수 있게 된다. 컨트롤러에 set('color', 'blue') 를 실행하면, 뷰내에서 $color 변수를 사용할 수 있다.
- validateErrors
저장에 실패하면 에러메시지를 반환한다.
- validate
모델의 검증 룰에 기초하여, 모델의 데이터를 검증한니다. 검증(validation)에 관해서는, "12. Data Validation" 장 를 참조하기 바란다.
- render
- string $action
- string $layout
- string $file
컨트롤러의 액션 마지막에 render() 가 자동 호출되고, 액션명에 기초해 뷰가 자동 렌더링되기 때문에, 이 함수를 쓸 일은 그다지 많지 않을 것이다. 다른 방식으로, 컨트롤러 로직의 어떤 시점에서라도 뷰를 렌더링하기 위해 이 함수를 호출할 수 있다.
7.2.2. 유저 리다이렉트#
- redirect
- string $url
이 함수로 이동할 장소를 지정할 수 있다. Cake 의 내부 URL 이나, 완전한 URL (http://...) 을 지정할 수 있다.
- flash
- string $message
- string $url
- int $pause
이 함수는, $message 를 $pause 초동안 flash 레이아웃 ( app/views/layouts/flash.thtml 에서 찾을 수 있다. ) 속에서 보여주고, 유저가 지정한 $url 로 리다이렉트한다.
Cake 의 redirect() 와 flash() 함수는 exit() 호출을 포함하지 않는다. 만약 redirect() 또는 flash() 한 후 애플리케이션을 멈추고 싶을 경우, 그 후에 즉각 exit() 호출을 직접 해야 한다. exit() 보다 다른 값을 리턴받고 싶을 수 있는데, 그것은 그 상황에 따라 다르다. (예를 들어, 실행을 위한 콜백이 필요할 경우)
7.2.3. 컨트롤러 콜백#
Cake 의 컨트롤러에는 몇가지 콜백이 있으며, 컨트롤러의 중요한 함수 전후에 로직을 삽입할 수 있다. 이 기능을 사용하려면 컨트롤러 내에서 다음 함수들을 정의하면 된다.
- beforeFilter
컨트롤러 액션 전에 매번 호출된다. 살아있는 세션의 체크, 역할 체크 등에 활용할 수 있다.
- afterFilter
컨트롤러 액션 후에 매번 호출된다.
- beforeRender
컨트롤러의 로직이 끝나고 뷰가 렌더링되기 직전에 호출된다.
7.2.4. 기타 유용한 함수#
이 것들은 Cake 의 객체 클래스의 함수지만, 컨트롤러내에서도 사용할 수 있다.
- requestAction
- string $url
- array $extra
이 함수는 어느 곳에서든 컨트롤러의 액션을 호출할 수 있고, 렌더링된 뷰를 반환한다. $url 은 Cake URL (/controllername/actionname/params) 로 지정한다. $extra 배열 중에 'return' 키가 포함되어 있는 경우, 컨트롤러 액션을 위해서 AutoRender 가 자동으로 true 로 설정된다.
requestAction 을 사용하면 다른 컨트롤러 액션으로부터 데이터를 취득하거나, 컨트롤러부터 완전히 렌더링된 뷰를 취득할 수 있다.
먼저, 데이터는 컨트롤러에서 간단한 방법으로 얻을 수 있다. 데이터를 취득하기 원하는 뷰에서 requestAction를 사용하기만 하면 된다.
- // 간단한 컨트롤러
class UsersController extends AppController
{
function getUserList()
{
return $this->User->findAll();
}
}
이 시스템의 유저 목록을 표시하는 간단한 테이블을 작성해야 한다. 다른 컨트롤러에 같은 코드를 반복하려면, requestAction() 을 사용하여 UsersController::getUserList() 로부터 데이터를 취득할 수 있다.
- class ProductsController extends AppController
{
function showUserProducts()
{
$this->set('users', $this->requestAction('/users/getUserList'));
// 뷰의 $users 변수에는,
// UsersController::getUserList() 로부터의 데이타가 들어간다
}
}
애플리케이션에서 고정적이지 않은 요소 (element) 가 여러번 필요할 경우, requestAction() 을 이용해 뷰 속에 주입 (inject) 가능하다. 단지 데이터를 UsersController::getUserList 로 받는 것 뿐만 아니라, 그 액션 안에서 렌더링된 뷰 (테이블 형태가 되어 있는) 를 취득하고 싶다고 하자. 이렇게 하면 코드의 반복없이 해결된다.
- class ProgramsController extends AppController
{
function viewAll()
{
$this->set('userTable', $this->requestAction('/users/getUserList', array('return')));
// 이제, 이 액션의 뷰 내에서 $userTable 를 불러내고
// /users/getUserList 에서 이용할 수 있는 렌더링된 뷰를 echo 할 수 있다.
}
}
requestAction() 을 사용하여 호출된 액션은 빈 레이아웃을 사용하여 렌더링되는 것에 주의한다. 이에 의해 레이아웃내에 레이아웃이 표시되는 위험을 걱정하지 않아도 된다.
requestAction() 함수는 AJAX 를 사용할 때에도 유용하다. AJAX 업데이트 중이나 전에, 작은 뷰 요소를 출력할 수 있다.
- log
- string $message
- int $type = LOG_ERROR
웹 애플리케이션내에서 일어나는 여러가지 이벤트를 이 함수를 이용해 로깅 할 수 있다. 로그는 Cake 의 /tmp 디렉토리 내에 있다.
$type 이 PHP 상수 LOG_DEBUG 와 같은 경우, 디버그 메시지가 로그에 기록된다. 그외 타입은 에러메시지가 기록된다.
- // 컨트롤러 내부에서 log() 로 접속을 기록할 수 있다:
$this->log('경고! 경고!');
//접속 로그 :
06-03-28 08:06:22 Error: 경고! 경고!
$this->log("{$_SESSION['user']} 님이 로그인했습니다.", LOG_DEBUG);
//접속 로그 :
06-03-28 08:06:22 Debug: 바비님이 로그인했습니다.
- postConditions
- array $data
$this->data 에 전달해줄 수 있는 메소드로, 모델의 conditions 배열을 다시 반환한다.
예를 들어, person 의 검색 폼이 있다고 하자:
- // app/views/people/search.thtml:
<?php echo $html->input('Person/last_name'); ?>
이 요소를 폼에 전송하면, $this->data 배열에는 다음과 입력된다:
- Array
(
[Person] => Array
(
[last_name] => Anderson
)
)
이 때에, postConditions() 을 사용하여 데이터를 모델내에 사용할 수 있는 형태로 만든다:
- // app/controllers/people_controller.php:
$conditions = $this->postConditions($this->data);
// 다음과 같은 배열을 생성한다:
Array
(
[Person.last_name] => Anderson
)
// 이것은 모델의 find 조작에 사용할 수 있다:
$this->Person->findAll($conditions);
7.3. 컨트롤러의 변수#
컨트롤러내의 몇가지 특별한 변수를 조작하면, Cake 의 몇가지의 추가 기능을 이용할 수 있다:
$name
PHP 4 는 현재 클래스명을 낙타표기법으로 반환해주지 않는다. 이 문제가 생겼을 경우, 이 변수에 바른 낙타표기법의 이름을 설정한다.
$uses
컨트롤러에 하나 보다 많은 여러 모델을 사용하는가? 예를 들면, FragglesController 는 자동으로 $this->Fraggle 를 로드하지만, $this->Smurf 와 같이 액세스하고 싶은 경우 컨트롤러에 다음과 같이 입력한다 :
- var $uses = array('Fraggle','Smurf');
지금까지 자동으로 사용 할 수 있었던 Fraggle 모델또한 $uses 배열에 포함시켜야 하는 것을 주의한다.
$helpers
이 변수를 사용하면, 뷰에 사용하는 헬퍼가 컨트롤러에 로드된다. HTML 헬퍼는 자동으로 로드되지만, 이 변수로 다른 것도 지정할 수 있다:
- var $helpers = array('Html','Ajax','Javascript');
이 변수를 사용하는 경우, Html 헬퍼도 $helpers 배열에 포함시켜야 한다. 보통은 디폴트로 사용할 수 있지만, $helpers 에 포함시키지 않으면 뷰에서 에러 메시지가 출력된다.
$layout
이 컨트롤러에 사용하고 싶은 레이아웃의 이름을 이 변수에 지정한다.
$autoRender
false 로 설정하면 자동 렌더링을 멈춘다.
$beforeFilter
액션이 호출될 때마다 (또는, 액션 코드가 실행되는 전에) 어떤 코드를 실행하고 싶은 경우 $beforeFilter 를 사용한다. 이 기능은 접근 제어 (AC) 에 대단히 편리하다 - 액션이 일어나기 전에 유저의 권한을 체크할 수 있다. 실행하고 싶은 컨트롤러의 액션을 배열을 사용하여 이 변수에 설정한다:
- class ProductsController extends AppController
{
var $beforeFilter = array('checkAccess');
function checkAccess()
{
//유저의 ID를 체크하여 액세스하는 로직은 여기에....
}
function index()
{
//이 액션이 호출되면, checkAccess() 가 처음 호출된다.
}
}
$components
$helpers 와 $uses 와 같이, 필요한 컴포넌트를 불러 올 때 사용할 수 있다 :
- var $components = array('acl');
7.4. 컨트롤러 파라미터#
컨트롤러의 파라미터는 Cake 컨트롤러의 $this->params 로 액세스가능하다. 이 변수는, 컨트롤러에 데이타를 입력하고, 현재의 리퀘스트에 관한 정보로 액세스할 수 있게 한다. $this->params 의 가장 일반적인 사용 방법은, POST 또는 GET 방식에 의해 컨트롤러에 넘겨받은 정보로 액세스 한다
$this->data
는, HTML 헬퍼의 폼에 의해 컨트롤러에 전송된 POST 데이타를 다룰 때 사용한다.
- // 폼의 작성을 위해 HTML Helper 가 사용된다.
$html->input('User/first_name');
// HTML 이 표시되면 다음과 같다 :
<input name="data[User][first_name]" value="" type="text" />
// POST 로 전송되면
// $this->data['User']['first_name'] 안에 나타난다
Array
(
[data] => Array
(
[User] => Array
(
[username] => mrrogers
[password] => myn3ighb0r
[first_name] => Mister
[last_name] => Rogers
)
)
)
$this->params['form']
모든 폼의 POST 데이터가 여기에 저장된다. $ _FILES 에 있는 정보도 포함된다.
$this->params['bare']
현재의 레이아웃이 노출(bare)이라면, '1' 이 입력된다. 아니면, '0' 이 입력된다.
$this->params['ajax']
현재의 레이아웃이 ajax 라면, '1' 이 입력된다. 아니면, '0' 이 입력된다.
$this->params['controller']
리퀘스트를 다루는 현재의 컨트롤러명이 들어 간다. 예를 들면, URL /posts/view/1 이 호출된 경우, $this->params['controller'] 는 "posts" 가 된다.
$this->params['action']
리퀘스트를 다루는 현재의 액션명이 들어 간다. 예를 들면, URL /posts/view/1 이 호출된 경우, $ this->params['action'] 은, "view" 가 된다.
$this->params['pass']
현재 리퀘스트에 넘겨 받은 GET 쿼리가 들어 간다. 예를 들면, URL /posts/view/?var1=3&var2=4 가 호출된 경우, $this->params['pass'] 는 "?var1=3&var2=4" 가 된다.
$this->params['url']
리퀘스트된 현재의 URL이, 취득한 키-값(key-value pairs)과 함께 들어 간다. 예를 들면, URL /posts/view/?var1=3&var2=4 가 호출된 경우, $this->params['url'] 는 다음과 같다:
- [url] => Array
(
[url] => posts/view
[var1] => 3
[var2] => 4
)
Comments (0)