XE Trigger 완전 정복하기 2편

Study4U 2014.08.03 21:04 조회 수 : 789

목차
  • Trigger 동작 원리
  • Trigger DB
  • Trigger를 이용하기 위해 사용하는 함수
  • 함수기능 설명
  • Trigger 등록해보기
  • 2편 마무리

Trigger 동작 원리

그림5.jpg


그림5)

그림5)은 Trigger의 동작원리를 나타냅니다. insertDocument에서 수행문 처리 중에 Trigger를 호출하게 될때 우선적으로 DB에 접속하여 자신이 선언한 이름으로 등록된 Trigger가 있는지 조회하게 됩니다. 조회결과 등록된 Trigger가 있다면 해당 Trigger를 수행하게 됩니다.

Trigger DB


xe_module_trigger
trigger_name varchar(80)
called_position varchar(15)
module varchar(80)
type varchar(15)
called_method varchar(80)

그림6.jpg


그림6)

Trigger는 xe_module_trigger라는 DB 테이블을 이용하여 처리합니다. 모듈을 제작할때 Trigger를 사용하고자 한다면 이 테이블에 원하는 호출 내용을 등록하고 사용을 하게 됩니다.

Trigger를 이용하기 위해 사용하는 함수


ModuleHandler::triggerCall()
moduleModel::getTriggers()
moduleModel::getTrigger()
moduleController::insertTrigger()
moduleController::deleteTrigger()

우리가 사용하려는 Trigger의 주요 함수들입니다. 호출방법에 있어서는 ModuleHandler::triggerCall()이외에는 모두 인스턴스로 생성하여 불러와야 합니다.

moduleModel::getTrigger(...); -> X
 
$oModuleModel = &getModel('module');
$oModuleModel->getTrigger(...); -> O

그럼 간단히 위의 함수의 역할에 대해 소개해보겠습니다.

ModuleHandler::triggerCall()
자신을 지정한 함수를 요청할때 사용하는 명령함수입니다. 1부 그림1)에서 Trigger before, after에 대한 설명이 있었는데 이 함수가 그에 해당됩니다. 이 함수를 내가 수행하고 있는 함수 수행문의 적당한 위치에 선언해 놔야지 다른 함수와의 연계가 가능해집니다.

moduleModel::getTriggers()
triggerCall()내에서 수행하는 함수로 자신을 선언하고 있는 함수들이 몇개나 되는지 테이블에서 조회하여 배열화 시킵니다. 이 함수는 우리들이 활용하는 함수는 아닙니다.

moduleModel::getTrigger()
triggerCall()에 의해 호출되어질 함수가 등록되어있는지를 조회하는 기능입니다. 주요역할로써는 제작모듈.class.php에서 Trigger를 등록하기전에 이미 등록되어있는지를 검사하는데 주로 사용됩니다.

moduleController::insertTrigger()
Trigger를 등록합니다. 이 함수를 이용하여 등록되는 정보는 DB테이블에 등록되며 triggerCall()에 의해 조회 후에 함수를 호출시키게 됩니다. 제작모듈.class.php에서 주로 사용됩니다.

moduleController:: deleteTrigger()
Trigger를 삭제합니다. DB테이블에 등록시켰던 정보를 삭제합니다. 제작모듈.class.php에서 주로 모듈 업데이트에서 사용되거나, 쉬운설치 메뉴에서의 삭제기능을 이용하여 모듈을 삭제할때 주로 사용됩니다.

함수기능 설명


위에서는 간단히 함수에 대한 소개를 하였습니다. 이번에는 조금 더 깊숙히 함수의 기능을 소개해보겠습니다. 기능의 소개는 이해의 편의상 제작 과정에 도움이 되도록 프로세스 순서적으로 나열하겠습니다.

getTrigger()

/**
 * @brief Get specific triggers from the trigger_name
 **/
function getTrigger($trigger_name, $module, $type, $called_method, $called_position)

$trigger_name : Trigger의 이름을 나타냅니다.
여기서 이름이란 triggerCall()에서 호출될때 사용할 이름을 뜻합니다. 이름으로 구분하는 이유는 명확히 역할을 구분하여 함수를 선언하고 호출되게 하기 위함입니다. 현재의 많은 함수들과 앞으로 여러 모듈에서 생길 함수들이 서로 연계를 진행할때 이름의 정의가 없다면 역할이 모호해져서 불필요한 요청이 발생할 수 있기 때문에 Trigger의 이름을 통해 명확히 함수가 호출될 수 있도록 정의하고 있습니다.

호출하는 이름은 아래와 같습니다.

module.dispAdditionSetup
document.insertDocument
comment.updateComment
file.deleteFile
display


이름은 특별히 정해진 규칙은 없으며 triggerCall()에서 처음 정해지는 이름을 기준으로 모든 주요 Trigger함수들이 사용되게 됩니다. 하지만 대체적으로 XE에서는 Trigger의 역할을 이름으로도 쉽게 구분하도록 하기 위해 .(점)을 이용하여 “모듈명.함수명”의 규칙성 문장을 이용하고 있습니다. 그리고 위의 display와 같이 경우에 따라서는 단일 이름으로도 선언할 수 있습니다.

$module : 모듈 이름을 나타냅니다.
여기서의 이름이란 앞으로 triggerCall()에 의해 호출되어질 함수를 담고 있는 모듈 이름을 나타냅니다. 예를 들어 내가 새로운 모듈을 제작하는데 모듈이름이 memorize이고 트리거를 이용해 내 모듈안의 함수를 호출하고 싶다면 모듈 이름을 “memorize”로 적어주셔야합니다.

$type : 모듈 타입을 나타냅니다.
모듈 타입이란 쉽게 설명하면 모듈에서 구성하는 파일의 단위로 이해하시면 쉽습니다. XE의 모듈에서 구성되는 파일은 크게 view, controller, model이 있으며 이 3가지가 타입이 됩니다. 이 타입은 바로 밑에 설명할 $called_method의 값, 즉 함수명이 존재하는 class 명칭으로 사용합니다.

$called_method : 호출하려는 함수 이름을 나타냅니다.
제일 처음 설명한 $trigger_name의 이름을 가지고 조회하여 호출되어질 함수의 이름입니다. 함수의 이름은 모듈을 제작하실때 사용하실 이름이면 되고 특별한 규칙은 없습니다. 하지만 대개 의미적인 구분을 위해 사용하려는 함수앞에 trigger라는 명칭을 붙이게 됩니다.

document.insertDocument => triggerInsertDocument


문서 등록시에는 내 모듈안의 triggerInsertDocument를 호출한다는 의미입니다. 함수명이 서로 동일하므로 이 함수가 무얼 뜻하는지 동작과정을 살펴보지 않아도 함수만 봐도 의미를 파악할 수 있으며 앞에 trigger를 붙여놓음으로써 trigger 처리용 함수라는 것도 쉽게 파악할 수 있게 됩니다.

$called_position : before, after를 나타냅니다.
1부 Trigger의 종류에서 설명한 before, after의 두가지 방식을 나타냅니다.


insertTrigger()

/**
 * @brief Add module trigger
 * module trigger is to call a trigger to a target module
 *
 **/
function insertTrigger($trigger_name, $module, $type, $called_method, $called_position)

$trigger_name : Trigger의 이름을 나타냅니다. 
$module : 모듈 이름을 나타냅니다.
$type : 모듈 타입을 나타냅니다.
$called_method : 호출하려는 함수 이름을 나타냅니다.
$called_position : before, after를 나타냅니다.


triggerCall()

/**
 * @brief call a trigger
 * @param[in] $trigger_name trigger's name to call
 * @param[in] $called_position called position
 * @param[in] $obj an object as a parameter to trigger
 * @return Object
 **/
function triggerCall($trigger_name, $called_position, &$obj)


$trigger_name : Trigger의 이름을 나타냅니다.
여기서 사용하는 이름이 현재 호출하려는 “모듈명.함수명”이 됩니다. 호출되는 자신의 이름을 선언하면 getTrigger(), insertTrigger()들이 이 이름을 가지고 조회 또는 Trigger에 등록을 하게 됩니다.

$called_position : before, after를 나타냅니다.
1부 Trigger의 종류에서 설명한대로 함수내에 수행문 처리의 전 후를 기준으로 before인지 after인지를 선언합니다.

$obj : 정보를 담을 파라미터를 나타냅니다.
활용예에서 보다 더 자세히 다루겠지만 $obj에 담아질 정보의 형태는 배열정보를 담을 수도 있고 그냥 문자열을 담을 수도 있습니다.

$obj->extra_vars1 = ‘a’;
$obj->extra_vars2 = ‘b’;
 
$obj = “설정메뉴입니다.”;

위에보시면 &$obj로 나타나있는데 &의 의미는 참조표현을 나타내는 의미입니다. 

해당 기능에 대해서는 참조표현의 링크를 클릭하셔서 읽어보시기 바라며, 이 기능이 왜 이곳에 들어가는지에 대해서만 잠깐 설명드려보면 triggerCall()에 의해 호출되어지는 함수정보는 하나가 아니라 여러개일 수 있기 때문에 각 함수에서 처리되어 나온 결과를 최종적으로 $obj에 담아서 처리하게 하기위해서 입니다.

$obj->document_srl = 1349;
 
function getModuleSrl(&$obj)
{
    $oModuleModel = &getModel('module');
    $module_info = getModuleInfoByDocumentSrl($obj->document_srl);
    $obj->module_srl = $module_info->module_srl;
}
 
//수행
getModuleSrl($obj);
var_dump($obj);


결과
object(stdClass)#1 (2) {
  ["document_srl"]=>
  int(1349)
  ["module_srl"]=>
  int(123)
}



해당 내용은 Trigger 활용부분에서 다시한번 상세히 설명드리겠습니다.


deleteTrigger()

/**
 * @brief Delete module trigger
 *
 **/
function deleteTrigger($trigger_name, $module, $type, $called_method, $called_position)


$trigger_name : Trigger의 이름을 나타냅니다. 
$module : 모듈 이름을 나타냅니다.
$type : 모듈 타입을 나타냅니다.
$called_method : 호출하려는 함수 이름을 나타냅니다.
$called_position : before, after를 나타냅니다.

Trigger 등록해보기


그럼 이제부터 본격적으로 Trigger를 사용하는 방법을 소개하겠습니다. 우선 Trigger를 등록해보기 위해서는 만드실 모듈이 하나 있으셔야 합니다.

ttest.zip 

document.insertDocument를 이용하여 데이터베이스에 입력을 하고 출력을 하는 간단한 예제 모듈을 제작해보았습니다.

이 모듈에서 Trigger로 수행할 함수의 이름을 triggerInsertTtest()라고 정의해보겠습니다.

1. ttest.class.php에서 Trigger를 등록시킵니다.

class ttest extends ModuleObject
{
    /**
     * @brief 설치시 추가 작업이 필요할시 구현
     **/
    function moduleInstall()
    {
        $oModuleController = &getController('module');
        $oModuleController->insertTrigger('document.insertDocument', 'ttest', 'controller', 'triggerInsertTtest', 'after');
 
        return new Object();
    }
 
    /**
     * @brief 설치가 이상이 없는지 체크하는 method
     **/
    function checkUpdate()
    {
        $oModuleModel = &getModel('module');
        if(!$oModuleModel->getTrigger('document.insertDocument', 'ttest', 'controller', 'triggerInsertTtest', 'after'))
        {
            return true;
        }
 
        return false;
    }
 
    /**
     * @brief 업데이트 실행
     **/
    function moduleUpdate()
    {
        $oModuleModel = &getModel('module');
        $oModuleController = &getController('module');
        if(!$oModuleModel->getTrigger('document.insertDocument', 'ttest', 'controller', 'triggerInsertTtest', 'after'))
        {
            $oModuleController->insertTrigger('document.insertDocument', 'ttest', 'controller', 'triggerInsertTtest', 'after');
        }
 
        return new Object(0,'success_updated');
    }
 
    /**
     * @brief 모듈 삭제 실행
     **/
    function moduleUninstall()
    {
        $oModuleModel = &getModel('module');
        $oModuleController = &getController('module');
 
        if($oModuleModel->getTrigger('document.insertDocument', 'ttest', 'controller', 'triggerInsertTtest', 'after'))
        {
            $oModuleController->deleteTrigger('document.insertDocument', 'ttest', 'controller', 'triggerInsertTtest', 'after');
        }
 
        return new Object();
    }
 
    /**
     * @brief 캐시 파일 재생성
     **/
    function recompileCache()
    {
    }
}


2. triggerInsertTtest()에 수행 정보를 만듭니다.
class ttestController extends ttest
{
 
    /**
     * @brief Initialization
     **/
    function init()
    {
    }
 
    /**
     * @brief Trigger 호출 함수
     **/
    function triggerInsertTtest(&$obj)
    {
        $args->module = $obj->module;
        $args->module_srl = $obj->module_srl;
        $args->document_srl = $obj->document_srl;
        $args->type = 'Y';
 
        $this->insertTtest($args);
    }
 
    /**
     * @brief 정보 추가
     **/
    function insertTtest($args = NULL)
    {
        if($args == NULL)
        {
            return new Object(-1, "msg_error_occured");
        }
 
        // begin transaction
        $oDB = &DB::getInstance();
        $oDB->begin();
 
        $output = executeQuery('ttest.insertTtest', $args);
        if(!$output->toBool())
        {
            $oDB->rollback();
            return new Object(-1, "msg_error_occured");
        }
 
        // commit
        $oDB->commit();
 
        return $output;
    }
}


3. 관리자페이지에서 ttest 모듈의 '설치하기' 버튼을 누릅니다.
 
4. 게시판 모듈에서 글을 등록하고 ttest 모듈에서 결과를 확인합니다.
그림7.jpg



그림7

2편 마무리


Trigger의 보다 상세한 원리와 함수설명, 예제를 통한 실습을 간단히 해보았습니다. 1편보다는 조금 전문적인 이야기가 나왔는데 이해하기 어떠셨나요? 3편에서는 다양한 예제를 통해 본격적인 Trigger 활용법, Trigger가 없는 대상또한 처리할 수 있는 방법 등을 소개하겠습니다.