views:

741

answers:

1

Given a Category (parent) and Product (child) tables in a database, say, I want to create Smarty Block Plugins that would enable template snippets similar to this:

{products category="Some Category"}
    <h1>{products_name}</h2>
    <p>{products_description}</p>
{/products}

I believe plugins like these would help avoid repeated chunks of code that read a database and do a smarty-assign on the result in my controller.

I know how to write this as a smarty function. But I am looking for a block version to give the template designer the flexibility to style the individual columns in whatever way he wants. I am a long-time Perl programmer and new to Smarty. Perl users will recognise something like this in the Movable Type Templating System for example, and I wonder if a smarty version is possible.

Is something like this possible in Smarty at all? Is it a good thing to make a DB call from inside a smarty plugin?

+1  A: 

My suggestion is use configuration array ($conf) with the SQL query template to use inside the plugin for simple modification. Of course is not a good thing make a DB call inside the Smarty plugin. Instead, you can load the results in the $conf array making the DB call in the PHP script and unload in the plugin, as you wish.

This is the Smarty plugin:

<?php
function smarty_block_products($params, $content, &$smarty, &$repeat)
{
    global $conf;

    $category = $params['category'];
    $md5 = md5($category);
    if (empty($content))
    {
        if (empty($category))
        {
            $smarty->trigger_error("products: missing 'category' parameter"); 
        }
        $sql = str_replace('{$category}', $category, $conf['get-products-sql-template']);
        $query = mysql_query($sql);

        $result = array();
        while ($row = mysql_fetch_assoc($query))
        {
            $result[] = $row;
        }
        if (count($result) == 0)
        {
            $result = false;
        }
        $GLOBALS['__SMARTY_PRODUCTS'][$md5] = $result;
    }
    if (is_array($GLOBALS['__SMARTY_PRODUCTS'][$md5]))
    {
        $field = "product";
        if (isset($params['item']))
        {
            $field = $params['item'];
        }

        $product = array_shift($GLOBALS['__SMARTY_PRODUCTS'][$md5]);            

        $smarty->assign($field, $product);

        if (count($GLOBALS['__SMARTY_PRODUCTS'][$md5]) == 0)
        {
            $GLOBALS['__SMARTY_PRODUCTS'][$md5] = false;
        }
        $repeat = true;
    } else {
        $repeat = false;
    }
    echo $content;
}
?>

the Smarty template:

{products category="Some Category" item=product}
    <h1>{$product.name}</h2>
    <p>{$product.description}</p>
{/products}

and the PHP:

<?php
require 'Smarty/Smarty.class.php';

$smarty = new Smarty;

$conf['get-products-sql-template'] = 'SELECT product.* FROM product INNER JOIN category ON category.id = product.category_id WHERE category.title = \'{$category}\'';

$smarty->display('test.tpl');
?>
inakiabt