SmartyBundle: adding support for Symfony2 forms

255 views
Skip to first unread message

Vítor Brandão (noisebleed)

unread,
Feb 2, 2012, 9:21:16 AM2/2/12
to Smarty Developers
Hello all,

As announced on a previous message I've developed a Symfony2 bundle
called SmartyBundles that allows the usage of Smarty3 in the Symfony2
PHP framework. It's available here: https://github.com/noiselabs/SmartyBundle

Now, I'm adding form rendering support using Twig code (http://
twig.sensiolabs.org/) as an example and have a couple of questions.

1) What is the Smarty equivalent to the Twig function below?

From http://twig.sensiolabs.org/doc/functions/block.html:

When a template uses inheritance and if you want to print a block
multiple times, use the block function:
<title>{% block title %}{% endblock %}</title>
<h1>{{ block('title') }}</h1>
{% block body %}{% endblock %}

2) In template inheritance context is there something like $smarty-
>getBlocks() and $smarty->getParent()?

Thanks in advance,
Vítor Brandão.

uwe.tews

unread,
Feb 2, 2012, 10:20:11 AM2/2/12
to Smarty Developers
1. In the parent template you can reference the same child {block}
sevaral times, like:

<title>{block name='title'}{/block}</title>
<h1>{block name='title'}{/block}</h1>

2. Not sure what should be the function of the mentioned methods.

May be you are looking for something like the {$smarty.block.child}
and {$smarty.block.parent} placeholders?
See http://www.smarty.net/docs/en/advanced.features.template.inheritance.tpl

Regards Uwe

On Feb 2, 3:21 pm, Vítor Brandão (noisebleed)
<noisebl...@noiselabs.org> wrote:
> Hello all,
>
> As announced on a previous message I've developed a Symfony2 bundle
> called SmartyBundles that allows the usage of Smarty3 in the Symfony2
> PHP framework. It's available here:https://github.com/noiselabs/SmartyBundle
>
> Now, I'm adding form rendering support using Twig code (http://
> twig.sensiolabs.org/) as an example and have a couple of questions.
>
> 1) What is the Smarty equivalent to the Twig function below?
>
> Fromhttp://twig.sensiolabs.org/doc/functions/block.html:

Vítor Brandão

unread,
Feb 2, 2012, 10:47:38 AM2/2/12
to smarty-d...@googlegroups.com
2012/2/2 uwe.tews <uwe....@googlemail.com>

1. In the parent template you can reference the same child {block}
sevaral times, like:

 <title>{block name='title'}{/block}</title>
 <h1>{block name='title'}{/block}</h1>

Perfect. Thanks.
 
2. Not sure what should be the function of the mentioned methods.

May be you are looking for something like the {$smarty.block.child}
and {$smarty.block.parent} placeholders?
See http://www.smarty.net/docs/en/advanced.features.template.inheritance.tpl

OK, what I'm looking for is, in a modifier function (where I have access to the Smarty instance), to collect blocks from a given template and then do something like $template->displayBlocks();

The "given template" is tpl file filled with blocks used to theme the form.

If useful I can send a (GitHub) link to the class methods where this feature is implemented for Twig and PHP templates.
 
Regards Uwe

Thanks,
  Vítor. 

On Feb 2, 3:21 pm, Vítor Brandão (noisebleed)
<noisebl...@noiselabs.org> wrote:
> Hello all,
>
> As announced on a previous message I've developed a Symfony2 bundle
> called SmartyBundles that allows the usage of Smarty3 in the Symfony2
> PHP framework. It's available here:https://github.com/noiselabs/SmartyBundle
>
> Now, I'm adding form rendering support using Twig code (http://
> twig.sensiolabs.org/) as an example and have a couple of questions.
>
> 1) What is the Smarty equivalent to the Twig function below?
>
> Fromhttp://twig.sensiolabs.org/doc/functions/block.html:
>
>   When a template uses inheritance and if you want to print a block
> multiple times, use the block function:
>   <title>{% block title %}{% endblock %}</title>
>   <h1>{{ block('title') }}</h1>
>   {% block body %}{% endblock %}
>
> 2) In template inheritance context is there something like $smarty-
>
> >getBlocks() and $smarty->getParent()?
>
> Thanks in advance,
>   Vítor Brandão.

--
You received this message because you are subscribed to the Google Groups "Smarty Developers" group.
To post to this group, send email to smarty-d...@googlegroups.com.
To unsubscribe from this group, send email to smarty-develop...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/smarty-developers?hl=en.


uwe.tews

unread,
Feb 2, 2012, 11:01:42 AM2/2/12
to Smarty Developers
Hi Virtor

Please send the GitHub link that I can look into it.

Regards Uwe

On Feb 2, 4:47 pm, Vítor Brandão <noisebl...@noiselabs.org> wrote:
> 2012/2/2 uwe.tews <uwe.t...@googlemail.com>

Vítor Brandão

unread,
Feb 2, 2012, 11:12:32 AM2/2/12
to smarty-d...@googlegroups.com
2012/2/2 uwe.tews <uwe....@googlemail.com>

Hi Virtor

Please send the GitHub link that I can look into it.



Better is to focus on Twig and just go for the PHP implementation if needed.

SmartyBundle (to track implementation, work in progress): https://github.com/noisebleed/SmartyBundle/blob/master/Extension/FormExtension.php#L262

Just to give some context, in SmartyBundle an Extension, like FormExtension, is a class that holds a collection of Smarty plugins. These plugins are returned by getPlugins() and registered before the template rendering. The registration is done in the class SmartyEngine.

Vítor Brandão

unread,
Feb 2, 2012, 11:22:16 AM2/2/12
to smarty-d...@googlegroups.com
2012/2/2 Vítor Brandão <noise...@noiselabs.org>

2012/2/2 uwe.tews <uwe....@googlemail.com>

Hi Virtor

Please send the GitHub link that I can look into it.

Also, if you need some quick Q&A I'm on #smarty IRC right now.

uwe.tews

unread,
Feb 2, 2012, 11:54:38 AM2/2/12
to Smarty Developers
There is no quick answer, I need to have a closer look when I have
some more time.

There might be problems as the handling of template inheritance is
completely different in Smarty and in Twig.

In Smarty this is a compile time process, in Twig everything is
resolved at render time.
So we might not have the needed datastructures available for your
FormExtension....

Uwe

On Feb 2, 5:22 pm, Vítor Brandão <noisebl...@noiselabs.org> wrote:
> 2012/2/2 Vítor Brandão <noisebl...@noiselabs.org>
>
> > 2012/2/2 uwe.tews <uwe.t...@googlemail.com>
>
> > Hi Virtor
>
> >> Please send the GitHub link that I can look into it.
>
> Also, if you need some quick Q&A I'm on #smarty IRC right now.
>
>
>
>
>
>
>
>
>
> >> Twig:
> >https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Twi...
>
> > PHP:
> >https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/Fra...
>
> > Better is to focus on Twig and just go for the PHP implementation if
> > needed.
>
> > SmartyBundle (to track implementation, work in progress):
> >https://github.com/noisebleed/SmartyBundle/blob/master/Extension/Form...

Vítor Brandão

unread,
Feb 2, 2012, 1:16:13 PM2/2/12
to smarty-d...@googlegroups.com
2012/2/2 uwe.tews <uwe....@googlemail.com>

There is no quick answer, I need to have a closer look when I have
some more time.

There might be problems as the handling of template inheritance is
completely different in Smarty and in Twig.

In Smarty this is a compile time process, in Twig everything is
resolved at render time.
So we might not have the needed datastructures available for your
FormExtension....

Instead of trying to mimic the Twig behavior I will gather information about how Symfony handles form customization and rendering and post some info here. Then we may discuss the best way to implement this in the Smarty world.

Vítor Brandão

unread,
Feb 3, 2012, 6:23:39 AM2/3/12
to smarty-d...@googlegroups.com
2012/2/2 Vítor Brandão <noise...@noiselabs.org>

2012/2/2 uwe.tews <uwe....@googlemail.com>

There is no quick answer, I need to have a closer look when I have
some more time.

There might be problems as the handling of template inheritance is
completely different in Smarty and in Twig.

In Smarty this is a compile time process, in Twig everything is
resolved at render time.
So we might not have the needed datastructures available for your
FormExtension....

Instead of trying to mimic the Twig behavior I will gather information about how Symfony handles form customization and rendering and post some info here. Then we may discuss the best way to implement this in the Smarty world.

Good morning. As promised I'll try to explain the basic stuff about form rendering implemented in Symfony. Here it goes:

Note: if in a hurry go straight to section 3 :)

1. Rendering the Form

1.1 In a Twig template form is rendered as follows:

<form action="submit.php" method="post" {{ form_enctype(form) }}>
    {{ form_widget(form) }}
    <input type="submit" />
</form>

1.2 Equivalent for Smarty 

<form action="submit.php" method="post" {$form|form_enctype}>
    {$form|form_widget}
    <input type="submit" />
</form>

2. How to customize Form Rendering

2.1 Form Themes

"Symfony uses form fragments - a small piece of a template that renders just one part of a form - to render every part of a form - - field labels, errors, input text fields, select tags, etc. The fragments are defined as blocks in Twig and as template files in PHP." Smarty also uses blocks as Twig does.



The idea behind this is to have several blocks that are responsible for rendering a specific element like a text input or a checkbox and have "bigger" blocks that include other more specific blocks.

So, a {block "form_widget"} includes a {block "field_rows"}. Inside {block "field_rows"} a foreach is executed to include {block "field_row"}. 

A "field_row" block looks like this:

{block "field_row"}
<div>
{$form|form_label}
{$form|form_errors}
{$form|form_widget}
</div>
{/block}

and "field_label" is (edited for simplicity):

{block "field_label"}
    <label>{$label}</label>
{/block}

The user is then able to extend the form_div_layout.htm.tpl file and override/customize each block.

3. Implementation

3.1 Twig way

In Twig the form rendering function follows this logic:
  1. The function first looks for a block named "_<view id>_<section>".
  2. if such a block is not found the function will look for a block named "<type name>_<section>".
  3. the type name is recursively replaced by the parent type name until a corresponding block is found.
     
Before the rendering Twig calls a $template->getBlocks() method to gather all blocks in the template. Then a $template->displayBlock() is executed with variables pulled from the $form instance. I guess this is how it populates each block variables.

3.2 Smarty way

I see that Smarty has a getTags() method but it just return tags names not a data structure. So I guess bottom the problem/challenge here is to gather all blocks (to the parent) and set variables inside them. Is this feasible? What would you suggest?

4. Documentation resources

- Symfony2: How to customize Form Rendering - http://symfony.com/doc/current/cookbook/form/form_customization.html
- Symfony2: Twig Template Form Function Reference - http://symfony.com/doc/current/reference/forms/twig_reference.html

Sorry for the really long email.

Regards,
  Vítor.

uwe.tews

unread,
Feb 3, 2012, 4:43:30 PM2/3/12
to Smarty Developers
After having a closer look into it I think the Forms Extention does
have nothing to do with traditional template inheritance.
The Symfony extentions makes use of Twigs internal implementation
blocks so that block can be called dynamicly.

This is not possible with Smarty's implementation of the {block} tags.
But in Smarty we have template functions implemented by the {function}
tag for doing same thing.

I think you can write the Smarty version of form_div_layout.tpl by
using template functions.

See http://www.smarty.net/docs/en/language.function.function.tpl and
http://www.smarty.net/docs/en/language.function.call.tpl

Uwe

On Feb 3, 12:23 pm, Vítor Brandão <noisebl...@noiselabs.org> wrote:
> 2012/2/2 Vítor Brandão <noisebl...@noiselabs.org>
>
>
>
>
>
>
>
>
>
> > 2012/2/2 uwe.tews <uwe.t...@googlemail.com>
>
> Twig provides all blocks inside a single file:https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Twi...
>
> SmartyBundles does the same:https://github.com/noisebleed/SmartyBundle/blob/master/Resources/view...
> - Symfony2: Forms -http://symfony.com/doc/current/book/forms.html
> - Symfony2: How to customize Form Rendering -http://symfony.com/doc/current/cookbook/form/form_customization.html
> - Symfony2: Twig Template Form Function Reference -http://symfony.com/doc/current/reference/forms/twig_reference.html

Vítor Brandão (noisebleed)

unread,
Feb 4, 2012, 12:54:47 PM2/4/12
to Smarty Developers


On 3 Fev, 21:43, "uwe.tews" <uwe.t...@googlemail.com> wrote:
> After having a closer look into it I think the Forms Extention does
> have nothing to do with traditional template inheritance.
> The Symfony extentions makes use of Twigs internal implementation
> blocks so that block can be called dynamicly.
>
> This is not possible with Smarty's implementation of the {block} tags.
> But in Smarty we have template functions implemented by the {function}
> tag for doing same thing.
>
> I think you can write the Smarty version of form_div_layout.tpl by
> using template functions.
>
> Seehttp://www.smarty.net/docs/en/language.function.function.tplandhttp://www.smarty.net/docs/en/language.function.call.tpl
>
Hi Uwe. Thanks for taking time to look at this. I've chatted with
Rodney Rehm in the #smarty channel and he also pointed me into
functions.

There is one (at least :) problem though. Symfony implementation uses
recursion to find the proper block/function. So, if my form is called
"user_settings_language", Symfony would look for (from more specific
to more general):
1. {function name="user_settings.language_form_enctype"}
2. {function name="user_settings_language_enctype"}
3. {function name="form_enctype"}
4. {function name="field_enctype"}

and load the first one available.

Using $template->getTags() I can look for function elements and pick
the first in the above list. But, is it possible to call this function
inside the plugin function method?
> ...
>
> mais informações »

uwe.tews

unread,
Feb 4, 2012, 1:16:51 PM2/4/12
to Smarty Developers
getTags() is currently experimental and will recompile template when
it's called to obtain the information from the parser. So this is not
an option.
But there is the $smarty->template_functions property which is an
array of template function information. The key of this array is the
function name.

Perhaps you can write a plugin to find the function name and call the
corresponding template function afterwards.

Regards Uwe

On Feb 4, 6:54 pm, Vítor Brandão (noisebleed)
<noisebl...@noiselabs.org> wrote:
> On 3 Fev, 21:43, "uwe.tews" <uwe.t...@googlemail.com> wrote:> After having a closer look into it I think the Forms Extention does
> > have nothing to do with traditional template inheritance.
> > The Symfony extentions makes use of Twigs internal implementation
> > blocks so that block can be called dynamicly.
>
> > This is not possible with Smarty's implementation of the {block} tags.
> > But in Smarty we have template functions implemented by the {function}
> > tag for doing same thing.
>
> > I think you can write the Smarty version of form_div_layout.tpl by
> > using template functions.
>
> > Seehttp://www.smarty.net/docs/en/language.function.function.tplandhttp:/...
> ...
>
> read more »

Vítor Brandão (noisebleed)

unread,
Feb 4, 2012, 1:54:56 PM2/4/12
to Smarty Developers
On 4 Fev, 18:16, "uwe.tews" <uwe.t...@googlemail.com> wrote:
> getTags() is currently experimental and will recompile template when
> it's called to obtain the information from the parser. So this is not
> an option.
> But there is the $smarty->template_functions property which is an
> array of template function information. The key of this array is the
> function name.
>
I'm storing all functions in form_div_layout.tpl and loading that
template inside the plugin by doing $template = $smarty-
>createTemplate(/path/to/form_div_layout.tpl');

If I do $template->template_functions the array of functions returned
holds the functions stored in the current template where the plugin
was triggered and not form_div_layout.tpl.

I must be doing something wrong or missing a step. Can you tell me the
right direction?

> Perhaps you can write a plugin to find the function name and call the
> corresponding template function afterwards.

Where do I call the template function? Inside the plugin code where I
do have access to the template object? Or with a prefilter or
something like that?
> ...
>
> mais informações »

Vítor Brandão (noisebleed)

unread,
Feb 6, 2012, 9:05:49 AM2/6/12
to Smarty Developers
On 4 Fev, 18:54, Vítor Brandão (noisebleed) <noisebl...@noiselabs.org>
wrote:
> On 4 Fev, 18:16, "uwe.tews" <uwe.t...@googlemail.com> wrote:> getTags() is currently experimental and will recompile template when
> > it's called to obtain the information from the parser. So this is not
> > an option.
> > But there is the $smarty->template_functions property which is an
> > array of template function information. The key of this array is the
> > function name.
>
> I'm storing all functions in form_div_layout.tpl and loading that
> template inside the plugin by doing $template = $smarty-
>
> >createTemplate(/path/to/form_div_layout.tpl');
>
> If I do $template->template_functions the array of functions returned
> holds the functions stored in the current template where the plugin
> was triggered and not form_div_layout.tpl.
>
> I must be doing something wrong or missing a step. Can you tell me the
> right direction?
>
> > Perhaps you can write a plugin to find the function name and call the
> > corresponding template function afterwards.
>
> Where do I call the template function? Inside the plugin code where I
> do have access to the template object? Or with a prefilter or
> something like that?
>

For those following this thread, Uwe answered this question in
StackOverflow:
http://stackoverflow.com/questions/9152047/in-smarty3-call-a-template-function-defined-by-the-function-tag-from-within-a
> > > > > >> > >> > do something like $template->displayBlocks();...
>
> mais informações »
Reply all
Reply to author
Forward
0 new messages