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

ADVANCED: Recursion with Smarty
Goto page Previous  1, 2, 3, ... 9, 10, 11  Next
 
Post new topic   Reply to topic    Smarty Forum Index -> Tips and Tricks
View previous topic :: View next topic  
Author Message
Transistor
Smarty Rookie


Joined: 20 May 2003
Posts: 9

PostPosted: Sun May 25, 2003 4:02 pm    Post subject: Recursion benchmarks Reply with quote

@boots
Quote:
recursion is good, but not because XSLT uses it and certainly NOT good for everything


Yes, but it is the (imo only true) solution to display a tree structure.

As mentioned above i did some tests today.

Tree with 642 leaves ... more or less nested taken from a board.
Apache with PHP 4.3 module without accelerator.
5 measurements per engine, all in seconds.

Here are the results:

Smarty (with {include ....} per reply block but not for every single leaf):
4,39
4,11
4,22
4,16
4,09

Smarty (with plugin):
0,12
0,14
0,13
0.15
0,13

XSLT (Sablotron):
1,10
1,13
1,20
1,11
1,10

XSLT (DomXSLT):
0,58
0,48
0,54
0,46
0,46

Very impressive IMO.
I've to mention that the DomXSLT version is not yet optimized. I use DomXSLT with a XML and a XSLT string. I think it could be a _little_ bit faster if I build the DOM tree in memory myself.
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Sun May 25, 2003 5:12 pm    Post subject: Reply with quote

cool! I agree -- certain data structures beg for recursive implementations Smile On-the-other-hand, real world problems tend to have limitiations that stop truly recursive behaviour. eg: it is okay to build menus with only up to 4 levels, etc.

Never-the-less, I'm a big fan of recursion and its speed penalty in Smarty has until now been a bit of downer for me. Your tests are very encouraging, Transistor!

Are you switching from XSLT to Smarty or are you using both these days?
Back to top
View user's profile Send private message
Transistor
Smarty Rookie


Joined: 20 May 2003
Posts: 9

PostPosted: Sun May 25, 2003 7:52 pm    Post subject: Reply with quote

Quote:
cool! I agree -- certain data structures beg for recursive implementations On-the-other-hand, real world problems tend to have limitiations that stop truly recursive behaviour. eg: it is okay to build menus with only up to 4 levels, etc.


Yes. But for threadbased forums this is not the case.

Quote:
Are you switching from XSLT to Smarty or are you using both these days?


I use both. XSLT because it is a standard and a lot of people can handle it i think. Former versions of the board support xslt only. So i need it for compatibility too.
Smarty because it does not have such a restrictive syntax like xslt and because it does not need a PHP extension.
So I leave it to the template designer and the user what skins they will install and use. I hope that the first smarty based solution will go online this week.[/quote]
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Sun May 25, 2003 10:50 pm    Post subject: Reply with quote

@Transistor: your numbers make me feel, i should support my defun-hack a little more. Smile

i think we still need some better function-names for it.
"call-template" instead of "fun" is not good, because of the "-".
"template" is not good for the "defun". a "template" is almost always a file in smarty nomenclature.

i'd vote for calling our functions inside templates "sub-templates".

instead of "defun" for declaring a sub-template we could say:
{sub name="sub-template-name"}...{/sub} to define a sub-template
instead of "fun" for calling such a sub-template we could say:
{include_sub name="sub-template-name"}
"include_sub" since it behaves a bit like {include} or {include_php} template, especially regarding variable's scope.

what do you think?

i would also like to convert the "fun"-compiler-function to a normal plugin-function. this will imply a little performance hit, but the plugin becomes simpler and cleaner. overall it's easiest to do as little as necessary at compiler-level and the rest at "normal" plugin-level IMHO.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Mon May 26, 2003 3:16 am    Post subject: Reply with quote

@messju: woo hoo!

I think you should avoid the "template" names altogether. "block", "callblock"? IIRC they were called template functions back in XSL -- which makes sense, since they are a bit of both. Personally, I would have prefered "section" but unfortunately, that is not available. "define" and "do"? Is there a designer in the house?

I almost disagree with your last point, though -- I think that as much should be done at the compile stage as possible, since that is likely the least expensive place (overall) to do things for a given page over its lifetime.
Back to top
View user's profile Send private message
andre
Smarty Pro


Joined: 23 Apr 2003
Posts: 164
Location: Karlsruhe, Germany

PostPosted: Mon May 26, 2003 9:08 am    Post subject: Reply with quote

Perhaps you could call it {proto} or {prototype} ? Confused
Back to top
View user's profile Send private message
SMK2003
Smarty n00b


Joined: 04 May 2003
Posts: 1
Location: Karlsruhe, Germany

PostPosted: Mon May 26, 2003 4:17 pm    Post subject: Reply with quote

I'm using a hacked Smarty that allows defining macro blocks (similar to XSLT templates) and calling them just like function-type plugins. These macros can be defined as either inline or block macros.

Define a block macro:
Code:
{macro name="fooBlock" inline="false"}
  ... HTML-/Smarty-Code, using $smarty.macro.* vars ...
  {$smarty.macro.param.bar} to access parameter "bar"
  {$smarty.macro.content} to access CDATA
{/macro}


Call a block macro:
Code:
{fooBlock bar="baz"}I am CDATA and will be accessible via $smarty.macro.content!{/foo}


Define another macro, this time inline:
Code:
{macro name="fooInline" inline="true"}
  ... HTML-/Smarty-Code, can only use $smarty.macro.param.* vars ...
{/macro}


Call an inline macro:
Code:
{fooInline bar="baz"}


One interesting thing is swapping out all macros into its own .TPL file, building sort of a template library.

The example given by Transistor looks like this:
Code:
{* Define inline macro *}
{macro name="myTree" inline="true"}
<ul>
{foreach from=$smarty.macro.param.element item=element}
   {if $element.name}<li>{$element.name}</li>{/if}
   {if $element.element}{myTree element=$element.element}{/if}
{/foreach}
</ul>
{/macro}
 
{* Call the macro *}
{myTree element=$tree}


Notes:
My implementation is optimized for rendering speed - no eval()'s, just pure PHP power. Compile times suffer from an increased number of function plugin lookups, similar to those in the other _compile_*_tag() methods.

Download:
Diffs exist against Smarty 2.5.0 (can't see any performance gains from the so called "abstraction" in cvs), feel free to grab'em >here<.

Thx:
Velocity template engine for their idea of macro blocks...

Cheers,
·SMK·
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Mon May 26, 2003 4:53 pm    Post subject: Reply with quote

SMK2003 wrote:

Diffs exist against Smarty 2.5.0 (can't see any performance gains from the so called "abstraction" in cvs)...


i know it's off-topic, but anyway: you are not supposed to see vast performance gains by the "abstraction", if any. the big question is if you encounter any performance-*decrease* by it. Smarty.class.php has reached quite some size, and by moving certain parts out of the core, we are able to add new stuff, that doesn't necessarily count to Smarty.class.php's size but only has to be parsed by people who actually use this certain feature. we all know there is overhead by abstraction, but we hope to equalize it, by decreasing the size of the core's core.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Mon May 26, 2003 6:35 pm    Post subject: Reply with quote

@SMK:
of course your syntax looks nifty. there are pros and cons in calling the macros without a wrapper simply by name. (polluted namespace. but {macronname} ressembles the look of ($varname) which it is kind of)

having a block that is passed to the macro looks also useful. but i wonder when it is more useful to have passed the block-contents as a string (that is accessible via {$smarty.macro.content}) and when it is better to see the block as an iterator that is re-executed on every use of {$smarty.macro.content} inside the macro. of course your way is faster at display, but both ways have it's merits.

unfortunately i cannot apply your patch against my 2.5.0 Smarty_Compiler.class.php, maybe it's just me, i didn't dig further into it.

greetings
messju
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Transistor
Smarty Rookie


Joined: 20 May 2003
Posts: 9

PostPosted: Mon May 26, 2003 8:26 pm    Post subject: Reply with quote

I agree with boots. What can be implemented as compiler plugin should be implemented as that.
I divided the "function" plugin and the "callfunction" plugin in two files.
I also added the line
Code:
$smarty->register_compiler_function("/defun","smarty_compiler_defun_close");

at the first line of the smarty defun plugin. So I don't need to register the plugin for the closing tag by myself and the two defun functions are connected to each other (if you open a defun block the /defun tag will be available).

Because of the "if(!function_exists....." construct it is impossible to put the defun block at the end of the template. Maybe it is better to drop the statement.

And finally another suggestion for the name of the tags:

{snippet name="xxx"}
{/snippet}
{processsnippet}

but I think {block} and {callblock} or {processblock} are better.
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Mon May 26, 2003 9:08 pm    Post subject: Reply with quote

Transistor wrote:
I agree with boots. What can be implemented as compiler plugin should be implemented as that.


yes and no. in this case maybe yes, but the template gets bigger if more stuff is emitted at compile time than a simple plugin-call. this can turn to the opposite under certain circumstances.


Quote:

I divided the "function" plugin and the "callfunction" plugin in two files.


me too Smile

Quote:

I also added the line
Code:
$smarty->register_compiler_function("/defun","smarty_compiler_defun_close");

at the first line of the smarty defun plugin. ...).


hmm, this should have been already done, by
[php:1:1e97b116ae]$this->register_compiler_function('/defun', 'smarty_compiler_defun_close'); [/php:1:1e97b116ae]
but your way may be clearer and cleaner

Quote:

Because of the "if(!function_exists....." construct it is impossible to put the defun block at the end of the template. Maybe it is better to drop the statement.


why? the if-statement only prevents php from puking if you include the same template (containg a defun-block) more than one time. maybe this doesn't work as intended, but removing it, makes it break at the other end.

Quote:

And finally another suggestion for the name of the tags:

{snippet name="xxx"}
{/snippet}
{processsnippet}

but I think {block} and {callblock} or {processblock} are better.


hmm, after SMK2003's input and the idea of having block-contents passed to the macro (or block or snippet or sub-template or whatever) i would need even more names Smile

(@SMK: may I borrow the name "macro" and the idea of passing block-contents to a "macro" from your version?) i intentionally left out the name {macro} for something so this wouldn't clash with SMK's version

{macro_def name=foo}....{/macro_def}: macro definition, macro_def-blocks may contain {macro_content}-tags to be replaced by the passed content-block
{macro_insert name=foo [params as name-value-pairs]}: simple macro-call
{macro_block name=foo [params]}...{/macro_block}: macro-call with block-contents, that are constant inside the macro
{macro_section name=foo [params]}...{/macro_section}: macro call, the block-contents are processed on each occurence of {macro_content}, not at call-time

note that you do not specifiy if the macro takes a block argument at definition, but at call-time.

this would look like a powerful structure to me, but as always all YMMV

greetings
messju
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Transistor
Smarty Rookie


Joined: 20 May 2003
Posts: 9

PostPosted: Mon May 26, 2003 9:58 pm    Post subject: Reply with quote

Quote:
why? the if-statement only prevents php from puking if you include the same template (containg a defun-block) more than one time. maybe this doesn't work as intended, but removing it, makes it break at the other end.


Normally php will execute all includes in a php file first, but if they are in a block they will be evaluated at execution time. So I can not call a function before the function declaration is reached.
Removing it will result in a php error, when the plugin uses the same name twice. I think that's ok because smarty throws php errors already for tag missmatches and so on.

@SMK2003 & @messju
What can I do with those macros and what are the advantages? What is the difference between inline and not inline (just the possibility to access macro.content?)? ...maybe it is too late for me today Wink
Back to top
View user's profile Send private message
Peter Robins
Smarty n00b


Joined: 08 Jun 2003
Posts: 1

PostPosted: Sun Jun 08, 2003 9:11 am    Post subject: Re: Recursion for HTML List Reply with quote

Transistor wrote:


Code:
{foreach from=$element item=element}
   <li>{$element.name}</li>
   {if $element.element}
   <ul>{include file="test-recursion.tpl" element=$element.element}</ul>
   {/if}
{/foreach}


This code works but is not very fast.

I think the lack of true recursion is a big problem not only for me




I agree that this is a problem, as recursion is surely quite a common requirement: menus, directory structures, etc - any array of unknown depth and length. I have a very similar structure to Transistor's above using file includes, and, yes, it works, and yes, it's slow.

A simple way to cut down on the file include overhead would be to be able to 'include' a variable rather than a file, then you could 'include' the template file into the variable and use that in your recursion logic. Something like:

Code:
{include file="test-recursion.tpl" assign=temp}

. . .

{foreach from=$element item=element}
   <li>{$element.name}</li>
   {if $element.element}
   <ul>{include var="temp" element=$element.element}</ul>
   {/if}
{/foreach}
Back to top
View user's profile Send private message
Transistor
Smarty Rookie


Joined: 20 May 2003
Posts: 9

PostPosted: Tue Jun 10, 2003 5:22 pm    Post subject: Online now Reply with quote

@Peter Robins
Quote:
A simple way to cut down on the file include overhead would be to be able to 'include' a variable rather than a file, then you could 'include' the template file into the variable and use that in your recursion logic.


I think you can do this with the plugin posted by messju above (fun and defun). If you put the {defun} ... {/defun} "section" in a separate template you can include it and call it with {fun ....}. Not tested, but should work.

Transistor
PS: Forum with smarty templates is online for about 2 weeks now at http://www.maniac.de/
-> http://www.maniac.de/forum/pxmboard.php
Back to top
View user's profile Send private message
jewdogg
Smarty n00b


Joined: 12 Jun 2003
Posts: 1

PostPosted: Thu Jun 12, 2003 8:31 pm    Post subject: How can this be done with a database result set? Reply with quote

I currently have a table of channels (folders) that I would like to use the recursion on. Each record has a link field named ['link'] that points to a parent folder's record id. I currently have the ability with ADODB to pull as one 2 dimensional array or iterate through the process. Any ideas?
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> Tips and Tricks All times are GMT
Goto page Previous  1, 2, 3, ... 9, 10, 11  Next
Page 2 of 11

 
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