Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

Pbs with the extends function

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Bugs
View previous topic :: View next topic  
Author Message
bluejester
Smarty Regular


Joined: 26 Apr 2012
Posts: 55

PostPosted: Thu Apr 26, 2012 9:49 am    Post subject: Pbs with the extends function Reply with quote

Hi !

I just found a bug within Smarty's template inheritance.
For several reasons, I have to put the parent template's filename into an assigned variable, that I use into the {extends} function.
The {extends} function works well with {extends $ParentTemplate}, the only thing I can't explain is that it only works once, and doesn't work again when the $ParentTemplate value is changed.

How to reproduce it ? Let's create 4 files. The main PHP file, a child template, and 2 different templates to extend.

PHP file :
Code:
<?
   error_reporting(E_ALL ^ E_WARNING ^ E_NOTICE);
   
   # Constant definitions for PHP Files
   define('MAIN_PATH',         getcwd());
   define('INC_PATH',         MAIN_PATH   .   '/inc');
   define('SMARTY_CLASS_PATH',   INC_PATH   .   '/Smarty/libs');
   define('TEMPLATES_PATH',   MAIN_PATH   .   '/tpl');

   # Main inclusions
   require_once(SMARTY_CLASS_PATH . '/Smarty.class.php');
   
   # Smarty Configuration
   $Smarty = new Smarty();
   $Smarty->setTemplateDir(TEMPLATES_PATH);
   $Smarty->setCaching(Smarty::CACHING_OFF);

   # Smarty rendering
   $Smarty->display('Child.tpl');

Note that I turned off the Smarty cache, of course.

Parent1.tpl :
Code:
I am Parent1.tpl
{block 'MainContent'}
{/block}


Parent2.tpl :
Code:
I am Parent2.tpl
{block 'MainContent'}
{/block}


And Child.tpl
Code:
{extends 'Parent1.tpl'}
   {block 'MainContent'}
      <br/>&nbsp;&nbsp;&nbsp;I am Child.tpl
   {/block}



OK, now, let's see what's the display is :
Quote:
I am Parent1.tpl
I am Child.tpl


Perfect. Let's change the static {extends 'Parent1.tpl'} to {extends 'Parent2.tpl'}. Hit F5, Smarty now displays :
Quote:
I am Parent2.tpl
I am Child.tpl


Great! Smarty now extends correctly Parent2.tpl.

Now, assign the parent template name in a variable, just before the display() method.
Code:
# Smarty rendering
   $Smarty->assign('ParentTemplate', 'Parent1.tpl');
   $Smarty->display('Child.tpl');


Change the first line of your Child.tpl :
Code:
{extends $ParentTemplate}
   {block 'MainContent'}
      <br/>&nbsp;&nbsp;&nbsp;I am Child.tpl
   {/block}


Hit F5 in your browser, now it looks like this :
Quote:
I am Parent1.tpl
I am Child.tpl


That worked perfectly.
Now, change the value of $ParentTemplate :
Code:
   # Smarty rendering
   $Smarty->assign('ParentTemplate', 'Parent2.tpl');
   $Smarty->display('Child.tpl');


Hit F5 :
Quote:
I am Parent1.tpl
I am Child.tpl


Wtf ? Hit F5 again :
Quote:
I am Parent1.tpl
I am Child.tpl


The rendering is blocked on Parent1.tpl, though Parent2.tpl should be rendered.
Waiting (long) minutes sometimes fixes the problem, but this should not happen, since my Smarty Cache has been turned off.

In my PHP files, I have to condition which master template to use, that's why I use a variable. But... I just can't go further until this is fixed Sad

Thanks a lot !
Ben

PS : I tested it on Smarty v3.0.6 and 3.1.8
Back to top
View user's profile Send private message Visit poster's website
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Thu Apr 26, 2012 2:39 pm    Post subject: Reply with quote

Note that template inheritance is a compile time process.
If you use variable filenames the filename must included in a compile_id. See http://www.smarty.net/docs/en/language.function.extends.tpl

Code:
# Smarty rendering
   $Smarty->assign('ParentTemplate', 'Parent1.tpl');
   $Smarty->compile_id = 'Parent1.tpl';
   $Smarty->display('Child.tpl');


Or instead using the {extends} tag you could use the extends resource to define parent/child relations.

Code:
$smarty->display('extends:Parent1.tpl|Child.tpl');
Back to top
View user's profile Send private message
bluejester
Smarty Regular


Joined: 26 Apr 2012
Posts: 55

PostPosted: Thu Apr 26, 2012 3:57 pm    Post subject: Reply with quote

U.Tews,

You just saved my life.

Viele Danke !! Cool
Back to top
View user's profile Send private message Visit poster's website
bluejester
Smarty Regular


Joined: 26 Apr 2012
Posts: 55

PostPosted: Fri Apr 27, 2012 9:27 am    Post subject: Reply with quote

Hello U.Tews,

I'm sorry to be back.
Yesterday night, it worked fine.

Then I did just a little mod on my child template (just swapping two <tr>/<td>, with static content).

Smarty then rendered a blank page, without any error displayed.
This morning, I couldn't fix it. So I turned my smarty and my php code up and down for one hour, rolling back to a static {extends}, disabling all cache and compiled files with $smarty->clearCompiledTemplate(); and $smarty->clearAllCache();... nothing succeed.

So, I took an old version of my scripts and coded back "from scratch" everything, step by step, and that finally works fine : child template extending different master templates with a variable.

However, 2 minutes ago, I had to modify something in my child template... and the blank page is back.

I'm losing my hair ! Confused
What have I done wrong ?

Thanks in advance,
Ben
Back to top
View user's profile Send private message Visit poster's website
bluejester
Smarty Regular


Joined: 26 Apr 2012
Posts: 55

PostPosted: Fri Apr 27, 2012 9:54 am    Post subject: Reply with quote

If it can help, here's an overview of my code:

PHP File :
Code:
<?
   # Creating a $Params array of the user request
   [...]
   
   # Smarty & Cache settings
   $smarty         ->   setTemplateDir(SERVER_ROOT_PATH . 'Templates');
   $smarty         ->   setCaching(Smarty::CACHING_LIFETIME_CURRENT);
   $smarty         ->   setCacheLifetime(60 * 60 * 24 * 365);
   
   $CacheId      =   (string)   md5(json_encode($Params));
   $CacheExists   =   (bool)   $smarty->isCached('DashBoard/DataTable.tpl', $CacheId, 'Index.tpl');
   
   if (!$CacheExists) :   
      
      # If no user ever did this request, we fetch some heavy data, for 1-2 minutes...
      [...]
   
   endif;
   
   # Now, we want to render the result in different ways, and cache them
   $smarty   ->   assign('ParentTemplate', 'DashBoard/XLSExport.tpl');   // XLS template
   $smarty   ->   compile_id = 'XLSExport.tpl';
   $XLS   =   $smarty->fetch('DashBoard/DataTable.tpl', $CacheId, $smarty->compile_id);   
   
   $smarty   ->   assign('ParentTemplate', 'DashBoard/PDFExport.tpl');   // PDF template
   $smarty   ->   compile_id = 'PDFExport.tpl';
   $PDF   =   $smarty->fetch('DashBoard/DataTable.tpl', $CacheId, $smarty->compile_id);
   
   $smarty   ->   assign('ParentTemplate', 'DashBoard/Index.tpl');      // HTML template
   $smarty   ->   compile_id = 'Index.tpl';    
   $HTML   =   $smarty->fetch('DashBoard/DataTable.tpl', $CacheId, $smarty->compile_id);
   
   # Now, wether the user wants to display the XLS, the PDF or the HTML :
   if ($_GET['FileFormat']   ==   'XLS') :
      header("Content-type: application/vnd.ms-excel");
      header("Content-Disposition: attachment; filename=DashBoard - " . date("Y-m-d H-i-s") . ".xls");
      echo $XLS;
      
   elseif ($_GET['FileFormat']   ==   'PDF') :
       require_once('html2pdf_PHP5_v4.03/html2pdf.class.php');   
      
      header('Content-Type: application/pdf; charset=ISO-8859-15');
      $FileName   =   'PDF_DashBoard - ' . date("Y-m-d H-i-s") . '.pdf';   
      
      $HTML2PDF   =   new HTML2PDF('L','A4','fr', false, 'ISO-8859-15', Array(3, 3, 3, 3));   
      $HTML2PDF   ->   WriteHTML($PDF);         
      $HTML2PDF   ->   Output($FileName, 'I');   
      
   else :
      echo $HTML;
   endif;




Child template DashBoard/DataTable.tpl :
Code:
{extends file=$ParentTemplate}
   {block 'DashBoard'}
      <table>
         <thead>
            <tr>
               <td colspan="6">Some data...</td>
            </tr>
         </thead>
         <tbody>
            <tr>
               <td>Some data...</td>
               <td>Some data...</td>
               <td>Some data...</td>
               <td>Some data...</td>
               <td>Some data...</td>
               <td>Some data...</td>
            </tr>
         </tbody>
      </table>
   {/block}


Parent Template Index.tpl (HTML view)
Code:
{extends 'MasterTemplate.tpl'}
   {block 'Title'}
      <title>Dashboard</title>
   {/block}

   {block 'CSSFiles' append}
      <link rel="stylesheet" type="text/css" href="/css/Dashboard.css" />
   {/block}

   {block 'Content'}

      <h1>Dashboard</h1>
      
      <form>
         <!-- Some input fields -->
      </form>
      
      {block 'DashBoard'}{/block}
      
      <!-- Footer -->
         
   {/block}



Other Parent Template PDFExport.tpl (PDF view)
Code:
<page backtop="15mm" backbottom="7mm" backleft="10mm" backright="10mm" style="font-family: Arial" orientation="landscape">
   <page_header>
      <img src="/img/Logo.png" />      
   </page_header>
   
   {block 'DashBoard'}{/block}
</page>



Other Parent Template XLSExport.tpl for the XLS view (just for rendering the Dashboard.tpl template with a Content-type: application/vnd.ms-excel)
Code:
{block 'DashBoard'}{/block}


Thanks,
Ben
Back to top
View user's profile Send private message Visit poster's website
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Fri Apr 27, 2012 9:55 am    Post subject: Reply with quote

Did you use the {extends} tag and compile_id or the extends: resource?

I think something must be wrong with your template code, but no idea why you don't see an error message....
Back to top
View user's profile Send private message
bluejester
Smarty Regular


Joined: 26 Apr 2012
Posts: 55

PostPosted: Fri Apr 27, 2012 10:27 am    Post subject: Reply with quote

No, I'm using the {extends $ParentTemplate} in the TPL code, $ParentTemplate is a string assigned in the PHP code, depending of the view the user wanted.

Now that I use a cache Id and a compile Id into my isCached() and my fetch() methods, erverything works fine, until I modify something in my TPL files.

That's disturbing since I often have to modify things in my TPL files...

No error message, indeed... Sad
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Bugs 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