SitePoint Sponsor

User Tag List

Results 1 to 15 of 15
  1. #1
    SitePoint Guru bronze trophy
    Join Date
    Dec 2003
    Location
    Poland
    Posts
    930
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)

    Question Is calling object methods from templates (smarty) ok?

    I will be redesigning code for a large website which uses Smarty and currently has 3 skins (3 separate sets of Smarty templates to display the same data). I will be keeping the templates as they are but write the application code from scratch since the current one is 7 year old and one big mess.

    In many cases data are passed to Smarty in arrays and templates access those arrays like this:
    Code:
    <h2>{$product.name}</h2>
    <p>{$product.short_description}</p>
    <p><a href="{$product.link}">more info</a></p>
    <p><a href="{$product.link}#accessories">Accessories ({$product.accessories_count})</a></p>
    This is just a simplified example. Now I will be using a sort of active record in the application layer so in such cases it would be convenient to use objects directly like this:
    Code:
    <h2>{$product->name}</h2>
    <p>{$product->short_description}</p>
    <p><a href="{$product->getPageLink()}">more info</a></p>
    <p><a href="{$product->getPageLink()}#accessories">Accessories ({$product->countAccessories()})</a></p>
    So you can see that to objects having primarily data from db I will add many convenience methods like getPageLink() or countAccessories(). For me accessing those methods from within the templates is very convenient when I code but is this good design? Is accessing methods right for a template? Template designers should generally be not bothered with underlying business logic and I am wondering if methods should be used within templates. I use methods all the time in administration panels and I see no problem with this but this time I would use them in templates that will probably be edited by other people as well - designers who are not interested in my application code underneath.

    What do you think? My question is what is your preference and how would you go about this? My current ideas are:

    1. Either recode the templates to use objects and methods and make it easier to maintain for me - the application coder
    2. Or leave the templates as they are and in the php code translate all necessary data from objects to arrays and pass only arrays to Smarty. This will not bother template designers at all but will add to the amount of code I will need to write.

    but I'm still not sure which way is the better way, or perhaps there is a third way?

  2. #2
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,151
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    So long as the methods handle display logic and don't impede on the controllers responsibilities.

    Quote Originally Posted by Lemon Juice
    Either recode the templates to use objects and methods and make it easier to maintain for me - the application coder
    This is the method in which the views in my current application are set up. Each view is a class which makes it very easy to encapsulate display functionality into separate methods. HTML template files don't exist.

  3. #3
    SitePoint Enthusiast
    Join Date
    Oct 2005
    Posts
    51
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Lemon Juice View Post
    For me accessing those methods from within the templates is very convenient when I code but is this good design? Is accessing methods right for a template? Template designers should generally be not bothered with underlying business logic and I am wondering if methods should be used within templates
    It is good that you are trying to separate concerns, you feel and probably have heard that templating is some form of best practice, but the how and why is somewhat vague to you. I know what it feels like.
    Templates are a means to separate "business logic" from the view. Business logic is something like update a record in the database, checking rights etc.
    There is one rule: the view may access data, but not change it!

    So: is accessing data from an object right? Yes, it is!
    There is a design pattern that is the defacto standard for good web application design: Model View Controller (MVC)

    The Model contains all data and rules about your domain (for instance: bicycles, customers, cats, processes).

    The View asks for data and displays it somehow. Nor the model nor the controller should dictate how information is presented. It is up to the View.

    The Controller should be thin: given an request (bicycles.com/product/345) it instantiates the appropriate view (template) and tells it to render.
    If an invalid request is made, the controller should do a redirect to an error page, log it or what else. The controller is a delegating object.
    On the internet many examples are shown of a controller class

    1. that gets a certain database identifier from a request
    2. pulls the data out of the database
    3. instantiate a template with only variables like you've shown
    4. and say: template->render();


    Well that's a nice controller, except the 3rd item. One should strive for thin controllers. The View should get the data it wants.

    In you controller you have:
    PHP Code:
    // file: ProductController.php
    $view = new TemplatingSystem();
    $view->productId $_GET['product-id']; 
    So in your template you ideally have

    PHP Code:
    <?php
    // file: products.tpl
    // $this is the template object. In smarty it is $smarty
    $bicycle Bicycles::getById($this->productId)
    echo 
    'model: '$bicycle->model;
    //etc
    ?>
    --

    I recommend reading http://blog.astrumfutura.com/archive...hitecture.html since it will teach you a lot about MVC.


    I've used smarty in the past, and it has been a very bad choice. You'd better of with Savant or Zend_View from Zend framework [Zend View is a modification of Savant].

    In conclusion:

    1. Writing your own MVC-framework is hard. I recommend picking an existing one.
    2. Smarty is a bad choice: working with real php objects is only easy in real php, not some cumbersome limiting syntax.
    3. Zend Framework supports Smarty too, if refactoring is a too big burden.

  4. #4
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,151
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    Quote Originally Posted by plaatspunt
    So: is accessing data from an object right? Yes, it is!
    PHP Code:
    class Foo {
      public 
    $name 'whatever';
    }

    $foo = new Foo();
    echo 
    $foo->name
    Accessing a property of a object isn't business logic. Business logic is merely communication between the domain and database.

  5. #5
    SitePoint Enthusiast
    Join Date
    Oct 2005
    Posts
    51
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Without a database you still can have business logic. I don't think this is a good definition. I think of b.l. as rules that are applied on your domain data.
    Accessing a property of an object is indeed not necessarily busines logic (it could trigger some b.l. rules however in theory).

    But that's completely not the point I wanted to make. My message is: separate your domain (data, rules, policies) from your view.

  6. #6
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,151
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    Quote Originally Posted by plaatspunt
    Accessing a property of an object is indeed not necessarily busines logic (it could trigger some b.l. rules however in theory).
    It could but generally it is the responsibility of the controller to initiate that transaction not the views.

  7. #7
    SitePoint Addict
    Join Date
    Nov 2005
    Location
    Germany
    Posts
    235
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by oddz View Post
    Business logic is merely communication between the domain and database.
    No. An application without persistence can have a lot of business logic.

    On topic: I too do access object properties from smarty templates but I usually prefer to pass - i.e. $template->assign() - dumb data objects, preferably arrays. Just make sure no part of the view changes the application's state.

  8. #8
    SitePoint Guru bronze trophy
    Join Date
    Dec 2003
    Location
    Poland
    Posts
    930
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    Thanks everyone for the answers, the general consensus seems to be that views and templates can access properties and methods but not change them.

    I don't want to discuss here whether Smarty is good or not, it serves its purpose well in this project and there's no need to rewrite everything at this point.

    Quote Originally Posted by FrlB View Post
    I too do access object properties from smarty templates but I usually prefer to pass - i.e. $template->assign() - dumb data objects, preferably arrays.
    What do you mean by dumb data objects?

  9. #9
    SitePoint Addict
    Join Date
    Nov 2005
    Location
    Germany
    Posts
    235
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Lemon Juice View Post
    What do you mean by dumb data objects?
    In Java I'd prefer using a passive interface (no setters, only getters) to make sure the template coder does not change state. In PHP I either pass simple data types like
    PHP Code:
    $template->assign('id'$user->getId());
    $template->assign('name'$user->getName()); 
    or if necessary an array (that's what I called dumb data object):
    PHP Code:
    $userArray = array('id' => $user->getId(), 'name' => $user->getName());
    $template->assign('user'$userArray); 
    Where a User class has the properties id and name.

    This is also useful because (I think) I recall in Smarty you can't do chaining:
    PHP Code:
    {$thing->getUser()->getName()} 
    Is this correct? It's been some time since I tried this.

  10. #10
    SitePoint Guru bronze trophy
    Join Date
    Dec 2003
    Location
    Poland
    Posts
    930
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by FrlB View Post
    In PHP I either pass simple data types like
    PHP Code:
    $template->assign('id'$user->getId());
    $template->assign('name'$user->getName()); 
    or if necessary an array (that's what I called dumb data object):
    PHP Code:
    $userArray = array('id' => $user->getId(), 'name' => $user->getName());
    $template->assign('user'$userArray); 
    Where a User class has the properties id and name.
    Well, that was my main question to start with and this is the option 2 from my initial post:
    2. Or leave the templates as they are and in the php code translate all necessary data from objects to arrays and pass only arrays to Smarty. This will not bother template designers at all but will add to the amount of code I will need to write.
    I'm wondering if it's better to use this kind of dumb data object or simply pass the object, which seems less work.

    This is also useful because (I think) I recall in Smarty you can't do chaining:
    PHP Code:
    {$thing->getUser()->getName()} 
    Is this correct? It's been some time since I tried this.
    Yes, it's correct. But I find those cases are rare when I need to use chaining, however it's a nice feature missing now in Smarty. I know there is a patch for Smarty if someone really wants it.

  11. #11
    SitePoint Addict
    Join Date
    Nov 2005
    Location
    Germany
    Posts
    235
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Lemon Juice View Post
    Yes, it's correct. But I find those cases are rare when I need to use chaining, however it's a nice feature missing now in Smarty. I know there is a patch for Smarty if someone really wants it.
    Chaining is considered evil anyway:
    http://en.wikipedia.org/wiki/Law_of_Demeter
    So I'd rather not patch this behaviour.

  12. #12
    SitePoint Enthusiast
    Join Date
    Oct 2005
    Posts
    51
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It is better to not let the controller pass the data to the view. Your controller should be thin; the view should query your domain for the data it wants to display. Why? Because if you need to reuse a template elsewhere, you find yourself duplicating code in different controllers.

    When you put aside this requirement you get the strange question whether you should turn the data into some other form just to please the template. Turning the data structures into other structures is unnecessary. So ideally you use the real objects.
    I can imagine that it can be a lot of work to rewrite all the templates, but writing procedures to turn format a into b will likely be the same amount of work.


    Yes, it's correct. But I find those cases are rare when I need to use chaining, however it's a nice feature missing now in Smarty. I know there is a patch for Smarty if someone really wants it.
    See how stupid smarty is. Before I used to think it helps me, but it does nothing more than php. It offers a strange syntax that is less expressive than php itself.
    I recommend reading http://nosmarty.net/articles/2008/08...-right-for-me/ for any future project.

  13. #13
    SitePoint Enthusiast
    Join Date
    Oct 2005
    Posts
    51
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by FrlB View Post
    Chaining is considered evil anyway:
    http://en.wikipedia.org/wiki/Law_of_Demeter
    So I'd rather not patch this behaviour.
    Hm, that's way too fast. Method chaining is ok, but it can sometimes be a bad smell. If software design could be done by such easy rules solely, than software engineering would be really simple. Unfortunately, this isn't the case.

    A disadvantage of the Law of Demeter is that it sometimes requires writing a large number of small “wrapper” methods (sometimes referred to as Demeter Transmogrifiers) to propagate method calls to the components. Furthermore, a class’s interface can become bulky as it hosts methods for contained classes resulting in a class without a cohesive interface.

  14. #14
    SitePoint Guru bronze trophy
    Join Date
    Dec 2003
    Location
    Poland
    Posts
    930
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by FrlB View Post
    Chaining is considered evil anyway:
    http://en.wikipedia.org/wiki/Law_of_Demeter
    So I'd rather not patch this behaviour.
    Interesting read, thanks. But it looks like a debatable law, doesn't it?

    Quote Originally Posted by plaatspunt View Post
    It is better to not let the controller pass the data to the view. Your controller should be thin; the view should query your domain for the data it wants to display. Why? Because if you need to reuse a template elsewhere, you find yourself duplicating code in different controllers.

    When you put aside this requirement you get the strange question whether you should turn the data into some other form just to please the template. Turning the data structures into other structures is unnecessary. So ideally you use the real objects.
    I can imagine that it can be a lot of work to rewrite all the templates, but writing procedures to turn format a into b will likely be the same amount of work.
    That is a valid point, thanks. I also was thinking about it. Translation seems unnecessary.

    See how stupid smarty is. Before I used to think it helps me, but it does nothing more than php. It offers a strange syntax that is less expressive than php itself.
    I recommend reading http://nosmarty.net/articles/2008/08...-right-for-me/ for any future project.
    I have worked with smarty and with php-based templates and smarty is quite convenient - in rare cases some features are missing compared to pure php but in frequent cases the simplicity of syntax is nice and can save a lot of typing. I've already read many debates for and against smarty so please don't start another one in this thread.

    Hm, that's way too fast. Method chaining is ok, but it can sometimes be a bad smell.
    This sounds like a good attitude - try to avoid chaining but don't be too strict about it.

  15. #15
    SitePoint Addict
    Join Date
    Nov 2005
    Location
    Germany
    Posts
    235
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes, I agree: The Law of Demeter is debatable, but it tells you to avoid chaining and why. I don't follow LoD strictly (I simply wouldn't want to), but as plaatspunt puts it: Chaining is a smell in most cases - it's just the law part of the name that is misleading - I guess LoD is more like a good advice.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •