smarty template variable not clear - php

I am trying to understand developing web apps with PHP and smarty this is the book
there is a file departments_list.tpl
{* departments_list.tpl *}
{load_presentation_object filename="departments_list" assign="obj"}
{* Start departments list *}
<div class="box">
<p class="box-title">Choose a Department</p>
<ul>
{* Loop through the list of departments *}
{section name=i loop=$obj->mDepartments}
{assign var=selected value=""}
{* Verify if the department is selected to decide what CSS style to use *}
{if ($obj->mSelectedDepartment == $obj->mDepartments[i].department_id)}
{assign var=selected value="class=\"selected\""}
{/if}
<li>
{* Generate a link for a new department in the list *}
<a {$selected} href="{$obj->mDepartments[i].link_to_department}">
{$obj->mDepartments[i].name}
</a>
</li>
{/section}
</ul>
</div>
{* End departments list *}
I do not understand in above file one line which is
{section name=i loop=$obj->mDepartments}
how does name=i works I what is i initialized to and how can a loop start from i,
secondly above file is using a file function.load_presentation_object.php
<?php
// Plug-in functions inside plug-in files must be named: smarty_type_name
function smarty_function_load_presentation_object($params, $smarty)
{
require_once PRESENTATION_DIR . $params['filename'] . '.php';
$className = str_replace(' ', '',ucfirst(str_replace('_', ' ',$params['filename'])));
// Create presentation object
$obj = new $className();
if (method_exists($obj, 'init'))
{
$obj->init();
}
// Assign template variable
$smarty->assign($params['assign'], $obj);
}
?>
in above file a parameter $params has been used in last line
$smarty->assign($params['assign'], $obj);
as far as I can understand from file departments_list.tpl passes on parameter to function.load_presentation_object.php
as
{load_presentation_object filename="departments_list" assign="obj"}
so when following is called
function smarty_function_load_presentation_object($params, $smarty)
$params=depratments_list and $smarty=obj
so how does
$smarty->assign($params['assign'], $obj);
work what is $params['assign'] in above?

{load_presentation_object filename="departments_list" assign="obj"}
translated to php will be:
smarty_function_load_presentation_object(
array(
'filename' => 'departments_list',
'assign' => 'obj'
),
$smarty
);
Every parameters specified in smarty template are passed as associative array in first argument. Second is always current smarty object.
As for
{section name=i loop=$obj->mDepartments}
it is simple for loop:
for ($i=0; $i < count($obj->mDepartments); $i++) {
$current = $obj->mDepartments[$i];
}

Related

Assigning function return value DIRECTLY in template - Smarty 2

I have global function defined in php:
function tabIsProtected($tabNr)
{
...
return true;
}
Now this works in Smarty:
{if tabIsProtected($tabnr)}
{assign var="tabProtected" value=true}
{else}
{assign var="tabProtected" value=false}
{/if}
And this is not:
{assign var="tabProtected" value=tabIsProtected($tabnr)}
When I print $tabProtected variable I get string "tabIsProtected(9)" (for $tabnr = 9) and function tabIsProtected isn't even called!
Is there any way to assign function return value directly in template using Smarty 2?
IMPORTANT: I don't want $smarty->assign(...) in php or Smarty3 solutions. Just one liner directly in template.

Codeigniter categories and sub categories function and pass to smarty variable

This is my codeigniter code for categories and sub categories when i echo the results outside the first foreach or pass results to smarty it only outputs last rows with last main id.
But echo within the first foreach before closing } returns all results.
function getAllCats(){
$this->load->model('mHtml', 'mnMod');
$main_cat = $this->mnMod->getncats();
$all_cat = '';
foreach($main_cat as $mcat){
$all_cat = '<li><h3>'.$mcat->cname.'</h3>';
$sub_cat = $this->mnMod->getscats($mcat->categoryid);
foreach($sub_cat as $scat){
$all_cat .= ''.$scat->cname.'<br />';
}
$all_cat .= '</li>';
}
// echo $all_cat; die;
$this->smarty->assign("nav", $all_cat);
}
Results returned with mymethod.
Power Inverters
Off Grid Pure Sine Wave
Grid Tie String
Micro Grid Tie
Results i want to achieve and pass to smarty variable
Solar Panels
Monocrystalline
Polycrystalline
Flexible Solar
Charge Controllers
PWM
MPPT Technology
Power Inverters
Off Grid Pure Sine Wave
Grid Tie String
Micro Grid Tie
I have the same issue what i did i get all parent categories by one mysql query and in another i select all categories, simply i assign variables to smarty and foreach those results against each parent category.
$main_Categories = $this->model->all_categories();
$this->smarty->assign("main_Categories ", $main_Categories );
//On Smarty page
{foreach $main_Categories $cat}
{if $cat->parentid = 'your parent id'} // parent id will be same for all main ids.
{$cat->category_name}<br />
{assign 'cat_id' $cat->cat_id}
{foreach $main_Categories as $sub}
{if $cat_id eq $sub->parent_id}
{$sub->category_name}<br />
{/if}
{/foreach}
{/if}
{/foreach}
Loop through your $main_cats and assign sub_categories for each one. Good practice is to ensure $main_cats is an array before doing this.
Controller:
function getAllCats() {
$this->load->model('mHtml', 'mnMod');
$main_cats = $this->mnMod->getncats();
if(is_array($main_cats))
foreach($main_cats as &$mcat) {
$mcat['subcat'] = $this->mnMod->getscats($mcat->categoryid);
}
$this->smarty->assign("cats", $main_cats);
}
View:
{if $cats}
{foreach from=$cats item=cat}
<li><h3>{$cat.cname}</h3>
{foreach from=$cat item=sub_cat}
{$sub_cat.cname}<br />
{/foreach}
</li>
{/foreach}
{else}
<p>No cats found</p>
{/if}

Smarty assign and display two dimensional array

I want to get a two dimensional array's data and display it in a html file using smarty:
The idea is as following: my array contains several arrays everyone contains the category name in the first offset and the attached links to this category
1-file php
$categories_links = array();//array that contains some catgories name with the attached links
//some dummy data
$categorie1="Horror movies";
$link11="http://www.movie11.com";
$link12="http://www.movie12.com";
$link13="http://www.movie13.com";
$categories_links[] = array($categorie1, $link11, $link12,$link13);
$categorie2="Action movies";
$link21="http://www.movie21.com";
$link22="http://www.movie22.com";
$categories_links[] = array($categorie2, $link21, $link22);
$smarty->assign('categories_links' , $categories_links );
$smarty->display('file.html');
2-file html
{foreach key=categorie item=categorie from=$categories_links}
foreach key=categorie item=categorie from=categorie}
<!--
1.display only the first item in every array as the category name
2.display the rest as the links attached to the above category
//-->
{/foreach}
{/foreach}
Assuming you use Smarty 3 (you haven't mentioned anything about Smarty 2) you can use the following code:
{foreach $categories_links as $categorie}
<p>
{foreach $categorie as $item}
{if $item#first}
<strong>Category name: {$item}</strong><br />
{else}
{$item}
{/if}
{/foreach}
</p>
{/foreach}
Output for this will be:
Category name: Horror movies
http://www.movie11.com http://www.movie12.com http://www.movie13.com
Category name: Action movies
http://www.movie21.com http://www.movie22.com
EDIT
As you mentioned in comment you want solution for Smarty 2 you need to use in you Smarty template file:
{foreach key=id item=categorie from=$categories_links}
<p>
{foreach item=item from=$categorie name=list}
{if $smarty.foreach.list.first}
<strong>Category name: {$item}</strong><br />
{else}
{$item}
{/if}
{/foreach}
</p>
{/foreach}
This will give you output:
Category name: Horror movies
http://www.movie11.com http://www.movie12.com http://www.movie13.com
Category name: Action movies
http://www.movie21.com http://www.movie22.com
(exactly the same as the one in Smarty 3)
I'd refactor the data array to use the category name as a key.
$categories = array(
'Horror movies' => array(
'link1',
'link2',
/...
),
'Action movies' => array(
'link1',
'link2',
/...
),
);
$smarty->assign("categories", $categories);
Then you can use it easily in Smarty
{foreach from=$categories key=category item=links}
Category: {$category}
{foreach from=$links item=link}
{$link}
{/foreach}
{/foreach}
It is much easier to use that way.

how to foreach an array variable created with recursive function in Smarty

I have an array which I created in php with a recursive function, I do not know how many dimensions, how can I use in Smarty ?
I trying use this code :
{foreach $myArr as $items}
<li>
{$items.title}
{if $item.submenu}
<ul>
{foreach $items.submenu as $items2}
<li>{$items2.title}</li>
{/foreach}
</ul>
{/if}
</li>
{/foreach}
But this code is for just 2 levels, may be my array have 3 or 4 or ... levels.
UPDATE:
I found the solution, in my solution I use Smarty functions :
{function name=menu level=0}
<ul>
{foreach $data as $items}
<li>
<a href="{$items.url}">
{$items.title}
</a>
{if is_array($items.submenu)}
{menu data=$items.submenu level=$level+1}
{/if}
</li>
{/foreach}
</ul>
{/function}
{menu data=$menuItems}
I would go a different approach.
My suggestion:
Instead of creating arrays with menus. Create two or one class/es.
First class is a Menu class which holds the items in a key/value manner.
Second class would be a menu item.
That way you could all necessary iterations/logic do through a function call in the model
and the printing in the view.
something like:
class Menu {
protected $_items = array();
protected $_parent_child = array();
public function add_menu_item($name, $id, $parent_id) {
if (array_key_exists($id, $this->_items))
return;
$this->_items[$i] = array('name' => $name, 'id' => $id, 'parent' => $parent_id) // model with data
$this->_parent_child[$parent_id] = $this->_items[$id];
}
public function get_nodes_by_parent($id=null /*for root*/) {
if (array_key_exists($id, $this->_parent_child))
return $this->_parent_child[$id];
return array(); // or null or something
}
}
Menu template:
{foreach($menuClass->get_nodes_by_parent() as $item ) {
<ul>
<li>{$item['name']}</li>
{include 'sub_cats' id=$item['id'], menuclass=$menuclass}
</ul>
{endforeach}
Sub category template:
{foreach($menuClass->get_nodes_by_parent($id) as $item ) {
<ul>
<li>{$item['name']}</li>
{include 'sub_cats' id=$item['id']}
</ul>
{endforeach}
This is not fully complete nor tested. But that would be my approach.

Smarty: Outputting Rows Based on # of Items in Array

I am using Smarty to output an array to an HTML table. I want each row of the table to have no more than 8 items in it. If the array has more than 8 items then the code would make a new row for the overflowing items.
How can I do this? Is this clear?
It's been a long time since I've used Smarty, but you should be able to do this like this:
<tr>
{foreach from=$items key=myId item=i name=foo}
{if $smarty.foreach.foo.index % 8 == 0 && $smarty.foreach.foo.index > 0 }
</tr><tr>
{/if}
<td>{$i.label}</td>
{/foreach}
</tr>
The modulus operator only returns 0 if the index is dividable by 8, So before every 9th item it adds a new row. We don't want this for the first item to happend so let's check that as well.
Here's how I did it in the past:
<table>
{foreach from=$array item='array_item' name='array_items'}
{if $smarty.foreach.array_items.first}
{* first item - start of all the rows *}
<tr><td>{$array_item}</td>
{elseif $smarty.foreach.array_items.index % 8 == 0}
{* 8 items added to row - start new row *}
</tr><tr><td>{$array_item}</td>
{elseif $smarty.foreach.array_items.last}
{* last item - end the row (or add logic to fill out row with empty cells if needed) *}
<td>{$array_item}</td></tr>
{else}
{* normal item - add cell *}
<td>{$array_item}</td>
{/if}
{/foreach}
</table>

Categories