V. MODULIZATION & PERFORMANCE
23.  스코핑
setScope() 메서드를 사용하여 템플릿을 캡슐화함으로써 모듈간 템플릿 변수의 충돌을 방지하고, 한 페이지에서 같은 템플릿을 여러 번 사용할 수 있습니다.
setScope() 대신 모듈내에서 별도의 템플릿 오브젝트를 생성하고 fetch() 메서드에 의한 결과를 리턴하는 방법을 사용할 수도 있으나 메모리를 비효율적으로 사용하게 됩니다.
메서드 의미 사용법
setScope() 템플릿변수를 캡슐화 $tpl->setScope('file_id');
 스코프와 템플릿변수
$tpl->setScope("file_id"); 이후 할당된 템플릿변수는 해당템플릿("file_id")과 그 하위템플릿내에서만 유효합니다. setScope()에 인자를 지정하지 않으면 기본스코프로 복귀합니다.
index.php
<?php
...
$tpl->define(array(
    'layout'=>'layout.tpl',
    'mod_a' =>'sub.tpl',
    'mod_b' =>'sub.tpl',
    'mod_c' =>'sub.tpl',
));
$tpl->assign('var', 'hello');
$gvar='This is global value.';
$tpl->setScope('mod_a');
$tpl->assign('var', 'This is mod_a value.');
$tpl->setScope('mod_b');
$tpl->print_('layout');
?>
layout.tpl
<body>
<div> mod_a : {# mod_a}</div>
<div> mod_b : {# mod_b}</div>
<div> mod_c : {# mod_c}</div>
<div> layout: {_gvar} - {var}</div>
</body>
sub.tpl
{_gvar} - {var}
>>output
<body>
<div> mod_a : This is global value. - This is mod_a value.</div>
<div> mod_b : This is global value. - </div>
<div> mod_c : This is global value. - hello</div>
<div> layout: This is global value. - hello</div>
</body>
언더바(_)로 시작하는 전역변수는 스코프에 관계없이 어디서나 유효하고, 'mod_b' 는 스코프사용을 지정했으나 해당 스코프의 템플릿변수가 값을 할당받지 못했기 때문에 출력내용이 없습니다.
 스코프를 이용한 모듈작성 예제
mod.listing.php
function listing(&$tpl, $scope) {
    $tpl->define($scope, 'mod.listing.tpl');
    $tpl->setScope($scope);
    $tpl->assign('title', $scope);
    $query = 'select name, date from '.$scope.' where ------';
    $result= mysql_query($query);
    $loop = array();
    while ($data = mysql_fetch_assoc($result)) $loop[] = $data;
    $tpl->assign('list', $loop);
    $tpl->setScope();
}
?>
mod.listing.tpl
<table>
<tr><td colspan=2>{title}</td></tr>
<!--{@ list}-->
<tr><td>{list.name}</td><td>{list.date}</td></tr>

<!--{/}-->
</table>
index.php
<?php
...
include LIB_DIR.'/mod.listing.php';
$tpl = new Template_;
listing($tpl, 'fruit');
listing($tpl, 'sport');
$tpl->define('layout', 'layout.tpl');
$tpl->assign('title', 'My Page');
$tpl->print_('layout');
?>
layout.tpl
<div>{title}</div>
{# fruit}
{# sport}
>>output
<div>My Page</div>
<table>
<tr><td colspan=2>fruit</td></tr>
<tr><td>apple</td><td>2003-09-26</td></tr>
<tr><td>orange</td><td>2003-08-20</td></tr>
<tr><td>melon</td><td>2003-05-05</td></tr>

</table>
<table>
<tr><td colspan=2>sport</td></tr>
<tr><td>running</td><td>2003-07-10</td></tr>
<tr><td>pingpong</td><td>2002-01-01</td></tr>
<tr><td>pushup</td><td>2000-03-06</td></tr>

</table>
 스코프와 파일아이디
스코프사용이 지정된 템플릿 역시 하위템플릿을 가질 수 있는데, 스코프사용이 지정된 템플릿의 파일아이디가 "scope_id" 라면, 하위템플릿은, "scope_id.file_id" 의 형식으로 정의됩니다.
index.php
<?php
...
$tpl->define(array(
    'layout'  =>'layout.tpl',
    'mod'     =>'sub0.tpl',
    'mod.sub1'=>'sub1.tpl',
    'mod.sub2'=>'sub2.tpl',
));
$tpl->setScope('mod');
$tpl->assign(array(
    'var'=>'This is mod value 1.',
    'abc'=>'This is mod value 2.',
    'xyz'=>'This is mod value 3.',
));
$tpl->print_('layout');
?>
layout.tpl
<body>
{# mod}
</body>
sub0.tpl
{var}
{# sub1}
{# sub2}
sub1.tpl
{abc}
sub2.tpl
{xyz}
>>output
<body>
This is mod value 1.
This is mod value 2.
This is mod value 3.
</body>
PHP 파일에서는 "mod.sub1" 이지만, 템플릿파일 내에서는 스코프를 사용하지 않을 때와 똑같이 {# sub1} 임에 유의합니다.
24.  캐슁
캐쉬를 사용하면, 한 번 출력했던 결과물을 저장하였다가, 같은 출력이 필요하다면 프로그램실행을 생략하고 저장된 결과물을 출력하게 됩니다.
Note:
템플릿 파일을 PHP 파일로 변환하는 것은 캐쉬가 아닙니다. 변환파일은 있어도 없어도 좋은 임시적인 것이 아니라, 출력을 위해서 반드시 필요하기 때문입니다. 템플릿언더바와 관련하여 두 가지 캐쉬가 있습니다.

하나는, Zend Performance Suit, TurckMMCache, PHPA 와 같이 설치만 하면 동작하는 캐쉬엔진입니다. 이들 엔진은 한 번 파싱/실행된 PHP 파일의 옵코드(opcode)를 저장하여 다음 번 실행부터는 파싱을 생략하고 옵코드를 바로 실행하게 합니다. 이 때, 템플릿클래스파일 뿐 아니라 템플릿 변환파일 역시 PHP 파일이므로 이들 엔진에 의해 모두 캐슁됩니다.

두 번째는 이 섹션에서 설명하는 캐쉬입니다.
캐쉬를 사용하려면 $caching 속성을 true로 합니다. $cache_dir 속성에는 캐쉬파일이 저장될 디렉토리를 지정(절대 또는 상대경로)하고 웹서버가 읽고 쓸 수 있도록 권한 설정을 합니다.
var $caching   = true;
var $cache_dir = '/path/to/_cache';
 기본 사용법, 만료시간에 의한 캐쉬 갱신
메서드 의미 사용법
setCache() 템플릿에 캐쉬정보 설정 $tpl->setCache('file_id', expiration);
isCached() 캐쉬의 유효여부 판별 $tpl->isCached('file_id');
setCache() 메서드의 첫 번째 인자로 지정된 파일아이디에 대해 캐쉬를 동작시키게 됩니다. 캐쉬가 만들어지면, 두 번째 인자로 지정된 시간동안 사용된 후 갱신됩니다.
index.php
<?php
...
$tpl->define(array(
    'layout'=>'layout.tpl',
    ...,
    ...,
));
$tpl->setCache('layout', 3600); // update per 1 hour
if (!$tpl->isCached('layout')) {
    // code for layout
}
$tpl->print_('layout');
?>
isCached() 메서드는 캐쉬의 유효여부를 리턴하므로, 캐쉬가 유효할 때는 // code for layout  블럭의 실행이 생략됩니다.
setCache() 의 두 번째인자가 0 이면 캐쉬가 만들어진후 갱신되지 않고 계속 사용됩니다. 1 이면 $cache_expire 속성에 설정된 기본값을 사용하게 됩니다.
템플릿 파일별로 캐쉬를 설정할 수 있습니다. 또한 ">"으로 정의한 외부 PHP 파일에도 캐쉬를 설정할 수 있으며, 이것을 통해 템플릿언더바를 캐쉬엔진으로만 사용할 수도 있습니다.
index.php
<?php
...
$cache = new Template_;
$cache->define('>source', '/path/to/other-php-source.php');
$cache->setCache('source', 3600);
$cache->print_('source');
?>
 삭제아이디에 의한 캐쉬 갱신
setCache() 메서드의 세 번째 인자로 삭제아이디를 지정할 수 있으며. 이 아이디를 사용하여 어떤 페이지에서든 $cache_dir 설정이 같다면 만료시간에 관계없이 강제만료시킬 수 있습니다.
$tpl->setCache( 'file_id', 3600, 'clear_id' );
$tpl->clearCache( 'clear_id' );
메서드 의미
clearCache() 인자로 지정된 삭제아이디를 갖는 모든 캐쉬를 삭제함
엔진 내부적으로는 캐쉬헤더를 검색해서 캐쉬파일을 실제로 삭제하는 것이 아니라, 별도의 디렉토리에서 관리되는 삭제아이디정보만을 억세스하므로 빠르게 처리됩니다. clearCache() 에 인자를 지정하지 않으면 모든 캐쉬파일을 삭제합니다.
show-list.php
<?php
...
$tpl->define(array(
    'layout'=>'layout.tpl',
    'main'  =>'shop/listing.tpl',
    ...
));
$tpl->setCache('main', 0, 'book_list');
if (!$tpl->isCached('main')) {
    // code for listing
}
$tpl->print_('layout');
?>
update-list.php
<?php
...
// code for updating list

$tpl->clearCache('book_list');
...
?>
setCache() 의 세 번째 인자로 문자열 대신 여러 개의 삭제아이디를 배열로 지정할 수 있습니다. 이 중 하나라도 clearCache() 로 처리되면 캐쉬는 갱신됩니다.
$tpl->setCache( 'file_id', 1800, array('book', 'magazine') );
또한 여러 캐쉬가 같은 삭제아이디를 가질 경우 삭제아이디가 clearCache() 로 처리되면 해당되는 모든 캐쉬가 갱신됩니다.
세 번째 인자로 빈문자열('')을 지정하면 삭제아이디는 설정되지 않습니다.
 캐쉬아이디에 의한 다중 캐쉬
예를 들어 본 싸이트의 레퍼런스 페이지는 get 으로 전달된 변수의 값에 따라 다른 페이지를 출력합니다. setCache() 메서드의 네 번째 인자를 설정함으로써 각각의 페이지를 캐슁할 수 있습니다.
$tpl->setCache( 'body', 0, '', $_GET );
네 번째 인자는 문자열, 변수, 배열(인덱스배열, 연관배열, 다중배열) 등으로 지정될 수 있고, 엔진 내부적으로는 serialize() 함수에 의해 캐쉬아이디로 설정됩니다. 배열로 지정할 때 필요한 변수만을 포함하여 불필요하게 많은 캐쉬파일이 만들어지지 않도록 합니다.
캐쉬는 사용범위가 제한적이며 적용방식이 다양합니다. 사용시 어려운점이 있다면 게시판에 문의하시기 바랍니다.
 
2003-03-03 ~