Muted Template <Review/Critique/Suggestions>
Moderator: General Moderators
Muted Template <Review/Critique/Suggestions>
Hello everyone! I'm new to this forum, I found it when searching for a place specifically to get feedback on a project of mine. This is "Muted Template" which is yet another templating language built over top of PHP which is itself a templating language. Some extra stuff is included because this is going to serve as the basis for a CMS I am developing.
The language itself is built with extensibility and full Utf-8 support at its core. This means that basic language constructs such as if, for, set and more are actually "plug-ins" and you can develop any other fundamental language tags provided you register them with the engine with MutedTemplate->createTag($TagName, $ClassName) and the class defines its own parsing rules appropriately. The only thing which is built-in to the template parsing class is variable output tags such as {$value[index]}.
The size of the project may seem daunting, however, there is a unit test folder where you can view a number of examples and there is a brief comment on how to use each tag in the Code/Parse/Tags folder. If you're feeling adventurous you can even try your hand at making a new tag. The best way to approach this would probably be to find a tag that does something similar to what you want and copy/modify that.
I have a demo here where you can take the language for a spin:
http://www.michaelhamilton.com/MutedTemplate/demo.php
The PHP source code is here:
http://www.michaelhamilton.com/Files/MutedTemplate.zip
If you would like to use this in your own projects please let me know via e-mail maxmike@gmail.com, mostly I just like knowing that people find it useful. If you make new tags which may be useful, again, let me know and I may include them in the core distribution!
But more importantly this project is in its infancy and I am looking for comments on both the PHP code running the project and also the language I have designed.
This project is PHP 4 and PHP 5 compatible.
The language itself is built with extensibility and full Utf-8 support at its core. This means that basic language constructs such as if, for, set and more are actually "plug-ins" and you can develop any other fundamental language tags provided you register them with the engine with MutedTemplate->createTag($TagName, $ClassName) and the class defines its own parsing rules appropriately. The only thing which is built-in to the template parsing class is variable output tags such as {$value[index]}.
The size of the project may seem daunting, however, there is a unit test folder where you can view a number of examples and there is a brief comment on how to use each tag in the Code/Parse/Tags folder. If you're feeling adventurous you can even try your hand at making a new tag. The best way to approach this would probably be to find a tag that does something similar to what you want and copy/modify that.
I have a demo here where you can take the language for a spin:
http://www.michaelhamilton.com/MutedTemplate/demo.php
The PHP source code is here:
http://www.michaelhamilton.com/Files/MutedTemplate.zip
If you would like to use this in your own projects please let me know via e-mail maxmike@gmail.com, mostly I just like knowing that people find it useful. If you make new tags which may be useful, again, let me know and I may include them in the core distribution!
But more importantly this project is in its infancy and I am looking for comments on both the PHP code running the project and also the language I have designed.
This project is PHP 4 and PHP 5 compatible.
Re: Muted Template <Review/Critique/Suggestions>
It is impressive work but I'm wondering what the benefit is over a more established and widely adopted engine like Smarty. And honestly, I've never been a fan of doing things this way - I suppose this is the .NET programmer in me but I prefer to completely decouple logic from the template. No controls structures of any kind. "Template tweaking" leads to more sloppy presentation code than I care to think about.
Again, it looks like solid work. Could you post some more details/examples on your site? Its difficult to get a feel for the scope with the two you've provided.
Again, it looks like solid work. Could you post some more details/examples on your site? Its difficult to get a feel for the scope with the two you've provided.
Re: Muted Template <Review/Critique/Suggestions>
I really don't see how that is possible. You can decouple business logic from the templates, but how can you forgo presentational logic such as loops / iterations and conditionals? where would presentational logic be if not in the templates?I prefer to completely decouple logic from the template
Re: Muted Template <Review/Critique/Suggestions>
It could go to the view classes. Views are not necessary templates. For example in gtk-xdebug-client I have a hierarchy of view classes working with UI widgets loaded from glade xml file (you can regard those widgets as templates). View class would accept the widget, wire it into the application and provide some methods like 'setBreakpoint' etc.pytrin wrote:I really don't see how that is possible. where would presentational logic be if not in the templates?
Re: Muted Template <Review/Critique/Suggestions>
Like Weirdan said, my view files are not my templates. The view controls the template. My templates get parsed early and are exposed to the view as part of the class. This is nice because a lot of times your presentation depends on data provided by the model and giving the view access to the controls on the page keeps your templates clean and easy to modify.
Views end up looking like this, instead of your templates being littered with PHP if/ blocks.
Or if I need to hide/show an entire block of controls I just encase them in what I call a "dock". Then it becomes....
This also makes it a breeze to distribute data to the controls - instead of having to go through each textbox and do ...text="$username"..... etc. etc. I can bind arrays to my docks and each array key is mapped to provided control id.
Views end up looking like this, instead of your templates being littered with PHP if/ blocks.
Code: Select all
$this->textbox1->visible = false;Code: Select all
$this->dock3->visible = false;Code: Select all
$this->dock3->bind($array)- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Re: Muted Template <Review/Critique/Suggestions>
I think pytrin's comments raise the question for me of the benefits of:JNettles wrote:Like Weirdan said, my view files are not my templates.
1. not having logic in templates
2. having a separation between the "template" and the "view"
There is no a clear definition here of "template" and "view" here, so it is a little hard to discuss. You definitions seem to be self-referential. You split your presentation code and give the parts names.
In MVC parlance the View is the part of the Presentation Layer that deals mainly with the Response. So there is a primary layer separation and then a secondary separation within the layer from the Controller. There is no distinction between logic in the View and templates in the View. So what are the benefits for the separation and restrictions you propose? I get a sense in these templating discussions that people see specific benefits from Domain Specific Languages. Is that you goal?
(#10850)
Re: Muted Template <Review/Critique/Suggestions>
Yes, like arborint said it's not clear what you mean when you say "view" and "template". It seem wierdan even referred to a desktop application, which have different methods for rendering than a web application (it doesn't just return out textual markup, it invokes API methods etc for drawing / rendering).
I use mostly the Zend Framework which has a View class instance which you can load parameters into. This instance can then render any number of templates - which could contain repeatable elements, such as table rows, and conditionals based on permissions and other variables. I can't really see how this can be separated from the templates without making the process much more complicated and verbose than it has to be. Don't abstract / decouple just for the sake of it, there must be tangible benefits.
Personally I don't like having HTML markup in what I call "pure" PHP classes. It feels wrong to build HTML as concatenated strings instead of having it in plain text, which can also be read by any modern IDE and edited by people who don't understand anything more than basic PHP structures.
I use mostly the Zend Framework which has a View class instance which you can load parameters into. This instance can then render any number of templates - which could contain repeatable elements, such as table rows, and conditionals based on permissions and other variables. I can't really see how this can be separated from the templates without making the process much more complicated and verbose than it has to be. Don't abstract / decouple just for the sake of it, there must be tangible benefits.
Personally I don't like having HTML markup in what I call "pure" PHP classes. It feels wrong to build HTML as concatenated strings instead of having it in plain text, which can also be read by any modern IDE and edited by people who don't understand anything more than basic PHP structures.
Re: Muted Template <Review/Critique/Suggestions>
http://joshribakoff.com/?p=37 -" So I needed namespaced view helpers ( need $this->foo() to act conditionally based on the module, not using a switch statement in a view helper but rather by using polymorphic helpers ). "pytrin wrote:I use mostly the Zend Framework which has a View class instance which you can load parameters into. This instance can then render any number of templates - which could contain repeatable elements, such as table rows, and conditionals based on permissions and other variables. I can't really see how this can be separated from the templates without making the process much more complicated and verbose than it has to be. Don't abstract / decouple just for the sake of it, there must be tangible benefits.
Magento does this too, thats what the thing called "blocks" do. Although Magento still failed at removing logic from the template (they have 1,000+ line conditionals even still). I have found though that it is useful to subclass the view and have my template run within the subclassed view.
Really this is the same thing as "view helpers" in Zend, just without the helper architecture, and "more OOP" (depending on what you are doing). The benefits are tangible, even if you don't happen to see/need them.
I think the technical name for this pattern is "composite view". Usually it includes a configuration like weirdan stated (that is exactly what Magento does). it is one of the major gripes that Magento designers have (because it adds so much indirection). I think the way Magento did it is totally wrong though. It should be used for encapsulating presentation logic, not for deciding which template partial gets rendered next.
Also from my blog - "Right now I’m keeping it at the module level. I’ve found from working with Magento if you take this too far you are more prone to leaking controller logic into the helpers."
Last edited by josh on Tue Mar 02, 2010 6:14 pm, edited 1 time in total.
Re: Muted Template <Review/Critique/Suggestions>
I use name-spaced helpers and sub-templates, quite similar to what you show in that link. However, I wouldn't create a new helper everytime I needed a conditional or a loop that couldn't conform to partialLoop.
I hope you realize this is exactly the opposite of tangible...The benefits are tangible, even if you don't happen to see/need them.
Re: Muted Template <Review/Critique/Suggestions>
The sun is tangible although you only see it for 12hrs out of the day.pytrin wrote:I hope you realize this is exactly the opposite of tangible...The benefits are tangible, even if you don't happen to see/need them.
Re: Muted Template <Review/Critique/Suggestions>
It would stop being tangible if I didn't see/need it ... a black hole is a more relevant metaphor. According to science they exist, but I can't see them directly for obvious reasons and though it makes great Sci-Fi material I wouldn't plan my house to be black-hole resistant.The sun is tangible although you only see it for 12hrs out of the day.
Since I don't find presentational logic to be out of place in view templates, I can't see those "tangible" benefits you speak of but don't elaborate on.
I'll use a small example for demonstration. How would you take out the following logic out of a view template in a way that is more maintainable / makes sense:
Code: Select all
... HTML markup ...
<?php if($this -> can_edit) : ?>
<a href="url/to/editing/item/id">Edit</a>
<?php endif; ?>
... HTML markup ...
Last edited by Eran on Tue Mar 02, 2010 6:43 pm, edited 1 time in total.
Re: Muted Template <Review/Critique/Suggestions>
I've extracted two primary questions for me and I'll do my best to respond to them. Keep in mind I'm really just presenting my personal reasoning, and I am not a Smarty guru, so any corrections on claims I've made about Smarty would be welcomed!
Really it's difficult to provide examples on a large enough scale to cover the language. It's really a project in and of itself to set up appropriate documentation. It is something I would like to do, and plan on doing. For now, the various unit tests provide a very lame set of examples of edge cases and regular use of individual tags which you can check out.
"Why use a template language at all?"
There are more situations in which a template language is the wrong choice than there are in which it is the right choice. There are, however, some benefits to running a scripting language over PHP and I will list them:
Primary Reasons:
1) Ability to reflect on what has been parsed. With a PHP "template" you really don't get anything more than you put in to it. This means that if you wanted to keep track of all the links that were displayed you would end up needing to parse everything anyway. Let's say you want to create a CMS solution which detects fields such as "title" "body" "title image" and so on so that you can get that information from someone managing the site and display it appropriately later? This allows you to have the output of such a field be directly tied to the detection of it and really streamlines the process. This primarily helps to plug in an otherwise basic html file with a couple curly braces into an existing framework like a CMS for interpretation and streamlines the production of sites when you're on a schedule.
2) Ability to control the executing environment completely. This means you do not have to worry about user-submitted code in any situation where you might expose the language to them. Mailing list software frequently makes use of mail templates, social sites may offer a range of flexibility for output of the user's page and a template language might be appropriate to expose to power users... These situations may not be appropriate to actually expose PHP to those users.
Secondary Benefits:
3) A true domain specific language which you can tune to display the HTML of your project. You can create a tag to display a user for example {DisplayUser|({$UserSession[User][Id]})(narrow)} (note, similar idea to a view class). Express your intent directly. This is, of course, a contrived example, but even if it's only a thin semantic wrapper, it can be beneficial to write this:
{url|http://www.someplace.com/({$path})/({$f ... {$value2})}
vs:
echo htmlentities("http://www.someplace.com/".rawurlencode ... ode($file).
"?value1=".urlencode($value1)."&value2=".urlencode($value2));
4) One more layer of presentation stripped from the actual logic. This is the fourth and least important point as it can be replicated in function by Model View Controller frameworks such as CakePHP and the Zend Framework. This is in contrast with Smarty's "why use" page which basically tries to sell you that this is the most important thing a template language can do.
"Why this over Smarty?"
This is a very good question and one which bears scrutiny. Smarty offers a few key benefits this project lacks, the primary ones being built-in caching and compilation to PHP before execution instead of interpretation directly into output. I have not run benchmarks, but I strongly suspect Smarty will out-perform Muted Template performance-wise. How important this is depends largely on the scope of a project.
That said, I do plan on introducing caching. Compilation to PHP would be a big task, but is something that I believe could be achieved and I was planning on approaching this as a separate project if the language started to gain popularity. Before that I need to set up a proper documentation site as I mentioned earlier.
Now, with that said, the benefits you have with Muted Template over Smarty are primarily in the flexibility of the parsing mechanism. The Smarty parsing system is built around regex which makes certain things kind of clunky and generally means that nesting tags must be supported by each tag developed (as I understand it). It also means that we can more intelligently deal with braces you may encounter within javascript or CSS without having to use something like {literal} every time you want to use a bracket.
Beyond this, the language is slimmer and tighter, but provides more structure (Smarty is heavily attribute based, Muted Template relies more on parameter lists).
This is just a very basic comparison of a foreach loop:
Muted Template:
Smarty:
However, if you wanted to notate the key and value with labels, Muted Template ignores everything outside of the () in a parameter list, so you can write notation such as if you prefer:
Let's look at setting variables:
Muted Template:
Smarty:
It may seem like a minor point, but smarty is -incredibly- verbose and doesn't really lend itself well to compact and easily scannable code. This is mostly because it tries to disguise itself as a markup language when it just is not. Muted Template is unafraid of looking different than HTML, and it is different enough from PHP that it cannot be confused for either. Some people may think this is a bad thing, but I believe it helps keep the language mentally distinct and yet low-profile which is one of the goals considering it is meant to be embedded in otherwise static markup language and things can get messy if boundaries are not observed.
It is important to note here that Muted Template can actually execute arbitrarily nested commands. We could, for example, execute this:
The above outputs Hello World
It's incredibly powerful, I'm not advocating executing things like this, but the fact that you can is interesting and means that if you -do- need to you are not stuck. I do not believe Smarty is nearly this flexible with its parsing of nested template tags. So primarily I believe the benefit in Muted Template is in language flexibility, nesting, and the syntax. I should mention that in situations where you need to, you can escape using \ to output control flow characters. The ability to escape any control character in a context-knowledgeable way was built in to the language. I'm not sure how or if smarty allows anything to be escaped due to regex parsing.
A good way to get a sense for what the language reads like is to simply look in the Parse Tags folder where at the top of each tag is a quick example of common use.
Really it's difficult to provide examples on a large enough scale to cover the language. It's really a project in and of itself to set up appropriate documentation. It is something I would like to do, and plan on doing. For now, the various unit tests provide a very lame set of examples of edge cases and regular use of individual tags which you can check out.
"Why use a template language at all?"
There are more situations in which a template language is the wrong choice than there are in which it is the right choice. There are, however, some benefits to running a scripting language over PHP and I will list them:
Primary Reasons:
1) Ability to reflect on what has been parsed. With a PHP "template" you really don't get anything more than you put in to it. This means that if you wanted to keep track of all the links that were displayed you would end up needing to parse everything anyway. Let's say you want to create a CMS solution which detects fields such as "title" "body" "title image" and so on so that you can get that information from someone managing the site and display it appropriately later? This allows you to have the output of such a field be directly tied to the detection of it and really streamlines the process. This primarily helps to plug in an otherwise basic html file with a couple curly braces into an existing framework like a CMS for interpretation and streamlines the production of sites when you're on a schedule.
2) Ability to control the executing environment completely. This means you do not have to worry about user-submitted code in any situation where you might expose the language to them. Mailing list software frequently makes use of mail templates, social sites may offer a range of flexibility for output of the user's page and a template language might be appropriate to expose to power users... These situations may not be appropriate to actually expose PHP to those users.
Secondary Benefits:
3) A true domain specific language which you can tune to display the HTML of your project. You can create a tag to display a user for example {DisplayUser|({$UserSession[User][Id]})(narrow)} (note, similar idea to a view class). Express your intent directly. This is, of course, a contrived example, but even if it's only a thin semantic wrapper, it can be beneficial to write this:
{url|http://www.someplace.com/({$path})/({$f ... {$value2})}
vs:
echo htmlentities("http://www.someplace.com/".rawurlencode ... ode($file).
"?value1=".urlencode($value1)."&value2=".urlencode($value2));
4) One more layer of presentation stripped from the actual logic. This is the fourth and least important point as it can be replicated in function by Model View Controller frameworks such as CakePHP and the Zend Framework. This is in contrast with Smarty's "why use" page which basically tries to sell you that this is the most important thing a template language can do.
"Why this over Smarty?"
This is a very good question and one which bears scrutiny. Smarty offers a few key benefits this project lacks, the primary ones being built-in caching and compilation to PHP before execution instead of interpretation directly into output. I have not run benchmarks, but I strongly suspect Smarty will out-perform Muted Template performance-wise. How important this is depends largely on the scope of a project.
That said, I do plan on introducing caching. Compilation to PHP would be a big task, but is something that I believe could be achieved and I was planning on approaching this as a separate project if the language started to gain popularity. Before that I need to set up a proper documentation site as I mentioned earlier.
Now, with that said, the benefits you have with Muted Template over Smarty are primarily in the flexibility of the parsing mechanism. The Smarty parsing system is built around regex which makes certain things kind of clunky and generally means that nesting tags must be supported by each tag developed (as I understand it). It also means that we can more intelligently deal with braces you may encounter within javascript or CSS without having to use something like {literal} every time you want to use a bracket.
Beyond this, the language is slimmer and tighter, but provides more structure (Smarty is heavily attribute based, Muted Template relies more on parameter lists).
This is just a very basic comparison of a foreach loop:
Muted Template:
Code: Select all
{each|$a|($key)($value)|
{$key} = {$value}<br/>
}Code: Select all
{foreach from=$a key=$key item=$value}
{$key} = {$value}<br/>
{/foreach}Code: Select all
{each|$a|key=($key) value=($value)|}Muted Template:
Code: Select all
{set|($variable1)(value1) ($variable2)({math|5 * 2})}
or, more clearly:
{set|($variable1) = (value1), ($variable2) = ({math|5 * 2})}
or, if you like:
{set|
($variable1) = (value1),
($variable2) = ({math|5 * 2})
}Code: Select all
{assign var='$variable1' value='value1'}
{assign var='$variable2' value=`5 * 2`}It is important to note here that Muted Template can actually execute arbitrarily nested commands. We could, for example, execute this:
Code: Select all
{set|($a[0]) = (Hello), ($a[1]) = ( ), ($a[2]) = (World)}
{set|($tagName) = (math)}
{set|($result) = ({if|{{$tagName}|5 * 2} == 10|{each|$a|($value)|{$value}}||Boo!})}
{$result}It's incredibly powerful, I'm not advocating executing things like this, but the fact that you can is interesting and means that if you -do- need to you are not stuck. I do not believe Smarty is nearly this flexible with its parsing of nested template tags. So primarily I believe the benefit in Muted Template is in language flexibility, nesting, and the syntax. I should mention that in situations where you need to, you can escape using \ to output control flow characters. The ability to escape any control character in a context-knowledgeable way was built in to the language. I'm not sure how or if smarty allows anything to be escaped due to regex parsing.
A good way to get a sense for what the language reads like is to simply look in the Parse Tags folder where at the top of each tag is a quick example of common use.
Last edited by M2tM on Tue Mar 02, 2010 10:39 pm, edited 2 times in total.
Re: Muted Template <Review/Critique/Suggestions>
So let me clarify, I am not touting this as a replacement for any kind of MVC frameworks. I believe it can even be used within such a framework for execution in specific situations if your problem is similar to my own. The strength of this is fairly domain specific to the problems I am personally facing developing a robust and easy to set up CMS based on having minimal work required in taking a static site design and turning that into a dynamic user-modifiable set of templates.
The thing is easy to set up and run:
$engine = new MutedTemplate();
$engine->parse('code');
If you would like to set some values you can do so:
Finally, here is a basic example of the load command and how a basic static site -might- be set up:
twoColumnTemplate.html
introPage.html
joeIntroLeftColumn.html
joeIntroRightColumn.html
And then we might run this in php like this:
$engine = new MutedTemplate();
$engine->parse('templates/pages/'.$_GET['Page'].'Page.html', MV_FILE); //we'd assume a valid $_GET['Page'] variable.
Note the use of MV_FILE which is to specify the input source which is absolutely important whenever recieving information from the user as otherwise we might get arbitrary rendering occurring if MV_ANY is used and it just parses the user data as a string.
//MV_ANY If a file is found it will open and parse it, if not it will basically parse a string.
//MV_FILE is set to indicate only files may be loaded and it will output an error message if the file does not exist.
//MV_STRING is set to indicate that only a string may be supplied, it will parse a filename as if it were just a string.
The thing is easy to set up and run:
$engine = new MutedTemplate();
$engine->parse('code');
If you would like to set some values you can do so:
Code: Select all
$engine = new MutedTemplate();
$engine->set('a', array(1, 2, 3, 4, 5));
$engine->set('helloworld', 'Hello World');
$engine->parse('
{$helloworld}<br/>
{each|$a|($value)|
{$a}<br/>
}
');twoColumnTemplate.html
Code: Select all
{load|templates/header.html}
<div>
{$leftContents}
</div>
<div>
{$rightContents}
</div>
{load|templates/footer.html}
Code: Select all
{load|templates/twoColumnTemplate.html|
($leftContents)=(
{load|templates/pages/introParts/joeIntroLeftColumn.html}
)
($rightContents)=(
{load|templates/pages/introParts/joeIntroRightColumn.html}
)
}
Code: Select all
...
Welcome to my site, enjoy your stay.
...
joeIntroRightColumn.html
Code: Select all
...
Check out my blog and some interesting links in my gallery!
...
$engine = new MutedTemplate();
$engine->parse('templates/pages/'.$_GET['Page'].'Page.html', MV_FILE); //we'd assume a valid $_GET['Page'] variable.
Note the use of MV_FILE which is to specify the input source which is absolutely important whenever recieving information from the user as otherwise we might get arbitrary rendering occurring if MV_ANY is used and it just parses the user data as a string.
//MV_ANY If a file is found it will open and parse it, if not it will basically parse a string.
//MV_FILE is set to indicate only files may be loaded and it will output an error message if the file does not exist.
//MV_STRING is set to indicate that only a string may be supplied, it will parse a filename as if it were just a string.
Last edited by M2tM on Tue Mar 02, 2010 10:29 pm, edited 3 times in total.
Re: Muted Template <Review/Critique/Suggestions>
:-/pytrin wrote:I'll use a small example for demonstration.
I'll use a realistic example for demonstration
Code: Select all
<form id="co-shipping-method-form" action="<?php echo $this->getUrl('checkout/cart/estimateUpdatePost') ?>">
<dl class="sp-methods">
<?php foreach ($_shippingRateGroups as $code => $_rates): ?>
<dt><?php echo $this->getCarrierName($code) ?></dt>
<dd>
<ul>
<?php foreach ($_rates as $_rate): ?>
<li<?php if ($_rate->getErrorMessage()) echo ' class="error-msg"';?>>
<?php if ($_rate->getErrorMessage()): ?>
<?php echo $_rate->getErrorMessage() ?>
<?php else: ?>
<input name="estimate_method" type="radio" value="<?php echo $this->htmlEscape($_rate->getCode()) ?>" id="s_method_<?php echo $_rate->getCode() ?>"<?php if($_rate->getCode()===$this->getAddressShippingMethod()) echo ' checked="checked"' ?> class="radio" />
<label for="s_method_<?php echo $_rate->getCode() ?>"><?php echo $_rate->getMethodTitle() ?>
<?php $_excl = $this->getShippingPrice($_rate->getPrice(), $this->helper('tax')->displayShippingPriceIncludingTax()); ?>
<?php $_incl = $this->getShippingPrice($_rate->getPrice(), true); ?>
<?php echo $_excl; ?>
<?php if ($this->helper('tax')->displayShippingBothPrices() && $_incl != $_excl): ?>
(<?php echo $this->__('Incl. Tax'); ?> <?php echo $_incl; ?>)
<?php endif; ?>
</label>
<?php endif ?>
</li>
<?php endforeach; ?>
</ul>
</dd>
<?php endforeach; ?>
</dl>
<div class="buttons-set">
<button type="submit" title="<?php echo $this->__('Update Total') ?>" class="button" name="do" value="<?php echo $this->__('Update Total') ?>"><span><span><?php echo $this->__('Update Total') ?></span></span></button>
</div>
</form>Re: Muted Template <Review/Critique/Suggestions>
When it's large blocks of markup inside a conditional, I often separate it to sub-templates. But when it's a one/two-liner, I really don't see the benefit. Also, I very rarely have nested loops inside a template, but one-level loops is quite acceptable in my opinion.
By the way, I hope we aren't stealing this thread from the OP, maybe this discussion should continue elsewhere...
By the way, I hope we aren't stealing this thread from the OP, maybe this discussion should continue elsewhere...