what is the best code for sidebar partial for multilevel?
Is it just do in Controller like :
public function tambahNota()
{
$head['title'] = 'Tambah Nota';
if($this->session->userdata('userLevel') == 1){
$this->load->view('partials/sidebarAdmin');
} elseif($this->session->userdata('userLevel') == 2){
$this->load->view('partials/sidebarUser');
}
$this->load->view('partials/footer');
$this->load->view('nota/tambahNota');
.. or in View partials/sidebar?
<?php if ($this->session->userdata('userLevel') == 1) {?>
..script of admin sidebar..
<?php } else if($this->session->userdata('userLevel') == 2) {?>
..script of user sidebar..
<?php } ?>
Thank you.
Hi #Goldplate it is good to keep it at the view. Although both ways works, keeping it in the view makes it easy to change filenames when you need to.
You can create a helper function to keep things simple, for example:
Create a helper with the name template_helper.php in the helpers directory.
Add the code below.
<?php
defined('BASEPATH') or exit('No direct script access allowed');
function load_partial($view_path, $view_data = null)
{
$ci =& get_instance(); //get_instance is an instance of codeigniter object
if (strstr($view_path, '.')) {
$view_path = str_replace('.', '/', $view_path);
}
$ci->load->view($view_path, $view_data);
}
And you can use it like this:
<?php if ($this->session->userdata('userLevel') == 1) {?>
load_partial('sidebars.level_one');
<?php } else if($this->session->userdata('userLevel') == 2) {?>
load_partial('sidebars.level_two');
<?php } ?>
So here "sidebars" is a directory that contains files level_one.php and level_two.php
If you see a dot in 'sidebars.level_one' it is just replacing a forward slash '/' and for easy access.
This is just to give you an idea. Let me know if it helps.
Both the process is good. It up to you to choose yours.
As it is templating, I like to keep it the view. so, later on, I can easily find the file for edit.
Related
I have 3 different navigation bars, a different 1 has to be loaded depending on the authority of the user. I have made a function in a different php file so i re use the code in each page. My problem is that after logging in , no navigation bar is being loaded. any suggestions to what might be the problem ?
Code in function.php file
function checkAuth()
{
session_start();
if(empty($_SESSION['role']))
{
require_once('menu.php');
}
else if ($_SESSION['role'] == "registered"){
include('regnav.php');
}
else if ($_SESSION['role'] =="admin"){
include('adminnav.php');
}
}
code in the begging of each page
<?php
require_once("function.php");
checkAuth();
?>
Try passing the session result into the function:
place session call at the top of the rendering page
session_start();
$this_session = $_SESSION['role'];
require_once("function.php");
place where you want to render menu
checkAuth($this_session);
the function
function checkAuth($this_session)
{
if($this_session == ''){include('menu.php');}
elseif($this_session == 'registered'){include('regnav.php');}
elseif($this_session == 'admin'){include('adminnav.php');}
}
I would personally restructure your pages just a little, like this:
At the top of each page put:
session_start();
include('function.php');
checkAuth();
Change the function to:
function checkAuth()
{
if (!isset($_SESSION['role'])) { require_once('menu.php'); }
if ($_SESSION['role'] == 'registered') { include('regnav.php'); }
if ($_SESSION['role'] == 'admin') { include('adminnav.php'); }
}
This assumes you aren't using functions in your navbar files, since you don't call any functions to write the navbar. You could, of course, put both navbars into functions and put both functions into a single navbar.php file that you would include at the top of every page (or put the functions into function.php), then call the appropriate navbar function from the checkAuth() function, like this:
if ($_SESSION['role'] == 'registered') { navbar_registered(); }
if ($_SESSION['role'] == 'admin') { navbar_admin(); }
I have created my own little PHP framework for fun, however, I am having trouble passing variables from bootstrap to the views....
if I put an echo,print_r,var_dump my target variable in the bootstrap, the output is displayed in the browser before the tag... yet the target var in bootstrap.php is not available in the view, it is coming up as "" even though at the top of the page it is being output correctly....
Somethings I noticed from similar questions:
- The target variable is not being over written
- The include target path is correct and the file exists
- The file is only being included one time (include_once is only fired once)
Any ideas are greatly appreciated, I am pulling my hair out over here lol...
Source Code
https://gist.github.com/jeffreyroberts/f330ad4a164adda221aa
If you just want to display your site name, I think you can use a constant like that :
define('SITE_NAME', "Jeff's Site");
And then display it in your index.tpl :
<?php echo SITE_NAME; ?>
Or, you can send your variables to the view by extending a little bit your JLR_Core_Views :
class JLR_Core_Views
{
private $data;
public function loadView($templatePath, $data = array())
{
$this->data = $data;
$templatePath = JLR_ROOT . '/webroot/' . $templateName . '.tpl';
if(file_exists($templatePath)) {
// Yes, I know about the vuln here, this is just an example;
ob_start();
include_once $templatePath;
return ob_get_clean();
}
}
function __get($name)
{
return (isset($this->data[$name]))
? $this->data[$name]
: null;
}
}
Then, you can call your template like that :
$view = new JLR_Core_Views();
$view->loadView("index", array("sitename" => "Jeff's Site"));
And here is your index.tpl :
<?php echo $this->siteName; ?>
Below is another example of what you can do.
First, you create this class in order to store all the variables you want :
<?php
class JLR_Repository {
private static $data = array();
public function set($name, $value) {
self::$data[$name] = $value;
}
public function get($name) {
return (isset(self::$data[$name]))
? self::$data[$name]
: null;
}
}
?>
Then, when you want to store something in it :
JLR_Repository::set("sitename", "Jeff's Site");
And in your index.tpl :
<?php echo JLR_Repository::get("sitename"); ?>
try using the 'global' keyword - http://php.net/manual/en/language.variables.scope.php
I'm totally new to smarty... and it's creeping me out :)
I got the following class in /inc/class/search.php:
Class search
{
function __construct($request) {
global $dbconn;
$request = htmlspecialchars($request);
$sql = "SELECT * FROM table WHERE id LIKE '%{$request}%'";
$res = $dbconn->Query($sql);
$entity = $res->fetchArray();
return $entity;
}
}
I have this in php_head.php:
if (isset($_REQUEST['search']) && !empty($_REQUEST['search'])) {
$is = new search($_REQUEST['search']);
$smarty->assign("searchValues", $is);
}
This code in php_head is designed to be called by ajax later on. But when I run index.php?search=string I get the whole smarty template. Please help.
What you need to do is displaying only some part of output when search is in URL.
So you could modify your code this way:
if (isset($_REQUEST['search']) && !empty($_REQUEST['search'])) {
$is = new search($_REQUEST['search']);
$smarty->assign("searchValues", $is);
$smarty->display('searchvalues.tpl'); // custom base template
exit; // stop execution of later code
}
And you should create searchvalues.tpl template and display here only this part that you want to display and not the whole base template.
You need to clear template that you need for ajax, and if you want to include it in some other template
{include file="path_to_template.tpl"}
And when you need only the result from this template use
echo $smarty->fetch('path_to_template.tpl');
For example you have :
$smarty->display('index.tpl');// this will return index.tpl
And in index.tpl :
<div id="result_ajax">
{include file="ajax_template.tpl"}
</div>
And in ajax.php :
//Do some stuff
echo $smarty->fetch('ajax_template.tpl');
Let say we are loading two or more views in the same class method like so:
$this->load->view('header');
$this->load->view('body');
$this->load->view('footer');
and you decide to create a variable inside the head view ($cat_name) like this example:
<?php
foreach ($categories as $key => $value) {
$selected = FALSE;
if ($this->router->class == 'category' && $this->router->method == 'id' && $this->uri->segment(3) == $value->id) {
$cat_name = $value->name;
$selected = TRUE;
}
?>
<option value="<?= $value->id; ?>" <?= ($selected ? 'selected' : ''); ?>><?= $value->name; ?></option>
<?php } ?>
This needed a loop to get that variable.
I want to pass that variable ($cat_name) to the next view without redoing the loop, that is just a waste.
what I am trying to achieve is minimizing the number of loops.
instead of loading all of that in controller load it in your view
create new file, let say template
$this->load->view('template',$variable);
and in your template
//do the loop here
$this->load->view('header');
$this->load->view('body');
$this->load->view('footer')
You need to create model for generating selects if You want to save MVC in Your project. I know, that's looks strange, but it will help You many times after
Controller
// load model
$this->load->model('myselect_model');
// get array with marked element
$select_data = $this->myselect_model->setSelected($categories, $this->router->class, $this->router->method, $this->uri->segment(3));
// get filled html
$my_html_select = $this->load->view('select_tpl',array('select'=>$select_data),TRUE);
// use it at any controller
$this->load->vars(array('my_select'=>$my_html_select));
// some views
$this->load->view('header');
$this->load->view('body');
$this->load->view('footer');
Model 'myselect_model'
function setSelected($items, $uri_controller,$uri_method, $uri_value){
// createing temp array for our list
$tmp = array();
foreach($items as $key=>$value){
// appending item
$tmp['options'][$key] = $value;
if ($uri_controller == 'category' && $uri_method == 'id' && $uri_value == $value->id)
{
// saving selected for any reason to use after
$tmp['selected'] = array('name'=>$value->name, 'id'=>$value->id);
// marking this item as selected
$tmp['options'][$key]['selected'] = TRUE;
}
}
// returning completed array
return $tmp;
}
View 'select_tpl'
<?php if(!empty($select)){?>
<select>
<?php foreach($select['options'] as $option){?>
<option value="<?=$option->id?>"<?=(isset($option['selected']) && $option['selected']==TRUE ? " selected=\"selected\"" : "")?>><?=$option->name?></option>
<?php }
</select>
<?php } ?>
views/header
<body><?=$my_select?><i>template here</i>
views/body
<p>some html here and our select goes here-> <?=$my_select?></p>
You could try like this:
Create a model like so:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Class Custom_model extends CI_Model
{
public function __construct()
{
parent::__construct();
}
function printSelect(){
// Do some logic and looping here
$html = "<select><option>...</option></select>";
return $html
}
}
Then call that model from your views like so..
$this->custom_model->printSelect();
Remember to load the model first.
$this->load->model('path/to/your/model/folder/custom_model');
This way, every time you want to print your you can simply call that method from your view.
I hope this helps.
So I'm setting up a system that has a lot of emails, and variable replacement within it, so I'm writing a class to manage some variable replacement for templates stored in the database.
Here's a brief example:
// template is stored in db, so that's how this would get loaded in
$template = "Hello, %customer_name%, thank you for contacting %website_name%";
// The array of replacements is built manually and passed to the class
// with actual values being called from db
$replacements = array('%customer_name%'=>'Bob', '%website_name%'=>'Acme');
$rendered = str_replace(array_keys($replacements), $replacements, $template);
Now, that works well and good for single var replacements, basic stuff. However, there are some places where there should be a for loop, and I'm lost how to implement it.
The idea is there'd be a template like this:
"hello, %customer_name%, thank you for
requesting information on {products}"
Where, {products} would be an array passed to the template, which the is looped over for products requested, with a format like:
Our product %product_name% has a cost
of %product_price%. Learn more at
%product_url%.
So an example rendered version of this would be:
"hello, bob, thank you for requesting
information on:
Our product WidgetA has a cost of $1.
Learn more at example/A
Our product WidgetB has a cost of $2.
Learn more at example/B
Our product WidgetC has a cost of $3.
Learn more at example/C.
What's the best way to accomplish this?
Well, I really dont see the point in a template engine that uses repalcements/regex
PHP Is already a template engine, when you write <?php echo $var?> its just like doing <{$var}> or {$var}
Think of it this way, PHP Already translates <?php echo '<b>hello</b>'?> into <b>hello</b> by its engine, so why make it do everything 2 times over.
The way i would implement a template engine is like so
Firstly create a template class
class Template
{
var $vars = array();
function __set($key,$val)
{
$this->vars[$key] = $val;
}
function __get($key)
{
return isset($this->vars[$key]) ? $this->vars[$key] : false;
}
function output($tpl = false)
{
if($tpl === false)
{
die('No template file selected in Template::output(...)');
}
if(!file_exists(($dir = 'templates/' . $tpl . '.php')))
{
die(sprintf('Tpl file does not exists (%s)',$dir));
}
new TemplateLoader($dir,$this->vars);
return true;
}
}
This is what you use in your login such as index.php, you will set data just like an stdClass just google it if your unsure. and when you run the output command it sends the data and tpl to the next class below.
And then create a standalone class to compile the tpl file within.
class TemplateLoader
{
private $vars = array();
private $_vars = array(); //hold vars set within the tpl file
function __construct($file,$variables)
{
$this->vars = $variables;
//Start the capture;
ob_start();
include $file;
$contents = ob_get_contents();
ob_end_clean(); //Clean it
//Return here if you wish
echo $contents;
}
function __get($key)
{
return isset($this->vars[$key]) ? $this->vars[$key] : (isset($this->_vars[$key]) ? $this->_vars[$key] : false) : false;
}
function __set($key,$val)
{
$this->_vars[$key] = $val;
return true;
}
function bold($key)
{
return '<strong>' . $this->$key . '</string>';
}
}
The reason we keep this seperate is so it has its own space to run in, you just load your tpl file as an include in your constructor so it only can be loaded once, then when the file is included it has access to all the data and methods within TemplateLoader.
Index.php
<?php
require_once 'includes/Template.php';
require_once 'includes/TemplateLoader.php';
$Template = new Template();
$Template->foo = 'somestring';
$Template->bar = array('some' => 'array');
$Template->zed = new stdClass(); // Showing Objects
$Template->output('index'); // loads templates/index.php
?>
Now here we dont really want to mix html with this page because by seperating the php and the view / templates you making sure all your php has completed because when you send html or use html it stops certain aspects of your script from running.
templates/index.php
header
<h1><?php $this->foo;?></h1>
<ul>
<?php foreach($this->bar as $this->_foo):?>
<li><?php echo $this->_foo; ?></li>
<?php endforeach; ?>
</ul>
<p>Testing Objects</p>
<?php $this->sidebar = $this->foo->show_sidebar ? $this->foo->show_sidebar : false;?>
<?php if($this->sidebar):?>
Showing my sidebar.
<?php endif;?>
footer
Now here we can see that were mixing html with php but this is ok because in ehre you should only use basic stuff such as Foreach,For etc. and Variables.
NOTE: IN the TemplateLoader Class you can add a function like..
function bold($key)
{
return '<strong>' . $this->$key . '</string>';
}
This will allow you to increase your actions in your templates so bold,italic,atuoloop,css_secure,stripslashs..
You still have all the normal tools such as stripslashes/htmlentites etc.
Heres a small example of the bold.
$this->bold('foo'); //Returns <strong>somestring</string>
You can add lots of tools into the TempalteLoader class such as inc() to load other tpl files, you can develop a helper system so you can go $this->helpers->jquery->googleSource
If you have any more questions feel free to ask me.
----------
An example of storing in your database.
<?php
if(false != ($data = mysql_query('SELECT * FROM tpl_catch where item_name = \'index\' AND item_save_time > '.time() - 3600 .' LIMIT 1 ORDER BY item_save_time DESC')))
{
if(myslq_num_rows($data) > 0)
{
$row = mysql_fetch_assc($data);
die($row[0]['item_content']);
}else
{
//Compile it with the sample code in first section (index.php)
//Followed by inserting it into the database
then print out the content.
}
}
?>
If you wish to store your tpl files including PHP then that's not a problem, within Template where you passing in the tpl file name just search db instead of the filesystem
$products = array('...');
function parse_products($matches)
{
global $products;
$str = '';
foreach($products as $product) {
$str .= str_replace('%product_name%', $product, $matches[1]); // $matches[1] is whatever is between {products} and {/products}
}
return $str;
}
$str = preg_replace_callback('#\{products}(.*)\{/products}#s', 'parse_products', $str);
The idea is to find string between {products} and {products}, pass it to some function, do whatever you need to do with it, iterating over $products array.
Whatever the function returns replaces whole "{products}[anything here]{/products}".
The input string would look like that:
Requested products: {products}%product_name%{/products}