일반적으로 PHP 작업시 아래처럼 프로그래밍과 디자인을 동시합니다.
<?php $point = $sum['point']; $sell_price = $sum['price']; ?> <tr> <td class="sod_img"><?php echo $image; ?></td> <td> <input type="hidden" name="it_id[<?php echo $i; ?>]" value="<?php echo $row['it_id']; ?>"> <input type="hidden" name="it_name[<?php echo $i; ?>]" value="<?php echo get_text($row['it_name']); ?>"> <?php echo $it_name.$mod_options; ?> </td> </tr> <?php if ($send_cost > 0) { // 배송비가 0 보다 크다면 (있다면) ?> <dt class="sod_bsk_dvr">배송비</dt> <dd class="sod_bsk_dvr"><strong><?php echo number_format($send_cost); ?> 원</strong></dd> <?php } ?>
그렇기에 전문분야가 각기 다른 개발자들은 프로그래밍도 하고, 디자인도 해야합니다.
만약 한 디자이너가 프로그래밍을 못할 경우 개발참여를 할 수 없습니다.
왜냐면 디자이너가 디자인만 하고, 중간에서 손 놓아버리면 프로그래머는 어디서 부터 시작해야 될지 모르기때문에 개발이 느려집니다.
하지만, XE에서는 프로그래밍 작업과 디자인 작업을 분리해서 할 수 있습니다.
즉, 프로그래머는 프로그래밍만 ,디자이너는 디자인만 담당할 수 있다는 말입니다.
그렇게 하면 각각 전문분야만 다루게 되므로 개발의 효율을 높일 수 있습니다.
그 이유는 무엇일까요?
프로그래밍을 할 수 있는 PHP파일과 디자인을 할 수 있는 HTML 템플릿 파일이 나누어져있습니다.
HTML 템플릿 파일이란? 페이지 구성을 할 수 있는 HTML 파일입니다. XE에서 그 템플릿 파일을 불려와 화면출력을 합니다.
그 템플릿에서는 HTML과 XE문법이 존재합니다. 그 XE문법으로 PHP처럼 동적인 페이지를 구현할 수 있습니다.
XE문법이 정확히 무엇인가요?
HTML 템플릿 파일에서만 사용할 수 있는 XE전용 문법이라고 할 수 있습니다.
XE문법을 사용하면 HTML 템플릿 파일에서 PHP처럼 동적인 페이지를 구현할 수 있습니다.
XE는 최종결과물에서 쓰일 HTML 템플릿 파일을 읽을 때 XE문법을 해석하여 PHP코드로 컴파일하게 됩니다.
바로 아래처럼 말입니다.
Before 템플릿 파일에서 XE문법사용
<section cond="count($lang->find_account_question_items)>1"> <h1>{$lang->cmd_find_member_account_with_email_question}</h1> <p>{$lang->about_find_account_question}</p> <div cond="$XE_VALIDATOR_MESSAGE && $XE_VALIDATOR_ID == 'modules/member/skin/default/find_member_account/2'" class="message {$XE_VALIDATOR_MESSAGE_TYPE}"> <p>{$XE_VALIDATOR_MESSAGE}</p> </div> <form action="/" method="get" ruleset="@find_member_account_by_question"> <input type="hidden" name="module" value="member" /> <input type="hidden" name="mid" value="{$mid}" /> <input type="hidden" name="document_srl" value="{$document_srl}" /> <input type="hidden" name="act" value="procMemberFindAccountByQuestion" /> <input type="hidden" name="success_return_url" value="{getUrl('', 'act', 'dispMemberGetTempPassword')}" /> <input type="hidden" name="page" value="{$page}" /> <input type="hidden" name="xe_validator_id" value="modules/member/skin/default/find_member_account/2" /> <div> <input type="text" name="user_id" required placeholder="{$lang->user_id}" title="{$lang->user_id}" cond="$identifier == 'user_id'" /> </div>
After 컴파일 (XE문법 -> PHP 코드로 변환)
<?php if(count($__Context->lang->find_account_question_items)>1){ ?><section> <h1><?php echo $__Context->lang->cmd_find_member_account_with_email_question ?></h1> <p><?php echo $__Context->lang->about_find_account_question ?></p> <?php if($__Context->XE_VALIDATOR_MESSAGE && $__Context->XE_VALIDATOR_ID == 'modules/member/skin/default/find_member_account/2'){ ?><div class="message <?php echo $__Context->XE_VALIDATOR_MESSAGE_TYPE ?>"> <p><?php echo $__Context->XE_VALIDATOR_MESSAGE ?></p> </div><?php } ?> <?php Context::addJsFile("./files/ruleset/find_member_account_by_question.xml", FALSE, "", 0, "body", TRUE, "") ?><form action="/" method="get" ><input type="hidden" name="error_return_url" value="<?php echo htmlspecialchars(getRequestUriByServerEnviroment(), ENT_COMPAT | ENT_HTML401, 'UTF-8', false) ?>" /><input type="hidden" name="vid" value="<?php echo $__Context->vid ?>" /><input type="hidden" name="ruleset" value="@find_member_account_by_question" /> <input type="hidden" name="module" value="member" /> <input type="hidden" name="mid" value="<?php echo $__Context->mid ?>" /> <input type="hidden" name="document_srl" value="<?php echo $__Context->document_srl ?>" /> <input type="hidden" name="act" value="procMemberFindAccountByQuestion" /> <input type="hidden" name="success_return_url" value="<?php echo getUrl('', 'act', 'dispMemberGetTempPassword') ?>" /> <input type="hidden" name="page" value="<?php echo $__Context->page ?>" /> <input type="hidden" name="xe_validator_id" value="modules/member/skin/default/find_member_account/2" /> <div> <?php if($__Context->identifier == 'user_id'){ ?><input type="text" name="user_id" required placeholder="<?php echo $__Context->lang->user_id ?>" title="<?php echo $__Context->lang->user_id ?>" /><?php } ?> </div>
참고로 컴파일된 코드는 속도를 위해 캐시폴더에 저장되니, 살펴보세요. (경로 : ./files/cache/template_compiled)
XE의 화면출력(HTML)의 요약하자면 아래와 같습니다.
템플릿 파일지정 -> 템플릿 파일 Load -> 템플릿 파일 Compile (XE문법 -> PHP 코드로 변환) ->(레이아웃이 있으면 합침) -> 출력
XE 문법은 크게 3가지 종류로 나뉩니다.
1. HTML 주석형태 (XE 전버전에서 사용가능)
<!--#include("불려올 템플릿 파일")--> : 다른 템플릿파일을 컴파일하여 불려와 삽입합니다.
예) <!--#include("./item_apply.html")-->
<!--%load_js_plugin("플러그인 이름")--> : ./common/js/plugins에 있는 자바스크립트 플러그인들을 불려올 수 있습니다.
./common/js/plugins에 있는 폴더이름이 플러그인 이름이 됩니다.
Context::loadJavascriptPlugin("플러그인 이름") 과 같은 역할을 합니다.
예) <!--%load_js_plugin("filebox")-->
<!--%import("불려올 파일")--> : js , xml, css 파일을 불려올 수 있습니다.
Context::loadFile("불려올 파일") 과 같은 역할을 합니다.
XML일경우 Filter XML로 인식해 Filter XML을 자바스크립트로 컴파일해서 불려옵니다.
다만, 파일이름이 lang.xml 일경우 언어파일로 인식해 불려옵니다. Context::loadLang("불려올 파일") 과 같은 역할을 합니다.
예) <!--%import("./css/common.css")-->
<!--%unload("불려온 파일")--> : 이미 불려온 js , css 파일을 불려오지못하게 합니다.
Context::unloadFile("불려온 파일") 과 같은 역할을 합니다.
예) <!--%unloadFile("./css/common.css")-->
<!--@PHP문--> : php의 if, switch, for, foreach, while문을 사용합니다.
{@ PHP코드}에다 if,for,for등.. PHP문을 쓸 경우 if{ .. }(if문 괄호)와 같이 PHP괄호,XE 괄호가 서로 겹쳐 오작동이 일어납니다.
오류의 예 : {@ if(1==1){} 1은 1이다 {@ }}
그래서 <!--@PHP문-->을 사용해 "<!--@if(1==1)-->1은 1이다<!--@end-->"와 같이 사용하면 오류도 없고, 보기에도 좋습니다.
* 사용가능한 <!--@PHP문-->
- <!--@foreach( ... )-->
- <!--@for( ... )-->
- <!--@switch( ... )-->
- <!--@break-->
- <!--@case( ... )-->
- <!--@default-->
- <!--@if( ... )-->
- <!--@elseif( ... )->
- <!--@else-->
- <!--@end-->
2. HTML 가상 속성 형태 (XE Core 1.5부터 사용가능)
HTML태그에 가상 속성을 붙여 if문과 foreach,for,while 문과 같은 동작을 수행합니다.
사용할 수 있는 가상 속성은 두가지입니다.
- cond : if문과 같이 조건에 따라 해당 태그를 표시합니다.
예) <div cond="$a == 1" class="ay">변수a는 1이다.</div>
- loop : foreach,for,while 문과 같이 조건에 따라 해당 태그를 반복적으로 표시합니다.
for 예) <div loop="$i = 1; $i<=10; $i++" class="ay">10번 반복된다. 현재순번 : {$i}</div>
foreach 예) <div loop="$list => $key,$val" class="ay">{$key}번 제목 : {$val->title}</div> ("$list => $val" 식으로도 가능)
while 예) <div loop="$a <= 10" class="ay">변수a가 100이 될때까지 멈추지않아! {@ $a++}</div>
아래와 같은 형식으로 사용합니다. (가상속성과 조건에 따라 태그자체가 표시됨 or 표시안됨)
<태그 가상속성(cond,loop)="조건">
내용
</태그>
* 이 문법형태는 태그 가상속성 형태이므로 태그가 없으면 사용하지못합니다. (태그가 있어야 속성도 쓰지요...;;)
-> 마땅히 사용할 태그가 없을 때는 <block>라는 가상태그를 쓰면 됩니다. 이 태그는 컴파일시 자동제거되어, 출력시 표시되지않습니다.
예) <block cond="$oDocument->hasUploadedFiles()" class="fileList"> ... </block>
* HTML태그의 속성에 XE가상속성을 부여할 수도 있습니다.
속성|cond=" 조건 " 형식으로 쓰면 조건에 따라 속성이 표시되거나 표시되지 않습니다.
단, 속성과 |cond=" 속건 " 사이는 뛰워쓰면 안됩니다.
예) <a href="#" class="category"|cond="$category=='Y'">category사용시 빨간색 테두리가 생깁니다.</a>
! 속성 "cond"만 가능합니다. 속성|loop=" 조건 " 형식은 없습니다.
3. {} 형태 (XE 전버전에서 사용가능)
템플릿 파일에서 php코드를 사용할 수 있습니다.
{$변수명} : 변수에 담긴 값 출력 -(컴파일)-> <?php echo $변수명 ?>
{@ PHP코드} : PHP 코드 실행 -(컴파일)-> <?php PHP코드 ?>
& 참고사항
* ./classes/template/TemplateHandler.class.php에서 HTML 템플릿 파일의 컴파일을 담당합니다.
* 레이아웃도 일종의 템플릿파일이므로 XE문법을 사용할 수 있습니다.
* 컴파일된 것을 보면 $__Context라는 변수가 있는 데.. 이 변수에는 Context::set(변수이름,값)으로 저장한 모든 변수가 담겨있습니다
그래서 act메서드에서 템플릿 파일에 변수를 넘겨줄때는 Context::set(변수이름,값)으로 저장해 변수를 사용하면 됩니다.
자세한 구조는 다음과 같습니다.
$__Context변수에는 $GLOBALS['__Context__'] 라는 글로벌 변수가 저장되어있습니다.
$__Context = &$GLOBALS['__Context__'];
그리고 $GLOBALS['__Context__']는 ./classes/context/Context.class.php의 set()으로 저장한 모든변수들을 담고있습니다.
* 템플릿 파일 지정은 모듈에서 아래와 같이 할 수 있습니다.
- $this->setTemplatePath(템플릿파일 위치경로);
- $this->setTemplateFile(템플릿파일이름 (.html은 붙일필요없음));
* "<!--//주석-->"형태로 템플릿 파일에서 주석을 작성할 수 있습니다. 물론 컴파일시 이 주석은 제외됩니다.
* 컴파일시 ruleset 코드도 실제 자바스크립트로 변환됩니다.
* 컴파일시 이미지 상대경로도 실제 경로로 변환됩니다.