TIP게시판

제목 HMVC 5.4 & Template_ 타로구조 만들기
글쓴이 타로 작성시각 2012/02/02 04:51:07
댓글 : 2 추천 : 0 스크랩 : 0 조회수 : 18268   RSS
포럼소스를 2.1.0 으로 이식하는 과정에서 조금 욕심이 생겨서 구조를 손보고 있는데 그 결과물이라고 보시면 될듯 합니다. 뷰를 사용함에 있어 php코드들이 디자인(뷰) 파일에 포함되는 문제와 헤더, 바디, 푸터 별개의 뷰를 만들어 관리해야 하는 문제등을 해소하기 위해 만들어진 것입니다.

작동은 잘하는데 손볼곳도 있습니다.

개요:
1. 더 이상 뷰(디자인)파일이 php 확장자를 가지지 않습니다. .html 확장자를 가집니다.
2. 뷰파일과 분리하여 skins 폴더에 디자인파일을 관리하게 됩니다.
3. 이제 디자이너들이 위지웍 에디터로 CI디자인을 할 수 있습니다.(하드코딩이 대세이지만..)
4. (핵심) 하나의 외형 템플릿파일에 body를 로딩합니다. (헤더, 푸터의 모든 내용을 하나로 관리)
5. 콘트롤러별 이미지와 스타일파일등의 서브폴더를 코드화하여 일체화 시켰습니다.

조건:
1. HMVC 5.4 필요.
2. Template_ 2.2.6
3. modules 폴더의 위치가 CI설치 root에 있어야 합니다. (application 폴더안에 있을 경우 오류 발생)
    포럼소스엔 이 문제가 패치되어 있을 예정입니다.

소스 보시고 많은 조언 부탁드립니다.


libraries/template.php
<?php if  ( ! defined('BASEPATH')) exit('No direct script access allowed');

// ------------------------------------------------------------------------

require_once(APPPATH . 'libraries/template_/Template_.class.php');


class Template extends Template_
{
 var $compile_check = true;
 var $compile_dir   = '_compile';
 var $compile_ext   = 'php';
 var $skin          = '';
 var $notice        = false;
 var $path_digest   = true;

 var $prefilter     = 'common';
 var $postfilter    = 'removeTmpCode | arrangeSpace';
 var $permission    = 0777;
 var $safe_mode     = true;
 var $auto_constant = false;

 var $caching       = false;
 var $cache_dir     = '_cache';
 var $cache_expire  = 3600;

 var $template_dir  = '_template';

 var $CI;

 // --------------------------------------------------------------------

 function __construct()
 {
  $this->CI =& get_instance();
  $this->compile_dir = 'var/_compile';

  $currentModule = $this->currentModule();

  $this->template_dir = $this->templateDirectory( $currentModule );
  $file = $this->templateFile( $currentModule );
  $this->define( $currentModule, $file );
 }

 // --------------------------------------------------------------------

 function display( $defineName=false )
 {
  if ( ENVIRONMENT != 'production' ) {
   $this->CI->output->enable_profiler(true);
  }

  if ( $defineName ) {
   $currentModule = $defineName;
  }
  else {
   $currentModule = $this->currentModule();
  }

  $mainContents = $this->fetch($currentModule);

  echo modules::run('layout/frame', $mainContents);
 }

 // --------------------------------------------------------------------

 function templateDirectory( $currentModule )
 {
  $ret = 'modules/' . $currentModule . '/skins';
  if ( is_dir( APPPATH . $ret ) ) {
   $ret = APPPATH . $ret;
  }
  return $ret;
 }

 // --------------------------------------------------------------------

 function templateFile( $currentModule )
 {
  if ( $currentModule == $this->CI->router->fetch_class() ) {
   $ret = $currentModule . '.' . $this->CI->router->fetch_method() . '.html';
  }
  else {
   $ret = $currentModule . '.' . $this->CI->router->fetch_class() . '.' . $this->CI->router->fetch_method() . '.html';
  }

  return $ret;
 }

 // --------------------------------------------------------------------

 function currentModule()
 {
  $module = ( $this->CI->uri->segment(1) == '' ) ? $this->CI->uri->rsegment(1) : $this->CI->uri->segment(1);

  return $module;
 }
}



Template_ 플러그인 prefilter.common.php
(필자주)
- sking 폴더 하위에 4개의 새로운 코드를 만들었습니다.
- 각각 __image, __style, __script, __common
- 이 코들은 html 파일에서 코드로 인식되어 집니다.
- (주) { __image} 형식이 아닙니다. 아래와같이 사용합니다.
<img src="__image/oops.png">


<?php

/* PREFILTER */

function common( $source, $tpl )
{

 $source = str_replace( "__image",  '/' . $tpl->template_dir . '/__image', $source );
 $source = str_replace( "__style",  '/' . $tpl->template_dir . '/__style', $source  );
 $source = str_replace( "__script", '/' . $tpl->template_dir . '/__script', $source  );
 $source = str_replace( "__common", '/' . $tpl->template_dir . '/__common', $source  );

 return $source;
}


필수모듈명 layout
layout.frame.html //이 파일에 BODY를 제외한 모든 디자인을 합니다.
controllers/layout.php

<?php if  ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Layout extends MX_Controller
{

 // --------------------------------------------------------------------

 function Layout()
 {
  parent::__construct();
 }

 // --------------------------------------------------------------------

 function index()
 {
 }

 // --------------------------------------------------------------------

 function frame( $mainContents )
 {

  $this->load->library('template');
  $this->template->template_dir = 'modules/layout/skins';
  $this->template->define('layout', 'layout.frame.html');
  $this->template->assign( 'mainContents', $mainContents );
  $this->template->assign('welcome', 'Hello World');
  $this->template->print_('layout');
 }
}

skins/layout.frame.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
 <HEAD>
  <TITLE> New Document </TITLE>
  <META name="Author" content="">
  <META name="Keywords" content="">
  <META name="Description" content="">
 </HEAD>

 <BODY>

  {mainContents} <!-- 이 코드가 body의 내용을 가지고 있습니다. -->
 
 </BODY>
</HTML>



다른 모듈에서 layout 모듈에 어떻게 body의 내용을 보내는지 아래 파일을 보시면 됩니다.

sample/controllers/sample.php
<?php if  ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Sample extends MX_Controller
{

 // --------------------------------------------------------------------

 function Sample()
 {
  parent::__construct();
 }

 // --------------------------------------------------------------------

 function index()
 {
  $this->load->library('template');
  $this->template->assign( 'oops', 'so good~' );
  $this->template->display();
 }
}
간단하죠? 위 소스를 보시면 템플릿언더바의 template_dir, define, print_ 가 없습니다. 사용하셔도 무방합니다.
template.php 라이브러리 파일을 보시면 이해되실 거에요.

각 body 템플릿파일명은 정해진 규칙이 있습니다. HMVC 모듈의 특성을 살려 규칙을 정했답니다.

모듈명을 포함할 때
모듈명.콘트롤러명.메소드.html

HMVC에서는 모듈명을 지정하지 않을 수도 있답니다.
콘트롤러명.메소드.html

예)
http://localhost/sample
콘트롤러파일: sample.php
템플릿파일: sample.index.html

http://localhost/sample/oops
콘트롤러파일: sample.php
템플릿파일: sample.oops.html

http://localhost/sample/oops/hey
콘트롤러파일: oops.php
템플릿파일: sample.oops.hey.html
눈치 채신분 계신가요?
1. 템플릿파일의 중복성 문제를 해결하기 위해 해당 모듈의 템플릿은 앞에 모듈명이 붙습니다.
2. 모듈에 두개 이상의 콘트롤러를 인식합니다.


------------------

이걸 필요로 하실 분이 계신지는 모르겠으나 최대한 실무에서 격었던 문제점을 보완하여 구조를 만들어 보았습니다. CI의 view를 선호하시는 분들에게는 신의손이 있지만...

바쁜 프로젝트 일정에서 디자인까지 가져다 일일이 코딩하려면 정말 아는 분들은 그 고충을 아실거라 믿습니다. 이 팁의 내용은 디자이너와 개발자 영역을 완벽히 분리시키고자하는 개인적인 집념에서 시작된 것입니다. ^__^

늘 행복하세요~
 다음글 CI_Cache_memcached 드라이버 버그 수정 (2)
 이전글 CI lang팩 -> Javascript lang... (4)

댓글

한대승(불의회상) / 2012/02/02 10:44:54 / 추천 0
좋은 자료 감사 합니다. 타로님의 노하우가 고스란히 녹아 있는 코드 군요. 잘 활용하도록하겠습니다.
밝은미소 / 2012/03/12 13:40:01 / 추천 0
적용해 봤는데 일단 root쪽에 modules의 모두를 위치시키는 것이 아니라 code는 application 밑에 위치시키고 static data는 root로 옮기는게 맞는 것 같습니다. 코드와 데이타가 한곳에 있으면 물론 관리는 편하지만 서로 access 제한이 다르기 때문에 불가피하게 두개로 나눠서 작성하는게 좋을 것 같습니다. 그래서 저는 application 밑에 modules는 위에서 말씀하신대로 작성하고 root쪽은 modules/sample/__image 이런식으로 정리했는데 잘 동작합니다.
 
** current_module 변수를 새로 만들어 prefilter.common.php 의 경로를 수정하면 간단히 정리됩니다.
좋은 팁 알려주신 타로님께 감사합니다. ^^