2

I'm writing a simple templating layer in PHP but I've got myself a little stuck. Here's how it works at the moment:

Firstly I use fetch_template to load the template contents from the database - this works (and I collect all the templates at startup if you're interested).

I use PHP variables in my template code and in the logic - e.g.:

// PHP:
$name = 'Ross';

// Tpl:
<p>Hello, my name is $name.</p>

I then use output_template (below) to parse through the variables in the template and replace them. Previously I was using template tags with a glorified str_replace template class but it was too inefficient.

/**
 * Returns a template after evaluating it
 * @param   string  $template   Template contents
 * @return  string  Template output
 */
function output_template($template) {
    eval('return "' . $template . '";');
}

My problem, if you haven't already guessed, is that the variables are not declared inside the function - therefore the function can't parse them in $template unless I put them in the global scope - which I'm not sure I want to do. That or have an array of variables as a parameter in the function (which sounds even more tedious but possible).

Does anyone have any solutions other than using the code from the function (it is only a one-liner) in my code, rather than using the function?

Thanks, Ross

P.s. I know about Smarty and the vast range of templating engines out there - I'm not looking to use them so please don't suggest them. Thanks!

4 Answers 4

8

Rather than run through your loop you can use include($template_name).

Or, if you want the content of the output from the template, you can do something like this:

$template_name = 'template.php';

// import the contents into this template
ob_start();
include($template_name);
$content = ob_get_clean();

// do something with $content now ...

And remember, in your template, you can use the often overlooked PHP syntax:

<?php if ($a == 5): ?>
A is equal to 5
<?php endif; ?>

Alternative syntax is available for if, while, for, foreach and switch ... perfect for manipulating the data in your template. See "Alternative syntax for control structures" for more details.

Sign up to request clarification or add additional context in comments.

Comments

6

I'd pass an associative array with variables to replace, then extract() them.

Then you could also pass $_GLOBALS to achieve the same result.

function output_template($template, $vars) {
    extract($vars);
    eval('return "' . $template . '";');
}

Edit: you might also want to consider string subtitution instead of eval, depending on who's allowed to write your templates and on who specifies which template to load. Then there might be a problem with escaping, too...

1 Comment

I expect to be the only one touching anything code-wise on this system, the main reason I'm not using string vars (e.g. {VARNAME}) is because this is faster. I was skeptical at first but a friend pointed out to me how slow my original template compiler was.
3

Also, expanding on davev's comment eval is a bit ugly.

If you can do something like

function inc_scope( $file , $vars )
{
    extract($vars); 
    ob_start(); 
    require($file); 
    return ob_get_clean(); 
}

Then you get to use plain-old-php as your templating language, and you don't get any evil-evals, and "extract" + buffering merely limits the visible scope of the php code in the require.

2 Comments

"evil evals" - they're only evil if you're doing something stupid like eval('echo $_GET['name'];');!
eval'ed code is much harder to follow/debug than static code. Hence the "evil" label.
-1

Create file

  1. config.php
  2. index.php

Create folder

  1. inc
  2. template/default/controller/ main files here home.php, login.php, register.php, contact.php, product.php ...

  1. headet.tpl and footer.tpl include home.php file.
  2. main dir /template/default

config.php code here

/* semu design */
// HTTP URL
define('HTTP_SERVER', 'http://localhost/1/');

// HTTPS URL DISABLE
// define('HTTPS_SERVER', 'http://localhost/1/');

// DİZİNLER
define('DIR_INC',       'C:\wamp\www\1/inc/');
define('DIR_TEMLATE',   'C:\wamp\www\1/template/default/');
define('DIR_MODULES',   'C:\wamp\www\1/template/default/module/');
define('DIR_IMAGE',     'C:\wamp\www\1/image/');
define('DIR_CACHE',     'cache'); // [php cache system turkish coder][1]

// DB
define('DB_HOSTNAME',   'localhost');
define('DB_USERNAME',   'root');
define('DB_PASSWORD',   '123');
define('DB_DATABASE',   'default');
define('DB_PREFIX',     '');

index.php code here

<?php 
// Version
define('VERSION', '1.0');

// Config file
if (file_exists('config.php')) {
    require_once('config.php');
}

// Moduller
require_once(DIR_INC . 'startup.php'); // mysql.php db engine, cache.php, functions.php, mail.php ... vs require_once code

// Cache System
//$sCache = new sCache();

/*$options = array(
    'time'   => 120,
    'buffer' => true,
    'load'   => false,
    //'external'=>array('nocache.php','nocache2.php'), // no cache file
);

$sCache = new sCache($options);*/

// page
$page = isset($_GET['page']) ? trim(strtolower($_GET['page'])) : "home";

$allowedPages = array(
    'home'          => DIR_TEMPLATE.'controller/home.php',
    'login'         => DIR_TEMPLATE.'controller/login.php',
    'register'      => DIR_TEMPLATE.'controller/register.php',
    'contact'       => DIR_TEMPLATE.'controller/contact.php'
);

include( isset($allowedPages[$page]) ? $allowedPages[$page] : $allowedPages["home"] );
?>
  1. index.php?page=home
  2. index.php?page=login ...

Active class code

<ul>
<li <?php if ( $page == 'home' ) echo 'class="active"'; ?> Home </li>
<li <?php if ( $page == 'login' ) echo 'class="active"'; ?> Login </li>
</ul>
  1. And Token system coming :
  2. index.php?page=home&token=Co54wEHHdvUt4QzjEUyMRQOc9N1bJaeS

Regards.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.