Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.

Include AND Extend - With Plugin Example

 
Post new topic   Reply to topic    Smarty Forum Index -> Feature Requests
View previous topic :: View next topic  
Author Message
cactustit
Smarty n00b


Joined: 26 Sep 2020
Posts: 2

PostPosted: Sat Sep 26, 2020 12:13 pm    Post subject: Include AND Extend - With Plugin Example Reply with quote

Preface

Obviously it is possible to create a template that is an extension of another with {extends} and {block}

It is also possible to include templates within another with {include}

Issue

What is not possible, is to include a template, while also extending parts of the template you are including.

Why?

Some may feel this complicates inheritance. For me, its the ideal solution to display a single piece of content or a set of contents that is surrounded by a shared element.

My workaround function

PHP
I access my smarty class from a wrapped function, here you can see the plugin functions I have added
Code:

class MySmarty extends Smarty {
   function __construct() {
      parent::__construct();
      
      $this->registerPlugin('block','bit', array($this, 'bit'));
      $this->registerPlugin('block','bit_block', array($this, 'bit_block'));
      
   }
   var $bit_blocks = array();
   
   /**
    * Similar to include, but can extend blocks within the template.
    * Either use the bit block as is with content directly inside to apply to the "content" block of the template you are extending,
    * or manually add bit_block blocks inside of the bit block to chose which blocks to specify what blocks to add content to.
    *
    */
   function bit($params, $content, Smarty_Internal_Template $template, &$repeat)
   {       
         if ($repeat){
            $this->bit_blocks[] = array();
            
         }else{
            $blocks = array_pop($this->bit_blocks);
            if (empty($this->bit_blocks)){
               $this->bit_blocks = array();
            }
            if (empty($blocks)){
               $blocks = array('content' => array('content' => $content, 'options' => array()));
            }
            $string = $this->left_delimiter . 'extends file="'.$params['file'].'"'.$this->right_delimiter."\n";
            
            foreach($blocks as $block => $contents){
               $options = '';
               if (!empty($contents['options'])){
                  $options = ' ' . implode(' ', $contents['options']);
               }
               $string .= $this->left_delimiter . 'block name="'.$block.'"'.$options.$this->right_delimiter. $contents['content'] . $this->left_delimiter . '/block '.$this->right_delimiter;
            }
            $bit = $this->fetch("string:$string");
            return $bit;
         }
      
   }
   function bit_block($params, $content, Smarty_Internal_Template $template, &$repeat)
   {
      // Get normal short hand options such as append by adding block_append=True in bit_block params (add block_ before the option and make it =True for workaround of not beng able to do shorthand)
      // only output on the closing tag
      if(!$repeat){
         $bit_keys = array_keys($this->bit_blocks);
         $options = array();
         $name = $params['name'];
         unset($params['name']);
         foreach($params as $param_key => $param_val){
            if ($param_val === True){
               $options[] = substr($param_key, 6);
            }
         }
         $this->bit_blocks[end($bit_keys)][$name] = array('content' => $content, 'options' => $options);
      }
   }
}


Template
This is an example of a template (child.tpl) that is extending another (parent.tpl), which also has a "bit" (bit.tpl). Hopefully also including an example of normal {exends} can better distinguish the feature I am trying to present here.

parent.tpl
Code:

<html>
   <head>
   </head>
   <body>
      {block name="content"}
      {/block}
   </body>
</html>


bit.tpl
Code:

<div class="panel">
   <h2>{block name="title"}</h2>
   <div class="content">
      {block name="content"}
   </div>
</div>


child.tpl <-- this is where the feature in question occurs
Code:

{extends file="parent.tpl"}
{block name="content"}
   {bit file="bit.tpl"}
      {bit_block name="title"}
         Title goes here
      {/bit_block}
      {bit_block name="content"}
         Content goes here
      {/bit_block}
   {/bit}
{/block}


Expected result

Code:

<html>
   <head>
   </head>
   <body>
      <div class="panel">
         <h2>Title goes here</h2>
         <div class="content">
            Content goes here
         </div>
      </div>


   </body>
</html>


Closing

If there is enough interest in this feature, I would love it to be incorporated into smarty directly. However, if not feel free to use or extend my simple plugin. I worry that its a bit hacky and maybe not optimal. If I had better knowledge of how smarty works I might make a proper block function that works similar to {block} and can include file without having to hack a string template.
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1653

PostPosted: Mon Sep 28, 2020 4:34 pm    Post subject: Reply with quote

There's no interest. Really.
{extends} supposed to be used to replace main (content) block on a page. Several blocks, if you wish, in different ways (prepend/append/replace).
{include} supposed to be used for shared/reusable content blocks.

What you want to achieve is trivially achieved with existing functionality, if you dare to learn how to use engine properly.

You create a layout page, then extend it with different content pages. Multiple times, if you wish (f.e. main site layout >> forum layout >> topics list/thread posts list/etc.).
Back to top
View user's profile Send private message
cactustit
Smarty n00b


Joined: 26 Sep 2020
Posts: 2

PostPosted: Tue Sep 29, 2020 3:40 am    Post subject: Reply with quote

Thank you,

I am aware of what can be achieved with multiple levels of extension, and how in my example specifically it could easily be done a different way as I've only included one bit.

This is for situations where I want to include content only in certain situations , and only in said situations does the encapsulating elements show, which I understand can be achieved with the block hide options, but in the case of mutliple of this situation, It feels messy to make multiple blocks with slightly varied names and with the same surrounding content just incase they are used.

I understand that my desired feature has many workarounds to achieve similar results, but I just felt this is a missing piece.

My original intension was to post this in a place more where I can just show my plugin incase anyone wants to use it or extend it but I felt that's wrong because it's not a very good one so I decided instead to post here. If anything I just wanted to hear if anyone else has similar experience to me, notably with the desire to extend a template within another template, and realising that it's not possible.
Back to top
View user's profile Send private message
AnrDaemon
Administrator


Joined: 03 Dec 2012
Posts: 1653

PostPosted: Tue Sep 29, 2020 9:59 am    Post subject: Reply with quote

You can use {include} inside {block}. And {extends} multiple templates at once.
Back to top
View user's profile Send private message
HocuWeb
Smarty Rookie


Joined: 19 Oct 2020
Posts: 5
Location: HocuWeb.com

PostPosted: Mon Oct 19, 2020 1:24 pm    Post subject: Reply with quote

thanks for this Very Happy
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> Feature Requests All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP