HEREDOC 문자열 내에서 PHP 함수 호출


91

PHP에서 HEREDOC 문자열 선언은 html 블록을 출력하는 데 정말 유용합니다. $ 접두사로 변수를 구문 분석 할 수 있지만 더 복잡한 구문 (예 : $ var [2] [3])의 경우 식을 {} 중괄호 안에 넣어야합니다.

PHP 5에서는 입니다 실제로 히어 닥 문자열 안에 {} 중괄호 내에서 함수 호출을 할 수 있지만 약간의 작업을 통해 이동해야합니다. 함수 이름 자체는 변수에 저장되어야하며 동적으로 이름이 지정된 함수처럼 호출해야합니다. 예를 들면 :

$fn = 'testfunction';
function testfunction() { return 'ok'; }
$string = <<< heredoc
plain text and now a function: {$fn()}
heredoc;

보시다시피 이것은 단순한 것보다 조금 더 지저분합니다.

$string = <<< heredoc
plain text and now a function: {testfunction()}
heredoc;

첫 번째 코드 예제 외에 함수를 호출하기 위해 HEREDOC에서 벗어나거나 문제를 되돌리고 다음과 같은 작업을 수행하는 것과 같은 다른 방법이 있습니다.

?>
<!-- directly output html and only breaking into php for the function -->
plain text and now a function: <?PHP print testfunction(); ?>

후자는 출력이 출력 스트림에 직접 입력된다는 단점이 있습니다 (출력 버퍼링을 사용하지 않는 한).

그래서, 내 질문의 본질은 : 이것에 접근하는 더 우아한 방법이 있습니까?

응답을 기반으로 편집 : 어떤 종류의 템플릿 엔진이 내 삶을 훨씬 더 쉽게 만들어 줄 것 같지만 기본적으로 평소의 PHP 스타일을 뒤집어 야합니다. 그게 나쁜 건 아니지만 제 관성을 설명 해줍니다.하지만 삶을 더 쉽게 만드는 방법을 찾아야해서 지금은 템플릿을 살펴보고 있습니다.


3
이것은 귀하의 질문에 대한 답은 아니지만 heredoc 문에서 함수 호출에 대한 지원이 부족하기 때문에 일반적으로 heredoc을 인쇄하기 전에 필요한 문자열을 생성합니다. 그런 다음 Text {$string1} Text {$string2} Textheredoc에서 와 같이 간단히 사용할 수 있습니다 .
rinogo

답변:


51

개인적으로는 HEREDOC을 전혀 사용하지 않을 것입니다. 좋은 "템플릿 구축"시스템을 만들지는 않습니다. 모든 HTML은 몇 가지 단점이있는 문자열에 잠겨 있습니다.

  • WYSIWYG에 대한 옵션 없음
  • IDE에서 HTML에 대한 코드 완성 없음
  • 논리 파일에 잠긴 출력 (HTML)
  • 루핑과 같은 더 복잡한 템플릿을 달성하기 위해 지금하려는 것과 같은 해킹을 사용해야합니다.

기본 템플릿 엔진을 가져 오거나 포함과 함께 PHP를 사용합니다. 이것이 언어에 <?php?>구분 기호 가있는 이유 입니다.

template_file.php

<html>
<head>
  <title><?php echo $page_title; ?></title>
</head>
<body>
  <?php echo getPageContent(); ?>
</body>

index.php

<?php

$page_title = "This is a simple demo";

function getPageContent() {
    return '<p>Hello World!</p>';
}

include('template_file.php');

8
echo : <?=$valueToEcho;?>또는 <%=$valueToEcho;%>INI 설정에 따라 약어가 있습니다 .
Peter Bailey

3
내가 그 속기 사용에 대해 읽은 대부분의 모든 것은 그것들을 사용하는 것이 나쁜 관행이라고 말하며 동의합니다. 유감스럽게도 배포 용 코드를 작성하는 경우 해당 INI 설정에 의존 할 수 없으므로 배포 된 코드에 대한 PHP의 "지원"이 필요합니다. FWIW, 다른 사람들의 WordPress 플러그인에서 이러한 속기를 사용했기 때문에 여러 번 버그를 수정해야했습니다.
MikeSchinkel 2012-09-05

1
아니요, 7자를 입력해야하는 것이 부끄러운 것이 아닙니다. 내 문제를 잘못 설명하셨습니다. 내가 관심 있는 타이핑 이 아니라 독서 입니다. 이러한 문자는 소스 코드를 스캔하고 코드가 수행하는 작업을 이해하는 것을 훨씬 더 어렵게 만드는 많은 시각적 노이즈를 생성합니다. 나에게는 적어도 HEREDOC을 읽는 것이 훨씬 쉽습니다. (. 그리고 BTW, 그것은 주어진 HTML 단편하지만의 탈선에 사용되는 방법 지금까지 몇 번이나 7 문자 시간입니다.)
MikeSchinkel

12
Short는 더 멋지고 깨끗하며 읽기 쉽습니다. 귀하의 의견에 <?=$title?>있습니다 많은 <? PHP는 에코 $ 타이틀보다 더 좋은는; ?>. 단점은 배포를 위해 많은 ini가 짧은 태그를 가지고 있다는 것입니다. 하지만 뭘 추측 해 ?? 현재 PHP 5.4 , 짧은 태그 INI 설정에 관계없이 PHP에서 사용할 수 있습니다! 따라서 5.4+ 요구 사항으로 코딩하는 경우 (예를 들어 트레이 트를 사용한다고 가정 해 보겠습니다) 계속해서 멋진 짧은 태그를 사용하십시오 !!
짐보

2
그런데 짧은 태그가 꺼져 있어도 <? = $ blah?>는 기본적으로 5.4에서 활성화됩니다.
callmetwan 2014 년

72

정말로 이것을하고 싶지만 클래스를 사용하는 것보다 조금 더 간단하다면 다음을 사용할 수 있습니다.

function fn($data) {
  return $data;
}
$fn = 'fn';

$my_string = <<<EOT
Number of seconds since the Unix Epoch: {$fn(time())}
EOT;

좋은 @CJDennis! 이것이 HEREDOC 내부에서 함수 호출을 사용하는 가장 좋고 깨끗한 솔루션입니다. 어떤 상황에서는 좋은 자원이 있습니다. 내 사이트에서는 탭 인덱스 위치를 생성하기 위해 함수 호출과 함께 22 줄의 필드 세트 (FOR 루프 내부의 HEREDOC 블록)로 양식을 생성하는 데 HEREDOC를 사용합니다.
Paulo Buchsbaum 2013 년

다음과 같이 할 수도 있습니다.$my_string = "Half the number of seconds since the Unix Epoch: {$fn(time() / 2 . ' Yes! Really!')}";
CJ Dennis

2
보다 간결한 정의 : $fn = function fn($data) { return $data; };
devsmt 2013-09-19

1
@devsmt 당신이 맞아요. 심지어 짧은 :$fn = function ($data) { return $data; };
CJ 데니스

오, 고데 고프? 좋아, 나에 보자 $fn=function($data){return $data;};rhis가 짧은해야한다
MY1

42

다음을 수행합니다.

$string = <<< heredoc
plain text and now a function: %s
heredoc;
$string = sprintf($string, testfunction());

이것이 더 우아하다고 생각하는지 확실하지 않습니다 ...


17

이것을 시도하십시오 (전역 변수로 사용하거나 필요할 때 인스턴스화) :

<?php
  class Fn {
    public function __call($name, $args) {
      if (function_exists($name)) {
        return call_user_func_array($name, $args);
      }
    }
  }

  $fn = new Fn();
?>

이제 모든 함수 호출이 $fn인스턴스를 통과합니다 . 따라서 기존 함수 testfunction()는 heredoc에서 다음과 같이 호출 할 수 있습니다.{$fn->testfunction()}

기본적으로 우리는 모든 함수를 클래스 인스턴스로 래핑하고 PHP의 __call magic메서드를 사용 하여 클래스 메서드를 호출해야하는 실제 함수에 매핑합니다.


2
이는 기존 프로젝트에 템플릿 엔진을 추가 할 수없는 경우에 적합한 솔루션입니다. 감사합니다. 지금 사용하고 있습니다.
Brandon

성능이 중요 할 때 널리 사용되어서는 안됩니다. call_user_func_arrayphp.net의 주석에서 지난번에 성능이 더 나쁘다는 것을 여러 번 읽었습니다 . php.net/manual/en/function.call-user-func-array.php # 97473
Markus

좋은! 나는 그것을 좋아한다, 나는 왜 이것을 생각하지 않았는가?!? :-)
MikeSchinkel 2012 년

10

완전성을 위해 !${''} black magic parser hack을 사용할 수도 있습니다 .

echo <<<EOT
One month ago was ${!${''} = date('Y-m-d H:i:s', strtotime('-1 month'))}.
EOT;

7
호그와트에 갔습니까?
Starx

이것은 false == ''. 이름 길이가 0 ( '') 인 변수를 정의하십시오 . 원하는 값 ( ${''} = date('Y-m-d H:i:s', strtotime('-1 month')))으로 설정하십시오 . 부정 ( !)하고 변수 ( ${false}) 로 변환합니다 . false문자열로 변환해야하며 (string)false === ''. 잘못된 값을 인쇄하려고하면 대신 오류가 발생합니다. 다음 문자열은 진실과 거짓 값 모두에서 작동하지만 더 읽기 어렵습니다 "${(${''}=date('Y-m-d H:i:s', strtotime('-1 month')))!=${''}}"..
CJ Dennis

또한 인쇄 NAN하려면을 사용하십시오 "${(${''} = date('Y-m-d H:i:s', strtotime('-1 month')) )==NAN}".
CJ Dennis

9

조금 늦었지만 무작위로 발견했습니다. 미래의 독자를 위해 내가 할 일은 다음과 같습니다.

출력 버퍼를 사용합니다. 따라서 기본적으로 ob_start ()를 사용하여 버퍼링을 시작한 다음 그 안에 함수, 변수 등이있는 "템플릿 파일"을 포함하고 버퍼의 내용을 가져 와서 문자열에 쓴 다음 버퍼를 닫습니다. 그런 다음 필요한 변수를 사용하고 모든 함수를 실행할 수 있으며 IDE에서 여전히 HTML 구문 강조 표시를 사용할 수 있습니다.

제가 의미하는 바는 다음과 같습니다.

템플릿 파일 :

<?php echo "plain text and now a function: " . testfunction(); ?>

스크립트:

<?php
ob_start();
include "template_file.php";
$output_string = ob_get_contents();
ob_end_clean();
echo $output_string;
?>

따라서 스크립트는 template_file.php를 버퍼에 포함하여 모든 함수 / 메소드를 실행하고 그 과정에서 변수를 할당합니다. 그런 다음 버퍼의 내용을 변수에 기록하고 원하는 작업을 수행하면됩니다.

그렇게하면 바로 그 순간에 페이지에 에코를 표시하지 않으려면 할 필요가 없습니다. 출력하기 전에 반복해서 문자열에 추가 할 수 있습니다.

템플릿 엔진을 사용하고 싶지 않다면 이것이 최선의 방법이라고 생각합니다.


6

이 스 니펫은 사용자 범위 내에서 정의 된 함수 이름으로 변수를 정의하고 동일한 이름을 포함하는 문자열에 바인딩합니다. 제가 보여 드리겠습니다.

function add ($int) { return $int + 1; }
$f=get_defined_functions();foreach($f[user]as$v){$$v=$v;}

$string = <<< heredoc
plain text and now a function: {$add(1)}
heredoc;

이제 작동합니다.


@MichaelMcMillian은 어떤 함수와 같은 이름의 변수를 갖지 않는 것이 좋습니다.
s3c

6

랩핑 기능이있는 좋은 솔루션을 찾았습니다. http://blog.nazdrave.net/?p=626

function heredoc($param) {
    // just return whatever has been passed to us
    return $param;
}

$heredoc = 'heredoc';

$string = <<<HEREDOC
\$heredoc is now a generic function that can be used in all sorts of ways:
Output the result of a function: {$heredoc(date('r'))}
Output the value of a constant: {$heredoc(__FILE__)}
Static methods work just as well: {$heredoc(MyClass::getSomething())}
2 + 2 equals {$heredoc(2+2)}
HEREDOC;

// The same works not only with HEREDOC strings,
// but with double-quoted strings as well:
$string = "{$heredoc(2+2)}";

2
나는 2.5 년 전에 똑같은 해결책을 제안했습니다. stackoverflow.com/a/10713298/1166898
CJ Dennis

5

heredoc을 사용하면 HTML 코드를 생성하는 데 좋습니다. 예를 들어, 다음은 거의 완전히 읽을 수 없습니다.

<html>
<head>
  <title><?php echo $page_title; ?></title>
</head>
<body>
  <?php echo getPageContent(); ?>
</body>

그러나 단순성을 얻기 위해 시작하기 전에 함수를 평가해야합니다. 그렇게하면 계산을 디스플레이에서 분리하게되므로 일반적으로 좋은 생각입니다.

나는 다음이 꽤 읽기 쉽다고 생각한다.

$page_content = getPageContent();

print <<<END
<html>
<head>
  <title>$page_title</title>
</head>
<body>
$page_content
</body>
END;

불행히도 함수를 변수에 바인딩하는 것이 귀하의 질문에서 좋은 제안 이었지만 결국에는 가치가없는 코드에 복잡성 수준을 추가하고 코드를 읽기 어렵게 만듭니다. heredoc의 주요 장점.


2
지난 4 년 동안 대부분의 다른 접근 방식보다 훨씬 똑똑하다는 것이 입증되었습니다. 템플릿에서 구성을 사용하고 (작은 페이지로 구성된 큰 페이지를 작성) 모든 제어 로직을 별도로 유지하는 것은 템플릿 작성에 진지한 사람을위한 표준 접근 방식입니다. 페이스 북의 ReactJS는이 작업에 탁월합니다 (XHP와 마찬가지로) XSLT와 마찬가지로 나는 사랑하지 않지만 학문적으로 건전합니다). 내가 작성할 유일한 스타일 메모 : 나는 주로 가독성의 일관성과 나중에 사고를 피하기 위해 항상 내 변수 주위에 {}를 사용합니다. 또한 사용자로부터 오는 모든 데이터를 htmlspecialchars () 잊지 마세요.
Qaribou에서 조쉬

4

Smarty 를 템플릿 엔진으로 살펴 보겠습니다. 다른 엔진을 직접 사용 해본 적은 없지만 잘 해냈습니다.

템플릿이 아닌 현재의 접근 방식을 고수하고 싶다면 출력 버퍼링에 대한 나쁜 점은 무엇입니까? 호출하려는 함수의 문자열 이름 인 변수를 선언하는 것보다 훨씬 더 많은 유연성을 제공합니다.


3

람다 함수를 잊고 있습니다.

$or=function($c,$t,$f){return$c?$t:$f;};
echo <<<TRUEFALSE
    The best color ever is {$or(rand(0,1),'green','black')}
TRUEFALSE;

create_function 함수를 사용할 수도 있습니다.



2

다음은 @CJDennis 제안을 사용한 좋은 예입니다.

function double($i)
{ return $i*2; }

function triple($i)
{ return $i*3;}

$tab = 'double';
echo "{$tab(5)} is $tab 5<br>";

$tab = 'triple';
echo "{$tab(5)} is $tab 5<br>";

예를 들어, HEREDOC 구문의 좋은 사용은 데이터베이스에서 마스터-세부 관계로 거대한 양식을 생성하는 것입니다. FOR 컨트롤 내에서 HEREDOC 기능을 사용하여 각 필드 이름 뒤에 접미사를 추가 할 수 있습니다. 일반적인 서버 측 작업입니다.



1
<div><?=<<<heredoc
Use heredoc and functions in ONE statement.
Show lower case ABC="
heredoc
. strtolower('ABC') . <<<heredoc
".  And that is it!
heredoc
?></div>

0
<?php
echo <<<ETO
<h1>Hellow ETO</h1>
ETO;

당신은 그것을 시도해야합니다. ETO 종료 후; 명령을 입력해야합니다.


0

이것은 오늘날 PHP 7.x에서 조금 더 우아합니다.

<?php

$test = function(){
    return 'it works!';
};


echo <<<HEREDOC
this is a test: {$test()}
HEREDOC;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.