Erzsamatory Weblog


※ 외국 문서 번역 자료입니다.

원문: Fundamentals - Controller (http://goo.gl/RH26me)


컨트롤러는 CController 또는 CController를 확장하는 클래스의 인스턴스를 의미합니다. 컨트롤러 인스턴스는 사용자가 요청하면 어플리케이션 객체에서 생성합니다. 컨트롤러가 실행될 때, 이것은 적당한 결과물을 산출하기 위해서 사용자가 요청한 액션을 수행합니다. 액션은 컨트롤러 클래스 메소드의 하나로, 이 액션 메소드의 이름은 action으로 시작합니다.

각각의 컨트롤러는 기본 액션을 가지고 있습니다. 유저가 요청 보낼 때, 특별히 액션이 정해져 있지 않으면 컨트롤러의 기본 액션이 실행됩니다. 기본적으로 기본 액션은 index라고 이름을 붙입니다. 이것은 공용 인스턴스 변수 (CController::defaultAction)을 설정함으로써 변경할 수 있습니다.

다음의 코드는 사이트 컨트롤러의 기본 액션과 Contact 액션을 정의하는 방법입니다.

class SiteController extends CController
{
    public function actionIndex()
    {
        // ........
    }
    
    public function actionContact()
    {
        // ........
    }
}

사용자 삽입 이미지


경로 (Route)


컨트롤러와 액션은 ID를 이용해서 식별됩니다. 컨트롤러 ID의 포맷은 path/to/xyz와 같이 나타내고, 컨트롤러는  protected/controllers/path/to/XyzController.php 와 같이 파일로 저장됩니다. xyz 부분은 실제 컨트롤러의 이름으로 바꾸어 사용합니다. 예를 들어, 포스트 컨트롤러는 protected/controllers/PostController.php 에 저장됩니다. 액션 ID는 컨트롤러 클래스 메소드 이름에서 접두사인 action을 제외한 부분입니다. 예를 들어, 컨트롤러 클래스가 actionEdit라는 메소드를 가지고 있다면, 이 메소드로 알 수 있는 액션 ID는 edit입니다.

개발자는 경로를 통해 컨트롤러나 액션을 요청합니다. 경로는 슬래시(/)로 구분하며, 컨트롤러 ID와 액션 ID에 연관되어 만들어집니다. 예를 들어, 경로 post/edit는 포스트 컨트롤러의 edit 액션을 의미합니다. 기본적으로 URL http://hostname/index.php?r=post/edit 는 포스트 컨트롤러의 edit 액션을 실행합니다.

기본적으로 경로는 대소문자를 구분합니다. 이것은 CUrlManager::caseSensitive 변수를 수정함으로써 대소문자를 구분하지 않게 만들 수 있습니다. 대소문자를 구분하지 않는 환경에서는 컨트롤러 파일을 포함하는 디렉터리는 모두 소문자로 만들어져야 하고, 컨트롤러 맵과 액션 맵도 소문자로 이루어진 키를 가지는 규칙을 따라야 합니다.

어플리케이션은 모듈을 가질 수 있습니다. 모듈에 포함되는 컨트롤러와 액션의 경로는 moduleID/controllerID/actionID 와 같습니다. 더 자세한 설명은 모듈 편을 참고하십시오.


컨트롤러 인스턴스 생성


컨트롤러 인스턴스는 CWebApplication이 사용자 요청을 처리할 때 생성됩니다. 컨트롤러의 ID가 주어지면, 어플리케이션은 다음의 규칙을 따라 요청받은 컨트롤러의 파일이 어디에 위치해 있는지를 판단합니다.

- CWebApplication::catchAllRequest가 정의되어 있는 경우, 컨트롤러는 이 변수에서 설정한 값으로 생성되며, 개발자가 지정한 컨트롤러 ID는 무시됩니다. 이 방법은 어플리케이션을 테스트하거나 고정된 페이지를 출력할 때 사용합니다.

- 컨트롤러 ID가 CWebApplication::controllerMap에 정의되어 있다면, 해당 컨트롤러의 설정 값은 컨트롤러 인스턴스를 생성할 때 사용됩니다.

- 컨트롤러 ID가 path/to/xyz 포맷일 때, 컨트롤러 클래스의 이름은 XyzController 라는 것을 추정할 수 있으며, 해당 클래스 파일이 protected/controllers/path/to/XyzController.php 에 있다는 것을 또한 추정할 수 있습니다. 예를 들어, 컨트롤러 ID가 admin/user 라면, User 컨트롤러라는 것을 알 수 있으며, 해당 클래스 파일은 protected/controllers/admin/UserController.php 로 저장됩니다. 만약, 해당 디렉터리에 클래스 파일이 없다면 404 CHttpException이 발생합니다.

모듈이 사용될 때에는 위 과정이 약간 다릅니다. 특히, 어플리케이션은 해당 ID가 모듈 내의 컨트롤러인지 확인하고, 만약 맞다면, 모듈 인스턴스가 생성되고 컨트롤러 인스턴스가 실행됩니다.

액션


앞서 설명했듯이, 액션은 action 접두사를 가지는 메소드로서 정의됩니다. 더욱 발전된 수준으로 액션이 클래스로 정의될 수 있으며, 해당 액션이 요청될 때 컨트롤러는 해당 액션의 클래스 인스턴스를 생성하게 됩니다. 이것은 액션이 재사용될 수 있다는 것을 의미합니다.

다음은 액션을 클래스로 정의하는 예시입니다.

class UpdateAction extends CAction
{
    public function run()
    {
        // place the action logic here
    }
}


컨트롤러가 이러한 액션을 인식할 수 있게 하려면 컨트롤러 클래스의 actions() 메소드를 오버라이드해야 합니다.

class PostController extends CController
{
    public function actions()
    {
        return array(
            'edit' => 'application.controllers.post.UpdateAction',
        );
    }
}


위에서 볼 때, application.controllers.post.UpdateAction 라는 ID를 사용했다는 것은 해당 액션 클래스 파일이 protected/controllers/post/UpdateAction.php 라는 것을 의미합니다.

protected/
    controllers/
        PostController.php
        UserController.php
        post/
            CreateAction.php
            ReadAction.php
            UpdateAction.php
        user/
            CreateAction.php
            ListAction.php
            ProfileAction.php
            UpdateAction.php


액션 매개변수 바인딩


1.1.4 버전부터 Yii Framework는 자동적으로 액션 매개변수를 바인딩합니다. 즉, 컨트롤러 액션 메소드는 매개변수를 정의할 수 있으며, 이것은 Yii Framework에 의해서 $_GET 변수의 값을 가지게 됩니다.

액션 매개변수 바인딩이 어떤 것인지 정확하게 알기 위해서, 먼저 포스트 컨트롤러에 create 액션이 있다고 가정합시다. 그리고 이 액션은 다음 두 개의 매개변수를 가집니다.

- category: 새 포스트가 만들어지는 카테고리의 ID를 저장하는 상수 변수
- language: 새 포스트가 작성된 언어를 저장하는 문자열 변수

위와 같이 되어 있다면, 다음과 같이 $_GET 변수에서 해당 매개변수의 값을 가져오는 귀찮은 코드가 필요할 것입니다.

class PostController extends CController
{
    public function actionCreate()
    {
        if(isset($_GET['category']))
            $category=(int)$_GET['category'];
        else
            throw new CHttpException(404,'invalid request');
        
        if(isset($_GET['language']))
            $language=$_GET['language'];
        else
            $language='en';
        
        // ... fun code starts here ...
    }
}


하지만 1.1.4 버전부터는 액션 매개변수를 활용하여 이전보다는 더욱 편리하게 코딩할 수 있게 되었습니다.

class PostController extends CController
{
    public function actionCreate($category, $language='en')
    {
        $category=(int)$category;
        
        // ... fun code starts here ...
    }
}


액션 매소드 actionCreate에 두 개의 매개변수를 추가했다는 사실을 명심해야 합니다. 이 매개변수의 이름은 가져오고자 하는 $_GET 변수의 그것과 반드시 일치해야 합니다. $language 매개변수의 경우에는 기본값이 en으로 설정되어 있기 때문에 실수로 인하여 $_GET 변수의 그것을 가져오지 못하더라도 오류가 발생하지 않지만, $category 매개변수는 기본값이 설정되어 있지 않기 때문에, 만약 $_GET 변수에서 원하는 값을 가져오지 못한다면, 400 CHttpException이 발생합니다.

1.1.5 버전부터는 액션 매개변수에 배열(array) 타입도 사용할 수 있게 되었습니다. 이 때에는 다음과 같이 코딩할 수 있습니다.

class PostController extends CController
{
    public function actionCreate(array $categories)
    {
        // Yii will make sure that $categories is an array
    }
}


위 코드를 보면 $categories 메소드 정의에 array 키워드를 사용하였는데, 이렇게 함으로써, $_GET['categories'] 변수가 단순한 문자열이라면, 해당 문자열을 포함하는 간단한 배열로 해당 매개변수에 저장됩니다.

매개변수가 정의될 때 array 키워드 없이 정의된다면, 해당 매개변수는 배열이 아닌 스칼라 변수로 정의됩니다. 이 경우, $_GET 변수를 통해 정의되어야 하는 배열 변수 때문에 HTTP exception이 발생합니다.

1.1.7 버전부터는 매개변수 자동 바인딩을 클래스 기반 액션으로까지 확장해서 사용할 수 있습니다. 액션 클래스의 run() 메소드가 몇 개의 매개변수를 가질 때, 이 매개변수의 값은 상응하는 $_GET 변수의 그것이 됩니다.

class UpdateAction extends CAction
{
    public function run($id)
    {
        // $id will be populated with $_GET['id']
    }
}


필터


필터는 컨트롤러 액션이 실행된 후 또는 실행되기 전 작동하도록 설정된 코드입니다. 예를 들어, 액세스 컨트롤 필터(access controll filter)는 요청된 액션이 실행되기 전에 요청한 사용자가 해당 액션을 실행할 권한이 있는지를 확인합니다. 퍼포먼스 필터는 액션이 실행될 때 소요된 시간을 측정하는데 사용됩니다.

액션은 여러 개의 필터를 가지고 있습니다. 액션 실행에 있어서 미리 정의된 필터 목록에 따라 해당 필터가 실행됩니다. 필터는 액션이나 나머지 아직 실행되지 않은 필터의 실행을 방지할 때 사용됩니다.

필터는 컨트롤러 클래스의 메소드로 정의되는데, 메소드 이름은 filter로 시작됩니다. 예를 들어, 메소드 filterAccessControlaccessControl 필터를 의미합니다. 필터 메소드는 반드시 다음과 같이 정의되어야 합니다.

public function filterAccessControl($filterChain)
{
    // call $filterChain->run() to continue filter and action execution
}


$filterChain 변수는 CFilterChain의 인스턴스를 저장합니다. CFilterChain은 요청된 액션의 필터 목록을 저장하는 인스턴스입니다. 개발자는 필터 메소드 내에 CFilterChain->run() 를 사용하여 필터와 액션의 실행을 계속할 수 있습니다.

필터 또한 CFilter 또는 이 클래스의 자식 클래스의 인스턴스가 될 수 있습니다. 다음은 새 필터 클래스를 생성하는 코드입니다.

class PerformanceFilter extends CFilter
{
    protected function preFilter($filterChain)
    {
        // logic being applied before the action is executed
        return true; // false if the action should not be executed
    }
 
    protected function postFilter($filterChain)
    {
        // logic being applied after the action is executed
    }
}


필터를 액션에 적용시키기 위하여, 개발자는 CController::filters() 메소드를 오버라이드해야 합니다. 이 메소드는 필터 설정 값을 배열에 저장하여 반환합니다. 다음은 하나의 예시입니다.

class PostController extends CController
{
    ......
    public function filters()
    {
        return array(
            'postOnly + edit, create',
            array(
                'application.filters.PerformanceFilter - edit, create',
                'unit'=>'second',
            ),
        );
    }
}


위 소스코드는 두 개의 필터ㅡpostOnlyPerformanceFilter를 정의하고 있습니다. postOnly 필터는 메소드 기반 필터입니다. 반면에 PerformanceFilter 필터는 객체(클래스) 기반 필터입니다. 경로 application.filters.PerformanceFilter 는 필터 파일이 protected/filters/PerformanceFilter 라는 것을 의미합니다. 개발자는 PerformanceFilter 필터 설정을 할 때에 배열을 사용하며, 이것은 이 필터를 초기화할 때 초기 값으로 사용됩니다. 위 소스코드에서는 PerformanceFilterunit 값을 'second'로 설정하였습니다.

플러스(+)나 마이너스(-) 같은 연산자는 해당 필터가 어떤 액션에 적용이 되는지, 적용이 되지 않는지를 결정합니다. 위 소스코드에서는 postOnly 필터는 editcreate 액션에만 적용되는 반면에, PerformanceFilter 필터는 editcreate 액션을 제외한 모든 액션에 적용됩니다. 필터 설정에 플러스(+) 또는 마이너스(-)가 없다면 그것은 모든 액션에 적용된다는 것을 의미합니다.


목차
1. 시작하기
     1-1. Yii란 무엇인가?
     1-2. 설치
     1-3. 아파치 웹서버와 Nginx 설정
     1-4. 첫 Yii 어플리케이션 생성

2. 기본 개념
     2-1. 모델-뷰-컨트롤러 (MVC)
     2-2. 엔트리 스크립트
     2-3. 어플리케이션
     2-4. 컨트롤러 (현재 페이지)
     2-5. 모델
     2-6.
     2-7. 컴포넌트
     2-8. 모듈
     2-9. 경로 별칭과 네임스페이스
     2-10. 일반 규칙
     2-11. 개발 흐름 (Workflow)
     2-12. MVC 예제

3. 양식(Form) 사용 연습
     3-1. 개요
     3-2. 모델 생성
     3-3. 액션 생성
     3-4. 양식 생성
     3-5. 테이블 추출
     3-6. 양식 생성기 사용하기

4. 데이터베이스 사용 연습
     4-1. 개요
     4-2. DB 액세스 객체
     4-3. 쿼리 빌더
     4-4. 동적 레코드
     4-5. Relational Active Record
     4-6. 데이터베이스 변환

5. 캐싱
     5-1. 개요
     5-2. 데이터 캐시
     5-3. 부분 캐시
     5-4. 페이지 캐시
     5-5. 동적 컨텐츠

6. Yii 확장
     6-1. 개요
     6-2. 확장 사용하기
     6-3. 확장 생성하기
     6-4. 써드파티 라이브러리 사용하기

7. 테스트
     7-1. 개요
     7-2. Defining Fixtures
     7-3. Unit Testing
     7-4. Functional Testing

원문: http://www.yiiframework.com/doc/guide/
http://www.erzsamatory.net/trackback/32

건전한 댓글 문화를 만들어주시기 바랍니다 ^^
불건전한 댓글이 등록되는 경우 관리자의 임의적 판단으로 삭제될 수 있음을 미리 공지드립니다.

비밀글로 작성하기