View previous topic :: View next topic |
Author |
Message |
ldrut Smarty Rookie
Joined: 22 Dec 2009 Posts: 11
|
Posted: Tue Dec 29, 2009 6:21 pm Post subject: Function declaration needed |
|
|
Apologies if I am misreading the situation (first time using the syntax) or if this is addressed in the docs somewhere, but I can't find it.
It appears that functions must be defined before referenced at the parser level. For instance the following generates a parser error on the function call line (parser, not execution error):
{test}
{function name=test}
...some code...
{/function}
Reversing the declaration and call order removes the error.
The problem is that include files are not taken into account. This means functions may not be embedded in include files and function libraries are hard to implement as the following also fails with a parser error (on hte last line of file2).
{* file1.tpl *}
{function name=test}
...some code...
{/function}
{* file2.tpl *}
{include name="file1.tpl"
{test}
Am I seeing this right?
I presume that a pre-scan of the include files for function definitions is problematic. If so, could we get a declaration syntax of some kind to declare an external function definition? Something like
{function name=test /} |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Tue Dec 29, 2009 8:46 pm Post subject: |
|
|
Currently the following does work:
{* file1.tpl *}
{function name=test}
...some code...
{/function}
{* file2.tpl *}
{function name=test}{/function}
{include name="file1.tpl"
{test}
The dummy function test gets overloaded when {include} is being executed. |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Tue Dec 29, 2009 9:38 pm Post subject: |
|
|
We will implement {call name="funcname" ...} to allow calls to externally declared functions in the next couple of days. |
|
Back to top |
|
ldrut Smarty Rookie
Joined: 22 Dec 2009 Posts: 11
|
Posted: Wed Dec 30, 2009 4:18 am Post subject: |
|
|
Thanks. Your solution sounds fine. I'll wait for Beta 6, not too much of a problem to code around for now.
BTW, is that ability to redefine a function by overwrite part of the specification or just "the way it works right now"? I can think of a couple of other places where an ability to redefine functions could come in useful. Not so useful I could not do without it though so I just want to know which way to plan. |
|
Back to top |
|
ldrut Smarty Rookie
Joined: 22 Dec 2009 Posts: 11
|
Posted: Wed Dec 30, 2009 5:12 am Post subject: |
|
|
I know its hardly urgent but while we are here, the documentation example for the {function} tag probably has an error in it. It looks to me like a function that should have two parameters, 'level' and 'data' but 'data' is missing in the declaration ('level' is missing in the call, but I presume you intended that to illustrate default values).
Confused me for a bit as from a quick glance I assumed that the syntax of a call was going to be {funcname data=gar1,arg2,...} |
|
Back to top |
|
douglassdavis Smarty Junkie
Joined: 21 Jan 2008 Posts: 541
|
Posted: Wed Dec 30, 2009 11:33 am Post subject: |
|
|
U.Tews wrote: | We will implement {call name="funcname" ...} to allow calls to externally declared functions in the next couple of days. |
Instead of dynamic function calls, forcing people to use two different styles for functions based on where the include is, and not being able to check if a function exists in the compiler how about having people put this at the top of the template:
Code: |
{uses file='library.tpl'}
|
Which would just go through and compile all functions in library.tpl.
Are there any other definitions in the templates besides with inheritance? Can't think of any, but if there are in the future, then this would become even more useful.
Another thing. Does {call name="funcname"} work for compiler functions? If not, that could be mentioned in the docs when they are written.
btw: if the functions library.tpl depend on includes in that file, this idea might not work. So, if not, nevermind. |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Wed Dec 30, 2009 11:49 am Post subject: |
|
|
What did you mean by compiler function? compiler plugins?
An idea would be to call functions defined by the {function} only by
{call name="funcname" ...} and remove the {funcname} syntax for these type of functions. It would remove also ambiguity with a possible plugin with same name. |
|
Back to top |
|
douglassdavis Smarty Junkie
Joined: 21 Jan 2008 Posts: 541
|
Posted: Wed Dec 30, 2009 12:10 pm Post subject: |
|
|
U.Tews wrote: | What did you mean by compiler function? compiler plugins?
An idea would be to call functions defined by the {function} only by
{call name="funcname" ...} and remove the {funcname} syntax for these type of functions. It would remove also ambiguity with a possible plugin with same name. |
I was thinking at first that it might be possible to call all types of functions through the dynamic call syntax, although maybe the intent was it's only to be used for functions defined in smarty code. Either way, to cut down on confusion, in the docs, the type of functions that can be called with the dynamic call syntax needs to be specified out of:
1. compiler/plugin functions such as http://www.smarty.net/manual/en/plugins.compiler.functions.php
2. plugin functions defined in PHP such as http://www.smarty.net/manual/en/plugins.functions.php
3. template functions defined in smarty code(as mentioned in this thread)
(I may have used the wrong terms)
I have no preference as far as removing the {funcname} syntax
I'm still not sure if {uses file= would work or not... I guess I just don't know enough about how the compiler works. |
|
Back to top |
|
ldrut Smarty Rookie
Joined: 22 Dec 2009 Posts: 11
|
Posted: Wed Dec 30, 2009 4:38 pm Post subject: |
|
|
Pretty much any solution is fine by me. Id' have to say though that the {funcname ...} syntax strikes me as a name collision generator. Every time you add new functionality it is bound to conflict with function names in user programs and force rewrites. Either you should carefully make a reserved keyword list before V3 release or go to the {call ...} syntax. Were it my program, I'd go to the {call ...} syntax.
No rush for me though - I'm using your suggested code as a workaround for now. Take your time and be sure it is the way you want it to be.
One suggestion I would make though is to reconsider all those name= attributes. They do make it nice in that there is no need to reserve keywords and I'm sure simplifies matters for code generation programs, but since you have already started down that road with the simplified {foreach} syntax, you may as well go all the way.
There is no reason the syntax could not just be {call funcname param1=value param2=value ...}, but leave the name= syntax available to make it easier for automatic code generation.
{include} is another one whose name attribute seems unnecessary and annoying. |
|
Back to top |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Wed Dec 30, 2009 4:42 pm Post subject: |
|
|
Quote: | Id' have to say though that the {funcname ...} syntax strikes me as a name collision generator. |
It would only collide with plugins or registered functions, and it must be unique within those anyways. |
|
Back to top |
|
ldrut Smarty Rookie
Joined: 22 Dec 2009 Posts: 11
|
Posted: Wed Dec 30, 2009 7:29 pm Post subject: |
|
|
If you say - I am pretty new to Smarty and the internals are still pretty much a mystery to me. I do think though that making some of the 'name=' optional where the parameter is required anyway bears looking at.
But then as I said, the internals are a mystery to me. It may be more trouble than it is worth. As well, that does increase the chance of name collision (with parameter names) so maybe the idea does not have merit.
Just my usual over-analyzing.
On the whole though I'd say I rather like Smarty. I'm in the process of rewriting my company website using it. It has bother been an easy process and has eliminated some really ugly PHP. |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Wed Dec 30, 2009 8:49 pm Post subject: |
|
|
The implementation of Code: | {uses file='library.tpl'} | would be very tricky.
{include...} is processed at render time. {uses...} would work only if it gets loaded in the same template which contains the call to the template function.
If {uses...} is included for example in a subtemplate it will fail because that subtemplate may get compiled at a different time. It' making things ver complicated.
There was another request to implement variable template function calls like {call name=$foo}. This implementation would work also for externally defined template functions as all the checks will be done at render time.
To avoid two diffrent calling syntaxes we could just drop {funname...} syntax and use always {call name=funname...}.
That would be similar the defun plugin in the wiki for Smarty2. |
|
Back to top |
|
douglassdavis Smarty Junkie
Joined: 21 Jan 2008 Posts: 541
|
Posted: Wed Dec 30, 2009 8:53 pm Post subject: |
|
|
U.Tews wrote: | The implementation of Code: | {uses file='library.tpl'} | would be very tricky.
{include...} is processed at render time. {uses...} would work only if it gets loaded in the same template which contains the call to the template function.
If {uses...} is included for example in a subtemplate it will fail because that subtemplate may get compiled at a different time. It' making things ver complicated.
There was another request to implement variable template function calls like {call name=$foo}. This implementation would work also for externally defined template functions as all the checks will be done at render time.
To avoid two diffrent calling syntaxes we could just drop {funname...} syntax and use always {call name=funname...}.
That would be similar the defun plugin in the wiki for Smarty2. |
thought about the compile time/render time difference after i posted (hence the deletion)... Anyway, the way you said it sounds good. |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Thu Dec 31, 2009 4:47 pm Post subject: |
|
|
External declared template functions are now working.
Like:
{* file1.tpl *}
{function name=test}
...some code...
{/function}
{* file2.tpl *}
{include name="file1.tpl"
{test}
So you can now create a library with template functions, include it and use the functions as usual.
The update is in the SVN now. |
|
Back to top |
|
douglassdavis Smarty Junkie
Joined: 21 Jan 2008 Posts: 541
|
Posted: Thu Dec 31, 2009 5:09 pm Post subject: |
|
|
U.Tews wrote: | External declared template functions are now working.
Like:
{* file1.tpl *}
{function name=test}
...some code...
{/function}
{* file2.tpl *}
{include name="file1.tpl"
{test}
So you can now create a library with template functions, include it and use the functions as usual.
The update is in the SVN now. |
I'm impressed.
I'm wondering if the compiler just looks at the name of functions in file1.tpl and turns those calls into dynamic calls, or if all calls are dynamic (or, i guess not checked at compile time) now? I would just like to know in advance the restrictions involved in using the current approach, and make sure they are documented.
I was just wondering about scenarios such as the following, and if they would result in compile or runtime errors or work fine:
A:
file1.tpl
Code: |
{if $x==1}
{function name=test}
...some code...
{/function}
{/if}
|
file2.tpl
Code: |
{$x=2}
{include file="file1.tpl"}
{test}
|
B:
file1.tpl
Code: |
{function name=test}
...some code...
{/function}
|
file2.tpl
Code: |
{$x=2}
{if $x==1}
{include file="file1.tpl"}
{/if}
{test}
|
C:
Code: |
{function name=test}
...some code...
{/function}
|
Code: |
{filename="file1.tpl"}
{include file=$filename}
{test}
|
|
|
Back to top |
|
|