Page 2 of 4

Re: Who wants to have a template engine discussion? :)

Posted: Mon Jan 19, 2009 5:15 pm
by Luke
Chris Corbyn wrote:If you want a solution that doesn't introduce yet another syntax, try playing with XML and XSLT. You provide your model as XML... the your template (XSL) creates a view in HTML. I also think you can extend a template with XSL (though I'm not an expert so I could be wrong, I've just seen it done in DITA).

Never feels nicer than PHP though.

I agree with pytrin too. IMHO, passing objects (just domain object mind you) into the view is an everyday practice for me. I don't want my page controller to know specifically *what* data it will use from my $auction domain object, I just know that my page displays an auction. What's so different about this:

Code: Select all

$this->view->set('auction', $auction);

Code: Select all

<h2 class="auctiontitle"><?php $this->escape($auction->getTitle()); ?></h2>
And this....

Code: Select all

$this->view->set('auctionTitle', $auction->getTitle());

Code: Select all

<h2 class="auctiontitle"><?php $this->escape($aucionTitle); ?></h2>
Your domain objects are just containers for information, and many believe it's a best-practice to allow your view to grab the data they need rather than being passed the information they need.

And no, don't move complex view logic into the page controller... that's simply not the correct place for it. View logic can get complex (when you've got loops full of conditions), but changing the foreach and the if..else syntax doens't remove the complexity, it just changes the syntax. It's still view logic at the end of the day.
I agree, like I said, getters will be available in my template engine. You can access methods, you just can't pass arguments to them. It would look something like this

Code: Select all

<?= $auction.gettitle ?>
That would actually make a call to $auction->getTitle() and output the return value

Re: Who wants to have a template engine discussion? :)

Posted: Mon Jan 19, 2009 6:11 pm
by Chris Corbyn
allspiritseve wrote:
sergio-pro wrote:But still Prado don't use logic in template. Every component has template and php class having all the logic.
I highly doubt that. You can't completely separate display logic and HTML, except for the simplest of cases. It really comes down to presentation logic in your templates or HTML in your views... I will take the first option any day.
I don't doubt it, but I can't say I agree with the approach. Have you ever programmed with J2EE? Java typically uses JSP as its template language and has this concept of Tags, so you can create a custom tag that looks something like:

Code: Select all

<namespace:mytag attr="value" />
That tag has an accompanying class (which you write) that specifies the logic taken by the view whenever that tag is used. Commonly it's used for fetching JavaBeans and displaying their data.

In PHP you could do a similar thing (and I seem to remember somebody mentioning WACT in this repsect). It sounds like Prado takes a similar approach.

So I think you're wrong by saying that it *can't* be done. ~sergio-pro obviously knows what he's talking about, it's just another way of doing things.

Like ~pytrin, I tend to break my views down into smaller .php files that I can include inside one other. This allows me to (consistently) have second and third level navigation across various pages that are not common to the entire site. It also allows me to re-use certain page elements like list views in different parts of the system. I could do exactly the same thing with a tag system like I mentioned above, but I'd then have view logic scattered around.

I'm sort of split really... I just use PHP in my templates, though I can see how forcing those small elements of view logic into a class (with it's own scope) can be of benefit.

Re: Who wants to have a template engine discussion? :)

Posted: Mon Jan 19, 2009 6:12 pm
by Chris Corbyn
In relation to my post above regarding JSP/Java tag libs:

http://java.sun.com/products/jsp/tutori ... esTOC.html

Re: Who wants to have a template engine discussion? :)

Posted: Mon Jan 19, 2009 8:09 pm
by Chris Corbyn
The Ninja Space Goat wrote:I agree, like I said, getters will be available in my template engine. You can access methods, you just can't pass arguments to them. It would look something like this

Code: Select all

<?= $auction.gettitle ?>
That would actually make a call to $auction->getTitle() and output the return value
That looks like a good idea to me. Or you could just have an ImmutableDomainObject wrapper or something that's used for passing a domain object into a view.

The syntax reminds me of Objective-C with its property synthesizers.

Re: Who wants to have a template engine discussion? :)

Posted: Mon Jan 19, 2009 8:35 pm
by Christopher
Maybe I am missing a major point here, but what is the advantage of this over regular old PHP templates?

Code: Select all

<?= $auction.gettitle ?>
(I am already annoyed that it uses short tags)

I could see if you wanted to do something XML like this:

Code: Select all

<auction:gettitle attr="value" />
Or maybe:

Code: Select all

{auction.gettitle foo="100" bar="Hello World..."}
 
Or even URL style:

Code: Select all

{auction_gettitle?foo=100&bar=Hello World...}
(there is a lot of library support for parsing that)

Re: Who wants to have a template engine discussion? :)

Posted: Mon Jan 19, 2009 8:54 pm
by Luke
actually I just posted that because I didn't want to get anybody started on the xml-ish syntax, I just wanted to show chris how I would access a method. the syntax I'm using for my new template language is precisely what you guys have mentioned. Here is a sample of it.

Code: Select all

<html>
    <head>
        <title><tt:block name="title">Luke is awesome</tt:block></title>
        <tt:block name="head">
            <tt:include template="elements/head.phtml" />
        </tt:block>
    </head>
    <body>
        <div id="head">
            <h1 id="logo">Luke Visinoni</h1>
            <tt:block name="header">
                <tt:include template="elements/header.phtml" />
            </tt:block>
        </div>
        <div id="wrap">
            <tt:flash namespace="error" />
            <tt:block name="content">
                <!-- content will be placed here -->
            </tt:block>
        </div>
        <div id="foot">
            <tt:block name="footer">
                <tt:include template="elements/footer.phtml" />
            </tt:block>
        </div>
    </body>
</html>
 
post.html

Code: Select all

<tt:extends template="base.html" />
<tt:block name="title">Luke's Posts</tt:block>
<tt:block name="content">
    <h2><a href="<tt:url route="post_view" slug="$post.slug" />">A link to a post</a></h2>
    <h3><tt:out expr="$post.date" date="m-d-Y g:ia" /></h3>
    <div class="body">
        <tt:out expr="$post.content" textile="true" />
    </div>
</tt:block>
 

Re: Who wants to have a template engine discussion? :)

Posted: Mon Jan 19, 2009 9:47 pm
by Chris Corbyn
Have you looked down the XSLT road? :) That would force you to provide your model in XML (you could easily add XML output to domain objects) and therefore have no way of modifying the data. It would also give you the flexibility to push said data to the browser in AJAX applications.

Code: Select all

<auction>  <title>Example auction title</title>  <subtitle>...</subtitle>  <details>...</details> 

Code: Select all

<div class="auction">  <h2><xsl:value-of select="/auction/title" /></h2>....
At least you've got all the looping and conditional constructs you'd need already provided for you.

Could also come in useful if you want to provide a remote access API.

And of course, AJAX, if you want to pass that model down to the client.

[js]var title = myXpathWrapper(xmlObject, "/auction/title");[/js]

Re: Who wants to have a template engine discussion? :)

Posted: Mon Jan 19, 2009 9:54 pm
by Luke
hmm, yea xslt does look interesting. I've been curious about it for a while actually, I will play around with it.

Re: Who wants to have a template engine discussion? :)

Posted: Thu Jan 22, 2009 11:00 am
by VladSun
arborint wrote:
VladSun wrote:My PHP projects don't use any HTML (except for the BODY tag and a few SCRIPT tags) - only JSON server-side views and ExtJS client side :)
I would be great if you would start a new thread on JSON server-side views and ExtJS client side. I'd be interested in learning more...
Done! :)
viewtopic.php?f=19&t=93937

Re: Who wants to have a template engine discussion? :)

Posted: Thu Jan 22, 2009 11:16 am
by Eran
I have an example which I think would be hard to replicate easily with a template engine. Suppose I want to draw a monthly calendar:

Code: Select all

 
<table>
     <tr>
<?php
$rows = $this -> rows; //A result set of database events sorted by date
$row = current($rows);
$days = 1;
$html = '';
foreach($monthDays as $date) { //$monthDays is an array of date objects, once for each day in the month
       if($days % 7 == 0) { // Split weeks into rows
             $html .= '</tr><tr>';
       }
       $html .= '<td>' . $date -> toString('d');
       while($row !== false && $date -> isEqual($row['date']) ) { //Advance the result set only for matching dates
            $html .= '<br />' . $row['event'];
            $row = next($rows);
       }
       $html .= '</td>';
} 
echo $html;
?>
    </tr>
</table>
The part which I think would be hard to implement in a template engine would the while loop with the dependent logic. You could claim that this could be abstracted outside using a view helper or something similar, but what if it only appear in one view? should I abstract everything even if there is no other need except to fit in a template engine?

Re: Who wants to have a template engine discussion? :)

Posted: Thu Jan 22, 2009 12:38 pm
by sergio-pro
Hi

Looks like you have events from DB in a format like:

Code: Select all

 
$rows[] = array('date'=>'2009-01-03', 'event'=>'event 3');
$rows[] = array('date'=>'2009-01-04', 'event'=>'event 4');
$rows[] = array('date'=>'2009-01-07', 'event'=>'event 7');
 
There are a couple of ways you can simplify this:

1. You can convert this array into:

Code: Select all

 
$rows['2009-01-03'] = array('date'=>'2009-01-03', 'event'=>'event 3');
$rows['2009-01-04'] = array('date'=>'2009-01-04', 'event'=>'event 4');
$rows['2009-01-07'] = array('date'=>'2009-01-07', 'event'=>'event 7');
 

and then having much easier access to an event by date

2. You can select full set of dates from MySql DB joined with events, that will look like:

Code: Select all

 
$rows[] = array('date'=>'2009-01-01', 'event'=>NULL);
$rows[] = array('date'=>'2009-01-02', 'event'=>NULL);
$rows[] = array('date'=>'2009-01-03', 'event'=>'event 3');
$rows[] = array('date'=>'2009-01-04', 'event'=>'event 4');
$rows[] = array('date'=>'2009-01-05', 'event'=>NULL);
...
$rows[] = array('date'=>'2009-01-29', 'event'=>NULL);
$rows[] = array('date'=>'2009-01-30', 'event'=>NULL);
 
3. In component-like framework the "while" code can be moved to a component class.

4. You can abstract it to a view helper. Just do it (nike:)).
Look at the code you provided - it has an error. And it is not obvious. Because this code looks like a mess - due to php-html mix.

You can say - its your way of doing things. And there are thousands of php coders that do that way.
But think of it in another way - ASP.NET, Java web-frameworks, RoR, Django - they all use templates that separates html from language codes.

Re: Who wants to have a template engine discussion? :)

Posted: Thu Jan 22, 2009 1:02 pm
by Eran
Actually, the date are in a full MySQL format (Y-m-d H:i:s). Joining that against a set of dates would require logic in the query that is above trivial, making an expensive query even more expensive, perhaps unfeasible, so that's not an option.
Option #1 you gave is actually what I do currently, but is not as simple as you put it due to the reason above (full date with time). Each date index represents an array of events.
In component-like framework the "while" code can be moved to a component class
Putting HTML in non-view classes is a big no-no in my book. Since the while loop solves the problem by appending html inline, it can't go there.
You can abstract it to a view helper. Just do it (nike:)).
I suggested this option - and said I wouldn't want to do if it happens just once in the code. You don't create a helper for every singular instance of your view logic - that's what view templates are for (exactly my point).
Look at the code you provided - it has an error. And it is not obvious. Because this code looks like a mess - due to php-html mix.
This is mock code I wrote in the post, not from any application code I use... but where is the error? can't see it. Anyway, the only thing against this is that it really isn't clear to someone who hasn't wrote it, that I agree. It is not a mess to me though, since I consider it presentational logic (I'm getting tired of writing that word..).
You can say - its your way of doing things. And there are thousands of php coders that do that way.
I just brought it as an example. Everybody has their way of doing things, and you are not the exception.

My main problem with moving this logic elsewhere is that it is inherently presentational logic. It has no other use, and will not be reused outside view/templates. Why should it be a helper if its just one instance? it might be moved to a helper later if it's needed, but having the template engine making decisions for you is really restrictive, no matter how you spin it. Doing cartwheels to please the template engine is not my idea of a good design.

Re: Who wants to have a template engine discussion? :)

Posted: Thu Jan 22, 2009 1:18 pm
by sergio-pro
As for SQL solution - not so expensive - try it :)
Option #1 you gave is actually what I do currently, but is not as simple as you put it due to the reason above (full date with time). Each date index represents an array of events.
Then your example is completely incorrect. And will never work even without any template engine.
Putting HTML in non-view classes is a big no-no in my book. Since the while loop solves the problem by appending html inline, it can't go there.
Component-class - is a kind of view class, since components are part of View layer. It also contains some controller funcionality - but it is a question of another discussion.

And you say this code is clear for you, but you cannot see an error in it.

Re: Who wants to have a template engine discussion? :)

Posted: Thu Jan 22, 2009 1:26 pm
by allspiritseve
sergio-pro wrote:Then your example is completely incorrect. And will never work even without any template engine.
Why won't it work?
sergio-pro wrote:And you say this code is clear for you, but you cannot see an error in it.
Could you kindly explain what error you have found?

Re: Who wants to have a template engine discussion? :)

Posted: Thu Jan 22, 2009 1:30 pm
by Eran
And you say this code is clear for you, but you cannot see an error in it.
You're not making any case for yourself by being cryptic. Spit it out or let it go.
As for SQL solution - not so expensive - try it
I'm quite familiar with the SQL solution... and again you are missing my point. The original query already joins 6 tables on a 2Gb database and is quite expensive as is. In any case, the result set would be two dimensional, and there is more hierarchy here.
Then your example is completely incorrect. And will never work even without any template engine.
:?
I've used similar code many times in the past, and it worked just as expected.

If anyone else has more constructive ideas on how to integrate something like this in an engine like Ninja suggested, I would like to hear it. Also, how can you pass parameters to objects inside a view in a template system?