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
यह कड़ाई से आपके प्रश्न का उत्तर नहीं है, लेकिन हेरेडोक स्टेटमेंट्स में फ़ंक्शन कॉल के लिए खराब समर्थन को देखते हुए, मैं आमतौर पर हेरिंगोक को प्रिंट करने से पहले मुझे जो तार चाहिए, वह उत्पन्न करता हूं। फिर, मैं बस Text {$string1} Text {$string2} Textहेरेडोक में कुछ का उपयोग कर सकता हूं ।
rinogo

जवाबों:


51

मैं व्यक्तिगत रूप से इसके लिए HEREDOC का उपयोग नहीं करूंगा। यह सिर्फ एक अच्छी "टेम्पलेट बिल्डिंग" प्रणाली के लिए नहीं है। आपके सभी HTML को एक स्ट्रिंग में बंद कर दिया गया है जिसके कई नुकसान हैं

  • WYSIWYG के लिए कोई विकल्प नहीं है
  • IDEs से 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
इको के लिए एक शॉर्टहैंड है: <?=$valueToEcho;?>या <%=$valueToEcho;%>अपनी INI सेटिंग्स पर निर्भर है।
पीटर बेली

3
उन शॉर्टहैंड्स का उपयोग करने के बारे में मैंने जो कुछ भी पढ़ा है, उनमें से अधिकांश का उपयोग करते हुए कहते हैं कि यह एक बुरा अभ्यास है, और मैं सहमत हूं। इसलिए यदि आप वितरण के लिए कोड लिख रहे हैं तो दुर्भाग्य से आप उन INI सेटिंग्स पर निर्भर नहीं हो सकते हैं, जिससे वितरित कोड के लिए उनके लिए PHP का "सपोर्ट" बनता है। FWIW, मुझे दूसरे लोगों के वर्डप्रेस प्लगइन्स में बग्स को एक से अधिक बार ठीक करना पड़ा है क्योंकि उन्होंने इन शॉर्टहैंड्स का इस्तेमाल किया है।
माइकस्किंकेल

1
नहीं, मैं यह नहीं कह रहा हूं कि मुझे शर्म की बात है कि मुझे 7 अक्षर लिखने हैं; आप गलत तरीके से मेरे मुद्दों का श्रेय देते हैं। यह वह टाइपिंग नहीं है जिससे मैं चिंतित हूं, यह रीडिंग है । वे वर्ण बहुत सारे दृश्य शोर पैदा करते हैं जो स्रोत कोड को स्कैन करने और कोड क्या कर रहा है यह समझने के लिए बहुत कठिन बनाता है। मेरे लिए कम से कम है पर है ज्यादा एक हियरडॉक पढ़ने में आसान। (और BTW, यह 7 कैरेक्टर का समय है, यह दिए गए HTML टुकड़ा में कितनी बार उपयोग किया गया है। लेकिन मैं
पचाता

12
शॉर्ट अच्छे, साफ-सुथरे और पढ़ने में आसान होते हैं। आपके विचारों <?=$title?>में <की तुलना में बहुत अच्छा है; php गूंज $ शीर्षक; ?>। नकारात्मक पक्ष यह है कि हां, वितरण के लिए आईएनआई के बहुत सारे टैग बंद हैं। लेकिन , लगता है क्या ?? PHP 5.4 के रूप में , लघु टैग PHP में सक्षम हैं ini सेटिंग्स की परवाह किए बिना! इसलिए यदि आप 5.4+ आवश्यकता के साथ कोडिंग कर रहे हैं (मान लें कि आप लक्षण का उपयोग कर रहे हैं, उदाहरण के लिए), तो आगे बढ़ें और उन भयानक लघु टैग का उपयोग करें !!
जिम्बो

2
वैसे, <? = $ Blah?> 5.4 में डिफ़ॉल्ट रूप से सक्षम है, भले ही शॉर्ट टैग बंद हो गए हों।
कॉलमेटवान

72

यदि आप वास्तव में ऐसा करना चाहते हैं लेकिन एक वर्ग का उपयोग करने की तुलना में थोड़ा सरल है, जिसका आप उपयोग कर सकते हैं:

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

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

ग्रेट @CJDennis! यह HEREDOC के अंदर फ़ंक्शन कॉल का उपयोग करने के लिए सबसे अच्छा और साफ समाधान है। कुछ स्थितियों में अच्छा संसाधन है। मेरी साइट में, मैं फ़ील्ड सेट्स की 22 लाइनों (एक लूप के अंदर एक HEREDOC ब्लॉक) के साथ फॉर्म जनरेट करने के लिए HEREDOC का उपयोग करता हूं, जिसमें tabindex स्थिति उत्पन्न करने के लिए फ़ंक्शन कॉल है।
पाउलो बुचसबम

आप यह भी कर सकते हैं:$my_string = "Half the number of seconds since the Unix Epoch: {$fn(time() / 2 . ' Yes! Really!')}";
CJ डेनिस

2
एक अधिक कॉम्पैक्ट परिभाषा: $fn = function fn($data) { return $data; };
devsmt

1
@ महादेव तुम सही हो। और इससे भी छोटा है:$fn = function ($data) { return $data; };
CJ Dennis

ओह, Godegolf? ठीक है, मुझे इसमें जाने दें: $fn=function($data){return $data;};यह सबसे छोटा होना चाहिए
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()को एक हेरेडोक में कहा जा सकता है{$fn->testfunction()}

मूल रूप से हम सभी फ़ंक्शंस को एक वर्ग उदाहरण में लपेट रहे हैं, और PHP की __call magicविधि का उपयोग करके क्लास फ़ंक्शन को वास्तविक फ़ंक्शन के लिए मैप करने की आवश्यकता है।


2
यह ऐसे समय के लिए अच्छा समाधान है जब आप किसी मौजूदा प्रोजेक्ट में सिर्फ एक टेम्प्लेटिंग इंजन नहीं जोड़ सकते। धन्यवाद, मैं अभी इसका उपयोग कर रहा हूं।
ब्रैंडन

प्रदर्शन महत्वपूर्ण होने पर व्यापक रूप से उपयोग नहीं किया जाना चाहिए: मैंने पढ़ा है कि कई बार प्रदर्शन खराब होता है call_user_func_array, पिछली बार php.net पर टिप्पणियों में: php.net/manual/en/function.call-user-func-array.php # 97473
मार्कस

अच्छा! मैं इसे प्यार करता हूँ, मैंने ऐसा क्यों नहीं सोचा? :-)
माइकस्किंकेल

10

पूर्णता के लिए, आप !${''} काले जादू पार्सर हैक का उपयोग कर सकते हैं :

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')))!=${''}}":।
सीजे डेनिस

और यदि आप प्रिंट करना चाहते हैं NAN, तो उपयोग करें "${(${''} = date('Y-m-d H:i:s', strtotime('-1 month')) )==NAN}"
सीजे डेनिस

9

मुझे थोड़ी देर हो गई, लेकिन मैं बेतरतीब ढंग से इसके पार आ गया। किसी भी भविष्य के पाठकों के लिए, यहाँ मैं शायद क्या करूँगा:

मैं सिर्फ एक आउटपुट बफर का उपयोग करूंगा। इसलिए मूल रूप से, आप ob_start () का उपयोग करके बफरिंग शुरू करते हैं, फिर अपनी "टेम्पलेट फ़ाइल" को किसी भी फ़ंक्शंस, चर इत्यादि के साथ शामिल करें, इसके अंदर बफर की सामग्री प्राप्त करें और उन्हें एक स्ट्रिंग पर लिखें, और फिर बफर को बंद करें। फिर आपने अपनी आवश्यकता के किसी भी चर का उपयोग किया है, आप किसी भी फ़ंक्शन को चला सकते हैं, और आपके पास अभी भी आपके आईडीई में उपलब्ध 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;
?>

इसलिए स्क्रिप्ट में अपने बफर में टेम्पलेट_फाइल। एफपी, किसी भी कार्य / तरीके को चलाने और रास्ते में किसी भी चर को असाइन करना शामिल है। फिर आप बस बफर की सामग्री को एक चर में रिकॉर्ड करते हैं और वह करते हैं जो आप इसके साथ चाहते हैं।

इस तरह से यदि आप इसे उस सेकंड में पृष्ठ पर इसे प्रतिध्वनित नहीं करना चाहते हैं, तो आपके पास नहीं है। आप लूप कर सकते हैं और इसे आउटपुट करने से पहले स्ट्रिंग में जोड़ सकते हैं।

मुझे लगता है कि अगर आप टेम्प्लेटिंग इंजन का उपयोग नहीं करना चाहते हैं तो यह सबसे अच्छा तरीका है।


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/107198/1166898
सीजे डेनिस

5

मुझे लगता है कि HTML कोड बनाने के लिए heredoc का उपयोग करना बहुत अच्छा है। उदाहरण के लिए, मुझे निम्नलिखित लगभग पूरी तरह से अपठनीय लगता है।

<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 वर्षों में यह अन्य दृष्टिकोणों की तुलना में अधिक चालाक साबित हुआ। अपने टेम्प्लेट में रचना का उपयोग करना (छोटे पृष्ठों से बना एक बड़ा पृष्ठ बनाना) और सभी नियंत्रण तर्क को अलग रखना, जो किसी के लिए भी गंभीर है, जो मानक है: फेसबुक का रिएक्टजेएस इसके लिए उत्कृष्ट है (जैसा कि एक्सएचपी है), एक्सएसएलटी (जो मैं प्यार नहीं करता, लेकिन अकादमिक ध्वनि है)। एकमात्र शैलीगत नोट्स जो मैं बनाऊंगा: मैं हमेशा अपने संस्करणों के आसपास {} का उपयोग करता हूं, मुख्य रूप से पठनीयता में स्थिरता के लिए और बाद में दुर्घटनाओं से बचने के लिए। इसके अलावा, htmlspecialchars () उपयोगकर्ताओं से आने वाले किसी भी डेटा को मत भूलना।
क़रीब से

4

मैं स्मार्टी को एक टेम्प्लेट इंजन के रूप में देखूंगा - मैंने स्वयं किसी अन्य व्यक्ति की कोशिश नहीं की है, लेकिन इसने मुझे अच्छा किया है।

यदि आप अपने वर्तमान दृष्टिकोण सैंस टेम्प्लेट के साथ रहना चाहते हैं , तो आउटपुट बफरिंग के बारे में क्या बुरा है? यह आपको उन वेरिएबल्स को घोषित करने की तुलना में अधिक लचीलापन देगा जो उन फ़ंक्शन के स्ट्रिंग नाम हैं जिन्हें आप कॉल करना चाहते हैं।


2

थोड़ी देर लेकिन फिर भी। यह वंशानुगत में संभव है!

Php मैनुअल में एक नज़र डालें, "कॉम्प्लेक्स (घुंघराले) सिंटैक्स" अनुभाग


मैं पहले उदाहरण में पहले से ही उस वाक्य रचना का उपयोग कर रहा हूँ; यह फ़ंक्शन के नाम को एक चर में रखने से पहले आपको यह नुकसान होता है कि आप इसे हेरेडोक अनुभाग में घुंघराले ब्रेसिज़ के अंदर कह सकते हैं, जो कि मैं बचने की कोशिश कर रहा था।
डग कवेंडक

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 सिंटैक्स का एक अच्छा उपयोग एक डेटाबेस में मास्टर-डिटेल रिलेशनशिप के साथ विशाल रूप उत्पन्न करता है। प्रत्येक क्षेत्र के नाम के बाद एक प्रत्यय जोड़कर, एक नियंत्रण के अंदर HEREDOC सुविधा का उपयोग कर सकता है। यह एक सामान्य सर्वर साइड कार्य है।


2

आप मेमना समारोह के बारे में भूल रहे हैं:

$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 का उपयोग भी कर सकते हैं



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;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.