Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I construct a new object from a Smarty template?

Tags:

php

smarty

What I want to do is this:

{myfunc myattribute=new MyClass('arg1', 'arg2')}

But it gives me an error when I try, saying that the function MyClass isn't defined.

The work-around I've been using is to create a top level function like this:

function MyClass($arg1, $arg2) { return new MyClass($arg1, $arg2); }

Then in the template doing:

{myfunc myattribute=MyClass('arg1', 'arg2')}

But is there anyway to avoid creating a new top level function for every class that I want contrastable from Smarty?

I guess I could also create a function that just takes the name of a class to let me construct any class, but that's kind of an ugly solution.

Edit: To everyone telling my violating best practices, perhaps this will make you feel better:

The object I'm constructing is a widget to render some html. The actual code looks like:

{render_widget widget=new MyWidget() id="myid" name="myname"}

Also, I'm unfortunately currently stuck on PHP 5.2, so I cannot use closures. I can use the latest version of Smarty3, though I'm currently using a version of Smarty 3.0.

like image 366
Tim Avatar asked Sep 03 '25 14:09

Tim


2 Answers

From http://www.smarty.net/best_practices

  1. Do not embed PHP
  2. Keep PHP constructs separate
  3. Keep business logic separate

In your case you mix presentation logic with business logic - and it is bad.

However, you can write your custom Smarty plugin (wrapper) for custom objects creation - and (I think) that it is more appropriate "Smarty-way" solution.

See http://www.smarty.net/docsv2/en/plugins.tpl and http://www.smarty.net/docsv2/en/plugins.functions.tpl

For example.

Definition:

function smarty_function_custom_class($params, &$smarty)
{
    $class = $params['class'];       
    $smarty->assign($params['var'], new $class());  
}    

Usage:

{custom_class var='myObject' class='MyClass'}

Update

So, if you have such construction:

{render_widget widget=new MyWidget() id="myid" name="myname"}

You can change your render_widget in this way:

function smarty_function_render_widget($params, &$smarty)
{
    $class = $params['widget'];       

    $id = $params['id'];
    $name = $params['name'];

    $widget = new $class($id, $name);

    /**
     *  if you need object in your template, assign it to same variable:
     */
    $smarty->assign($params['widget'], $widget);
    // rest of your code    
}    

And after that you can use it in this way:

{render_widget widget="MyWidget" id="myid" name="myname"}
like image 53
Vladimir Posvistelik Avatar answered Sep 05 '25 05:09

Vladimir Posvistelik


How about using closures?

{myfunc myattribute=function() { return new MyClass('arg1', 'arg2'); }}

It's not the prettiest thing ever, but it should get the job done. (As a side note, you may want to consider switching to the PHP Templating language sometime in the future)

like image 36
Mahn Avatar answered Sep 05 '25 05:09

Mahn