How to get rid of whitespace in Smarty {block}s? - php

I've run into a problem where defining the value of a {block} introduces a lot of unnecessary whitespace.
I've a main template, let's call it main.html, which looks like this (simplified):
<html>
<title>{block name=title}{$default_title}{/block}</title>
...
</html>
Then I inherit from it in let's say topics.html, and I define the title block in it:
{extends file="main.html"}
{block title}
{if $topic}
{if $topic == "all"}
{eval $Config['titles']['topics']['all']}
{else}
{eval $Config['titles']['topics']['particular']}
{/if}
{else}
{eval $Config['titles']['topics']['list']}
{/if}
{/block}
Now when I compile the topics.html template, there is so much whitespace inside of <title>...</title> tag.
For example, it looks like this:
<title>
Showing all wiki topics </title>
How could I trim/strip the whitespace from the result of evaluating a block so it looked like the following:?
<title>Showing all wiki topics</title>
I tried adding {strip}...{/strip} around the {block title}...{/block} like this:
{strip}
{block title}
...
{/block}
{/strip}
But that didn't change anything.
I also tried this:
{block title|strip}
...
{/block}
But that was a syntax error. I also tried this:
{block title|trim}
...
{/block}
But it also was a syntax error.
I also tried:
{block title}
{strip}
...
{/strip}
{/block}
But that didn't help either as I already introduced a new-line after {block title}so it stays there in the compiled template.
Any help appreciated!

As of Smarty 3.1 you cannot wrap {block}s in other constructs. (This might change with Smarty 3.2)
Have you tried putting the {strip} tags inside the {block}s? Otherwise have a look at my answer here

Related

Smarty Template 3.1 ERROR: variable template file names not allow within {block} tags

these days I am trying to improve my templates by using the Smarty template engine and its OOP template tag {block}
Its working pretty good, but I also noticed when I use {block} - tags the {include file="[...]" variableX="[..]"} breaks when I use nested variables.
PHP Fatal error: [...] variable template file names not allow within {block} tags
Some examples:
WORKING (without nested variable inside "param")
{block name=CONTENT}
{assign "extra" value="test"}
DropDown: {include "dropdown.html" param="product_name" items=DS::PRODUCTS()}
{/block}
NOT WORKING #1 (with nested variable using `` )
{block name=CONTENT}
{assign "extra" value="test"}
DropDown: {include "dropdown.html" param="product_name_`$extra`" items=DS::PRODUCTS()}
{/block}
NOT WORKING #2 (with nested variable using {} )
{block name=CONTENT}
{assign "extra" value="test"}
DropDown: {include "dropdown.html" param="product_name_{$extra}" items=DS::PRODUCTS()}
{/block}
When I am using {include} without {block} all examples are ok
Question: is there any other method to allow nested variables or is it a known issue?
Thank you in advance
Simple answer is - don not use such fancy techniques. If you really have no way around it, this likely means your design idea is flawed and needs to be rethought, or, in case of Smarty, you need a longer inheritance chain.
Check something like this.
Index template(index.tpl):
<html><head>
<title>{block 'page-title'}Silly title{/block}</title>
</head><body>{block 'page-content'}Silly content{/block}</body></html>
Single article content(index-content.tpl):
{extends 'index.tpl'}
{block 'page-title'}{$title|escape}{/block}
{block 'page-content'}{$content|render}{/block}
List/paged article content(list-content.tpl):
{extends 'list-index.tpl'}
{block 'page-title'}{$title|escape}{/block}
{block 'pager'}{somepaging}{/block}
{block 'list-content'}{somecontent}{/block}
The wrapper that the list is inherited from(list-index.tpl):
{extends 'index.tpl'}
{block 'page-content'}
{block 'pager'}[1] [2] [3]{/block}
{block 'list-content'}x{/block}
{block 'pager'}[1] [2] [3]{/block}
{/block}
When I'm rendering a simple article, I call index-content.tpl. When I need a paged list, I call list-content.tpl. I never call any of the base templates directly.
However, if your theme requere to enable or disable specific blocks of content on a page, you can always wrap selection in {if} blocks. But honestly, I would urge you to reconsider your base design.

Chaining smarty templates and clean multiline strings - PHP

I know that the first part of this is subjective, but I'd like to hear some different techniques people use. This is a two part question: what do you use for complex multiline strings in PHP? And, can I use a composition type of relationship with smarty?
Question 1: I know there is heredoc and the "." operator. I'm looking for fresh, more readable ideas if there are any.
Question 2: To be more specific, here is what I would like to do with smarty.
Say I have a template, base.tpl:
<html>
<head><title></title></head>
<body>
{$main_content}
</body>
</html>
Can I chain templates, i.e. another template that represents $main_content, say main.tpl:
<div id="header">$header</div>
<div id="container">
<h1>{$first_header}</h1>
<p>{$first_paragraph}</p>
<h1>{$second_header}</h1>
<p>{$second_paragraph}</p>
I want in whatever.php to load one template into the other, so i.e.:
// ... including smarty and all other boiler plate things ...
$smarty -> assign('first_header', "Foo");
$smarty -> assign('first_paragraph', "This is a paragraph");
$smarty -> assign('second_header', "Bar");
$smarty -> assign('second_paragraph', "This is another paragraph");
$main_content = $smarty->load('main.tpl');
$smarty -> display('base.tpl');
I know that there is "template inheritance" in smarty, but I'm not familiar with it. Can it give me similar functionality to this?
Note: I think my biggest problem with heredoc is that I can't get syntax highlighting for html (if i specify html in the heredoc string). Without the highlighting, the html that I want to pass through smarty is much harder to read, which kind of defeats the purpose of smarty.
You'll want to use {include} to call templates (fragments) within a template.
http://www.smarty.net/docsv2/en/language.function.include.tpl
<html>
<head>
<title>{$title}</title>
</head>
<body>
{include file='page_header.tpl'}
{* body of template goes here, the $tpl_name variable
is replaced with a value eg 'contact.tpl'
*}
{include file="$tpl_name.tpl"}
{include file='page_footer.tpl'}
</body>
</html>
Passing variables into included templates:
{include file='links.tpl' title='Newest links' links=$link_array}
{* body of template goes here *}
{include file='footer.tpl' foo='bar'}
In terms of multi-line strings, I tend to use this pattern:
$my_string = "Wow, this is going to be a long string. How about "
. "we break this up into multiple lines? "
. "Maybe add a third line?";
As you said, it's subjective. Whatever you feel comfortable with and as long as its easily readable...
I found some documentation on template inheritance this morning...
To expand on my example above, you can have a base layout (base.tpl)
<html>
<head><title>{$title|Default="title"}</head>
<body>
<nav>{block name=nav}{/block}</nav>
<div id="main">{block name=main}Main{/block}</div>
<footer>Copyright information blah blah...</footer>
</body>
</html>
You can extend a template and override blocks now with the new version of smarty (home.tpl)
{extends file=base.tpl}
{block name=nav}
<ul style="list-style:none">
{foreach $links as $link}
<li>{$link.txt}</li>
{/foreach}
</ul>
{/block}
{block name=main}
{foreach $paragraphs as $p}
<h2>{$p.header}</h2>
<p>{$p.content}</p>
{/foreach}
{/block}
http://www.smarty.net/inheritance

Can smarty block names be derived from smarty variables

I would like to define smarty block names according to smarty data, but I can't seem to do it.
Example:
{foreach $array as $code}
{block name=block_$code}
<div id='{$code}'></div>
{/block}
{/foreach}
My purpose is to extend a specific block_$code block by a child template. Is this possible or is there some other trick I could use to do this?
Thanks.
You can use the {assign} block and the cat modifier. For example
{foreach $array as $code}
{assign var=foo value="block_"|cat:$code}
{block name=$foo}
<div>
{/block}
{/foreach}
N.b. I've not tested this, but it should work. You might also be able to short-circuit this and just use {block name="block_"|cat:$code}.
I was able to find the following link from 2011 indicating that this wasn't possible at that time. I suspect it still isn't:
http://www.smarty.net/forums/viewtopic.php?t=19805&highlight=block%20variable%20name
The good news it that I was able to figure out how to make my code work without it. I wanted to be able to override just one of the divs defined by the foreach. Here's how I can do it:
Parent:
{foreach $array as $code}
{block name=code_loop}
<div>Normal Stuff</div>
{/block}
{/foreach}
Child:
{block name=code_loop}
{if $code == 'code of interest'}
<div>New Stuff</div>
{else}
{$smarty.block.parent}
{/if}
{/block}

What is wrong with this Smarty php templating code?

What is wrong with this Smarty php templating code? If I include either of these two loops individually in the file, they work. But if I have them both in the file like below only the first loop gets completed.
{include file="vote_js.tpl"}
{section name=i loop=$posts}
{include file="posts_bitother.tpl"}
{/section}
{section name=j loop=$posts2}
{include file="posts_bitposts.tpl"}
{/section}
So for example
{section name=j loop=$posts2}
{include file="posts_bitposts.tpl"}
{/section}
works fine on it's own.
Why is this happening and what is the way around it?
Solved it, was an error in my smarty code later on

How to check a complex condition in Smarty(PHP)

I need to display a section or another in a smarty template. My condition is simple: if a smarty value starts with a string I should display one section, otherwise the other smarty section should be displayed. I can change only the tpl files.
{php}
if (substr($url,0,4) != 'http')
{
{/php}
section 1
{php}
}
else
{
{/php}
section 2
{php}
}
{/php}
The problem is that I can not read the url varible which was previously assigned using $smarty->assign. Basically, I'm looking for the smarty function that can be used to retrieve a value, or if there is a better solution.
First, I would clean up your code. You don't need php tags, you're using smarty:
{if substr($url,0,4) neq 'http'}
section 1
{else}
section 2
{/if}
That's untested but it should be pretty close..
Now, if you're trying to read something like a constant, for example a server variable like HTTP_HOST, you can do something like this:
{assign var='url' value=$smarty.server.HTTP_HOST}
{if substr($url,0,4) neq 'http'}
section 1
{else}
section 2
{/if}

Categories