कास्टिंग PHP जादू

PHP एक अद्भुत प्रोग्रामिंग भाषा है। अपनी सभी कमियों के साथ, यह विस्मित करना बंद नहीं करता है। हाल ही में मैंने निम्नलिखित का सामना किया - पहली नज़र में रहस्यमय - उसका व्यवहार।

जैसा कि आप जानते हैं, PHP में एक अंतर्निहित टेम्पलेट इंजन होता है। PHP कोड के अंत और शुरुआत को दर्शाने वाले टैग के बीच दुभाषिया का सामना करने वाले सभी पाठ, यह आउटपुट बफर को भेजता है। आप निम्न उदाहरण से इसे सत्यापित कर सकते हैं:

<?php echo "Hello, "; ?> World. <?php echo "All is fine\n"; 

कार्यक्रम का आउटपुट "हैलो, वर्ल्ड" होगा। सब ठीक है ”, जैसा कि आप उम्मीद करेंगे। लेकिन वास्तव में क्या होता है? आइए एक और उदाहरण देखें:

 <?php $three = function() { ?> Three <?php }; $one = function() { ?> One <?php }; $two = function() { ?> Two <?php }; $one(); $two(); $three(); 

यदि आप स्रोत कोड निष्पादित करते हैं, तो प्रोग्राम का आउटपुट "वन टू थ्री" होगा, जो थोड़ा अजीब है। आखिरकार, कोड में पाठ पूरी तरह से अलग अनुक्रम में पाया गया था और "तीन एक दो" आउटपुट बफर में होना चाहिए था।

वास्तव में, जैसे ही इसका सामना होता है, PHP आउटपुट बफर को टेक्स्ट नहीं भेजता है। भाषा दुभाषिया के पास एक विशेष opcode ZEND_ECHO है (गूंज का इस opcode में अनुवाद किया गया है) और PHP कोड के बीच पाठ का एक टुकड़ा इस opcode के तर्क में अनुवादित किया जाएगा। यही कारण है कि हमारे पास दूसरे उदाहरण में प्रदर्शित पाठ है जिस क्रम में हम निर्मित अनाम फ़ंक्शंस कहते हैं (पाठ आउटपुट ZEND_ECHO opcode की बदौलत अनाम फ़ंक्शंस का हिस्सा बन गया है।

मेरे शब्दों की पुष्टि में, फ़ाइल zend_language_parser.y की सामग्री का एक टुकड़ा

  | T_INLINE_HTML { zend_do_echo(&$1 TSRMLS_CC); } 

और zend_do_echo के कार्य को zend_compile.c से ही कार्यान्वित किया जाता है:

 void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */ { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_ECHO; SET_NODE(opline->op1, arg); SET_UNUSED(opline->op2); } /* }}} */ 

खैर, इसका क्या फायदा है?

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

 $c->header->addClass('header')->setContent(function() { ?> <ul> <?= $c->li->addClassIf(1, 'active')->setContent('Main') ;?> <?= $c->li->addClassIf(0, 'active')->setContent('Account') ;?> <?= $c->li->addClassIf(0, 'active')->setContent('FAQ') ;?> <?= $c->li->addClassIf(0, 'active')->setContent('Logout') ;?> </ul> <?php })->_print(); ?> 

जहां चर में $ c-> हेडर क्लास सीईमेंट का एक ऑब्जेक्ट है। क्या यह सुविधाजनक है? स्वाद और कोई दोस्तों का रंग)

पुनश्च
आधिकारिक प्रलेखन से, दुभाषिया का व्यवहार पूरी तरह से स्पष्ट नहीं है। इसके अलावा, यह पाठ को एक ओपकोड तर्क में परिवर्तित करने के बारे में बिल्कुल भी उल्लेख नहीं करता है: जब PHP दुभाषिया हिट करता है?> टैग को बंद करना, यह बस जो कुछ भी पाता है, उसे आउटपुट करना शुरू कर देता है (सिवाय इसके तुरंत बाद की नई पंक्ति को देखें - निर्देश जुदाई देखें) जब तक कि यह आपके शुरुआती टैग को नहीं मारता।

Source: https://habr.com/ru/post/In171097/


All Articles