일반 PHP를 사용하여 템플릿 시스템을 구성하는 방법은 무엇입니까?


15

나는 stackoverflow 에서이 질문을 읽고있었습니다.

/programming/104516/calling-php-functions-within-heredoc-strings

받아 들여진 대답은 다음과 같은 일반 PHP 템플릿을 수행한다고 말합니다.

template.php :

<html>
    <헤드>
        <title> <? = $ title?> </ title>
    </ head>
    <본체>
        <? = getContent ()?>
    </ body>
</ html>

index.php :

<? php

$ title = '데모 타이틀';

getContent () 함수 {
    return '<p> Hello World! </ p>';
}

include ( 'template.php');

?>

위의 내용은 template.php가 다른 스크립트에 정의 된 변수에 의존한다는 의미에서 잘 구성되어 있지 않습니다. 그리고 include ()를 사용하여 코드를 실행할 때 include('template.php')(include ()를 사용하여 즉시 실행되지 않는 클래스 또는 함수를 포함하는 것과 반대).

더 나은 접근 방법은 템플릿을 함수로 감싸는 것입니다.

template.php :

<? php

함수 템플릿 ($ title, $ content) {
    ob_start (); ?>

<html>
    <헤드>
        <title> <? = $ title?> </ title>
    </ head>
    <본체>
        <? = $ content?>
    </ body>
</ html>

    <? php return ob_get_clean ();
}

?>

index.php :

<? php

require_once ( 'template.php');

print template ( '데모 타이틀', '<p> Hello World! </ p>');

?>

두 번째 방법이 더 낫습니까? 더 좋은 방법이 있습니까?

답변:


12

매개 변수의 이름이 지정되지 않았으므로 두 번째 방법을 사용하지 않습니다.

템플릿 시스템의 작동 방식을 설명하는 잘 작성된 에세이 는 Parr에서 나오며, 종종 템플릿 시스템 및 / 또는 web-mvc 프레임 워크를 작성하는 사람들이 인용합니다.

개인적으로 필자가 일반적으로 선호하는 것은 속성 배열을 사용하여 ArrayObject 클래스를 구현하는 것입니다. 템플릿은를 참조합니다 $this->propertyName. 실제로는 템플릿 객체 $this->property['name']입니다. 간단히 __setand 를 사용하여 간단히 달성 할 수도 있습니다 __get.

class Template {
  private $_scriptPath=TEMPLATE_PATH;//comes from config.php
  public $properties;
  public function setScriptPath($scriptPath){
    $this->_scriptPath=$scriptPath;
  }
  public function __construct(){
      $this->properties = array();
  }
  public function render($filename){

   ob_start();
   if(file_exists($this->_scriptPath.$filename)){
     include($this->_scriptPath.$filename);
    } else throw new TemplateNotFoundException();
    return ob_get_clean();
  }
  public function __set($k, $v){
      $this->properties[$k] = $v;
  }
  public function __get($k){
      return $this->properties[$k];
  }
}

템플릿은 다음과 같습니다.

<html>
      <head>
         <title><?=$this->title?></title>
      </head>
      <body>Hey <?=$this->name?></body>
</html>

호출하면 다음과 같습니다.

$view = new Template();
$view->title="Hello World app";
$view->properties['name'] = "Jude";
echo $view->render('hello.inc');

내가 기억하는 한, 이것은 오래된 Symfony 1.x와 Zend_View 템플릿 엔진이 어떻게 생겼는지에 대한 것입니다.


TinyButStrong 도 비슷한 일을합니다
Izkata

일부 점수의 반복을 어떻게 처리합니까? 별도의 "서브"템플릿을 사용합니까?
Ryan

템플릿에서 $ this를 제거하는 방법이 있는지 궁금합니다 (예 : $ title 또는 $ name).
Ryan

1
@Ryan extract($this->properties);include 문 바로 전에 속성을 변수로 추출하는 데 사용할 수 있습니다 .
Joyce Babu

1

템플릿은 항상 외부 변수에 의존하며 PHP는 동적 언어이므로 컴파일 타임에 해당 변수를 강제로 적용 할 방법이 없습니다. 따라서 첫 번째 접근법은 아마 괜찮을 것입니다. 그래도 여전히 몇 가지 문제가 있습니다.

  • 이 예제는 출력을 HTML 인코딩으로 처리하지 않으므로 잠재적 인 XSS 취약점이 있습니다.
  • 이러한 변수 중 하나가 설정되지 않으면 코드에서 경고가 발생합니다. 경고가 의미가 있는지 알 수 없습니다 (변수는 선택 사항 일 수 있음).

매우 간단한 접근 방식은 바람직하게는 매우 짧은 이름으로 함수를 작성하는 것입니다. 그것을 부르는 것이 _()일반적인 관례 인 것 같습니다. 간단한 버전은 다음과 같습니다.

function _($raw) {
    if (isset($raw)) {
        return htmlspecialchars($raw);
    }
}

그런 다음 템플릿에서 다음을 수행하십시오.

<title><?= _($title) ?></title>

_()기능 과 더 관련이있는 것들 :

  • htmlspecialchars원시 문자열이 아닌 HTML을 HTML에 전달하려는 경우 호출을 재정의 할 수 있도록 두 번째 인수를 지정하십시오 .
  • 그 배열과 객체가 산출되지 않도록 유형 검사를 추가 Array하고 Object오히려 의미있는 (또는 빈 문자열), 그러나.
  • 국제화 지원을 추가하십시오 (아직 다른 주장).
  • 디버그 모드에서 변수 이름을 정의하지 않은 경우 특별한 형식으로 인쇄하십시오. 이 방법으로 템플릿에 문제가 있는지 살짝 볼 수 있습니다.

1

첫 번째 template.phpdreamweaver / bluegriffon / 무엇이든 그대로 로드하는 것이 더 쉽습니다. 하고 서버 측의 잘 웹 디자이너가 편집 한 .

나는 서드 파티 디자이너가 일반적으로 선호하는 방식으로 HTML과 같은 이점을 HTML과 같이 유지하기 위해 처음으로 갈 것입니다 .


어떤 의미에서? 끌어서 놓기를 사용하여 변경할 수 없다는 의미입니까? 문자 적으로 두 번째는 첫 번째와 동일하지만 몇 줄의 PHP가 감겨 있습니다. 따라서 항상 그 구조를 가질 것이라고 가정하면 손으로 편집하기가 더 어렵지 않습니다.
Ryan

1
좋은 템플릿은 개발자에게는 의미가 있고 훌륭한 템플릿은 디자이너에게는 의미가 있습니다.
Citricguy

1

Codeigniter가 내가 가장 좋아하는 프레임 워크이므로 Codeigniter-ish 솔루션을 제안합니다.

class Template {
    protected $path, $data;

    public function __construct($path, $data = array()) {
        $this->path = $path;
        $this->data = $data;
    }

    public function render() {
        if(file_exists($this->path)){
            //Extracts vars to current view scope
            extract($this->data);

            //Starts output buffering
            ob_start();

            //Includes contents
            include $this->path;
            $buffer = ob_get_contents();
            @ob_end_clean();

            //Returns output buffer
            return $buffer;
        } else {
            //Throws exception
        }
    }       
}

템플릿은 다음과 같습니다.

<html>
    <head>
        <title><?=$title?></title>
    </head>
    <body>
        <?=$content?>
    </body>
</html>

그리고 클래스를 인스턴스화하고 배열의 데이터를 생성자 매개 변수로 전달하고 'render'메서드를 호출하여 렌더링합니다.

$data = array('title' => 'My title', 'content' => 'My content');
$tmpl = new Template('template.php', $data);
echo $tmpl->render();

이런 식으로 포함 된 코드를 직접 실행하지 않고 템플릿을 읽을 수 있도록 유지하므로 디자이너가 만족할 것입니다.


-3

Php는 프로그래밍 언어가 아닙니다. 따라서 언어에 실제 유형 시스템이 없으면 강력한 유형의 글을 쓸 수 없습니다. 그러나 PHP-Storm과 같은 IDE가 원하는 트릭을 수행하도록 도울 수 있습니다 ...

뷰 정의 :

interface mySimpleView { 
  public function getTitle(); 
} 

템플릿 파일 :

<?php
/**
* @var $this mySimpleView  <== Your IDE will try to use this type.
*/
?>

<h1><?= $this->getTitle() ?></h1>
<p><?= $this->getContent() ?></p> <!-- <= IDE will warn you !  -->
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.