I have been looking online for a tutorial to build a template engine. I know there are many engines that exist, like smarty, twig, and pattemplate, that could do exactly what I want, but I am looking to learn how to build one. I started with a template engine that added strings to an array and then displayed the array. Since then I built one using eval() (see below).
<// Define links & folders
define("ROOT_HTTP", "http://" . $_SERVER['HTTP_HOST'] . "/preprocessor");
define("TEMPLATE", "/template");
// Get the template file
$template = file_get_contents("template/template.php");
// Replace
$template = str_replace("<x Title x>", displayTitle(), $template);
$template = str_replace("<x Menu x>", displayMenu(), $template);
$template = str_replace("<x Content x>", displayContent(), $template);
$result = #eval("?>" . $template . "<?");
function displayMenu(){
return "Link1<br />" .
"Link2<br />" .
"Link3<br />";
}
function displayTitle(){
return "Site Title <?php echo date(\"m-d-y\", time()); ?>";
}
function displayContent(){
return file_get_contents("content.php");
}
It works fairly well but its not what I am looking to achieve. I would like to build something that is like the Joomla template with tags like <jdoc:include type="component" />. I would also like it to be able to handle errors inline meaning that it will display the line number of an error or when I call echo "text" it displays text in the correct position inside the template.
How do I create something along those lines?
http://www.phptal.org/ sounds very similar and has good code organization. if extension of mentioned system does not suit the needs, it would at least work as good tutorial
First of all: Immediately forget the idea about using a TE with XML-like tags. Really, it may look nice on the first glance but only causes too much work in the end and is really limiting.
Secondly I obviously recommend you to use Twig. It is clean, fast, extensible and offers all the features you need.
And lastly: I have written a small tutorial how to write a simple but powerful TE in another Stackoverflow question. It is really simple but for smaller projects it may suffice.
I cannot agree with NikiC's point of view.
XML is, although an old syntax, very powerful and brings a lot of advantages -- one of which is its similitude with properly written HTML.
There is nothing limiting in using an XML-based template syntax.
Besides, although Twig is, indeed, an excellent and famous project, it still lacks from a really good separation paradigm. It is still too dangerous and too easy to make mistakes from within the template and cause damages to the application as a whole.
Finally, the best template engine -- just as the best MVC framework -- is the one you feel really comfortable with.
I recommend having a look at FigDice]1, which was inspired by PHPTal, but takes things a few steps further, with an exclusive approach by giving the Web Designer (integrator, html-ist, etc.) a central position with the project -- much more flexible than the Twig-like approach.
I would be happy to read some feedback.
Thanks
Related
There are so many template engines out there. However, I am looking for something simple, fast and easy like the the phpBB3.0 Template System. Something simple like
$template->set_filenames(array(
'body' => 'your_template_file.html'
));
With similar templates using {L_SOME_VARIABLE} like output. I do not want to install phpbb because of the overhead. I need it to be simple but smart enough to where if I want to output json it will recognize when the last attribute is done not to output the leading ';'
I will be using it to output data in json, xml, txt, AOML and others pointing to its respective template, depending on the choice the user makes for desired data input.
I have looked at things like Smarty, but it seems a little much for me and there doesn't seem to be any easy json solutions.
If anyone has any simple solutions please let me know. I am unable to find this exact question on here.
PHP itself is a template engine (currently you can do much much more using it, but basically it is template engine) - IMHO creating and using template engines inside template engine is a little bit silly ;)
What I would suggest is just something like this:
function renderTemplate($_file_, $_args_ = null, $_return_ = false) {
if (is_array($_args_)) {
extract($_args_, EXTR_SKIP);
}
if ($_return_) {
ob_start();
ob_implicit_flush(false);
require('/mypath/to/templates/'.$_file_.'.php');
return ob_get_clean();
} else {
require('/mypath/to/templates/'.$_file_.'.php');
}
}
When I write PHP code for websites, I don't like mixing business logic with the presentation layer and as such I tend to create markup templates. I've written a very lightweight template engine to facilitate this, since I really don't want to move to a fully-fledged template framework like Smarty.
Here's a simplified example of what I do:
function renderTemplatePage($page, $params)
{
$page = readTemplateFile("templates/{$page}");
$tokens = getTemplateTokens($page);
foreach($tokens as $token)
{
if(substr($token, 0, 6) == "%_TPL_")
{
$subPage = renderTemplatePage(tokenToPageName($token), $params);
$page = str_replace($token, $subPage, $page);
}
else
{
$page = str_replace($token, $params[$token], $page);
}
}
return $page;
}
Sample page:
<html>
<head><title>%_PageTitle_%</title></head>
<body>
<div id="header">%_TPL_Header_%</div>
<div id="content">%_TPL_Homepage_%</div>
<div id="footer">%_TPL_Footer_%</div>
</body>
</html>
A call to renderTemplatePage("index", array("PageTitle" => "Home")) would produce a page entitled "Home", with content from the Header, Homepage and Footer templates.
I do all of my logic (including db queries, etc) before calling the rendering, so I can mass up a large $params array and just do a single call to render it all.
Are there any flaws in this methodology? Is there a more standard way to do this?
Its flawed. How do you handle template specific logic . Just out of curiosity how would you handle ifs or loops
There are several ways of achieving separation between logic and representation (it's formally known as part of MVC - Model-View-Controller methodology).
One direction I would like to point you in is XML+XSLT. The idea is to assemble all the information you need as an XML string (e.g. have a look at the output of the following URL: http://www.whiteoctober.co.uk/?dumpXML) , and then perform an XSLT transform on it (see http://www.w3schools.com/xsl/xsl_transformation.asp).
Templating in PHP is a religious debate - one I would rather not get dragged into. Suffice to say I'm strongly against Smarty - it's bulky and does nothing that standard PHP does not already do.
The problem with all these homebrew templates is lack of real life testing.
Instead of doing such a test you are coming here to ask other people.
It is not so wise strategy in general, as your own experience is indispensable, while there are not so much pro's hangs around having enough time to write you an extended answer. While there are always lots of inexperienced users ready to answer.
Are there any flaws in this methodology?
yes, of course.
You are declaring that you don't like mixing business logic with the presentation layer.
But whati is the content of %_TPL_ and where it written? In the same old business logic, I suppose. So, where is your desired separation then?
Im currently working on a system that has a comment system integrated, the system is running on Codeigniter so im looking to create a markdown library but with really minimal features.
The features im looking to have is
Autolinking
Bold *bold*
Italic _italic_
And that's practically it, The post data will be run through Codeigniter's XSS Class before it goes to the mark down class
So my question is what's the best way to do this, should i be using a library out there and disabling certain features, should I build this from scratch, if so, how should i build the class and what things should I take into account.
I was in a similar situation recently, where I wanted to support some kind of markup (BB, Markdown, etc). It turns out nothing has been done with BBCode for about 100 years, and it's dead easy to write a regex parser for it (for well-formed markup at least) so i wrote a really bare bones function to do just that.
My version also includes images, codes, and color support as well as nested tags ([b][i]bold and italic[/i][/b]).
function parseBBCode($string){
$search = array(
'/\[b\](.*?)\[\/b\]/',
'/\[i\](.*?)\[\/i\]/',
'/\[u\](.*?)\[\/u\]/',
'/\[img\](.*?)\[\/img\]/',
'/\[url\=(.*?)\](.*?)\[\/url\]/',
'/\[code\](.*?)\[\/code\]/',
'/\[color\=(.*?)\](.*?)\[\/color\]/'
);
$replace = array(
'<strong>\\1</strong>',
'<em>\\1</em>',
'<u>\\1</u>',
'<img src="\\1">',
'\\2',
'<code>\\1</code>',
'<span style="color:\\1;">\\2</span>'
);
$new = preg_replace($search, $replace, $string);
return nl2br($new);
}
You can begin with PHP Markdown class ?
or the one for CI.
And If I may suggest, you can also try MarkItUp as front end..
For me the easiest way to integrate Markdown is by simply
putting markdown.php from Michel Fortrin into my Application/helpers/ folder,
rename it to markdown_helper.php
load it with $this->load->helper('markdown');
...just in case someone - like me - stumbles upon this old thread again :)
I'm trying to find the best way of structuring a multi-language site navigation,.
I'm aware of the language class in CI but it seems to be more for defining random words and lines of text that are used commonly throughout the site. It appears that creating lang files for each language and then defining translations of all the links seems like the standard approach?
In past on non-codeigniter projects I’ve setup one class like this
class Link{
var $name = array();
var $url;
var $links = array();
function add_link($links){
$this->links[] = $links;
}
}
$all_sections = array();
$section = new Link();
$section->name['en'] = "Home";
$section->name['fr']] = "Uberdurky";
$section->url = "/";
$sub_section = new Link();
$sub_section->name['en'] = "About Acme Ltd";
$sub_section->name['fr'] = "Fabuka Acme Ltd";
$sub_section->url = "/about/";
$section->add_link($sub_section);
Then I have a function to loop through and output the nav, which just looks at the current name[Lang] as defined by session or URL
This to me seems simpler and less overhead - with the benefit that both the nav structure and translations are defined in one place. But I’m new to CI so I might be misunderstanding the standard approach… ? I've googled quite a bit and haven't seen a solution here in detail.
The important thing is that it works for you. There are a lot of benefits to using separate language files:
Clean separation
Only load what you need
Easy to keep track of which languages are available
Ability to let others easily translate the files
I don't see anything wrong with the way you're doing it, but if you want to optimize - don't bother defining all the different language lines. You don't need the French version defined if the language is English. Use only the ones you need, you shouldn't have to pass the whole array to add_link(), the Link class should be detecting the language and loading the appropriate array only...
...it's starting to sound like a language file might be a good idea actually.
For now you just have French and English. I'm assuming you know both languages and (Uberdurky?) are the only one working on this aspect, so it's easier for you to define them "inline". What happens when you want to support 3, 4, or 10 languages? Things will quickly become disorganized and cluttered.
However, you don't have to use the Codeigniter Language class, you might be better off using your own system for something like navigation, which tends to be littered with 1 or two word translations, and changes somewhat frequently (either per site or between sites).
Once again, it's your call. Do what works best for you now and optimize later.
This might be helpful to anyone coming across this question.
https://github.com/cflynn07/CodeIgniterInternationalizationUtility
It's a script to take a cleanly structed HTML table of language translations, and convert them into the required language files used in codeigniter.
I am building a English/french website and was wondering if there is a best practice for such a job.
Duplicating the site and making a french and english folder with the appropriate site inside.
Using PHP to swap the content with html tags.
eg. if($lang=='en'):
Use php to swap only the content leaving the html tags the same for both. eg. if statements all over the place. Would this be bad for efficiency?
Any other suggestions would be appreciated
We have a framework in place for when (if) our site goes international that works like this...
Folder structure;
/
lang/
english/
images/
text/
dutch/
images/
text/
Any text or images that are language specific are removed from the page directly and replaced by constants. eg On the login screen, we drop in;
echo TEXT_LOGIN_WELCOME;
which is defined in /lang/english/text/login.php as;
define('TEXT_LOGIN_WELCOME', 'Welcome, please login:');
but in /lang/dutch/text/login.php it's defined as;
define('TEXT_LOGIN_WELCOME', 'Welcome, please login (in dutch):');
;-)
Each language define file is named exactly the same as the page it is used for, so when we load a public-facing page, we only need to figure out which language the user speaks and we can include the relevant language define file.
The good thing about this system is that all the language info is centralised. When you need to add a new language, simply copy the main (english?) folder, rename it, zip the whole thing up and send it to a translation service to work their magic. Of course, the downside of this system is the maintenance as both languages and content grow... If anyone has any bright ideas with regard to this then I'd love to hear them!
Btw, if you end up needing to guess a user's location by IP, you might want to check out geoIP.
Use a templating system. Smarty Template Engine is probably one of the most well-known PHP ones. Not only does a templating system serve the exact purpose you're trying to accomplish, it also makes maintaining pages far easier by separating the display code from the content (which also allows you to use the same template for lots of different content pages of a similar nature).
As the simplest way I recommend you to use i18n internationalization method & gettext catalogs (.po files).
The famous WordPress project is using it as well.
1 - Duplicating the entire site will force you to repeat every code touch-up into the 2 folders :-[
2 - If you mean somenting like
<?php if($lang=='en') { ?>
<p>English text</p>
<? } else { ?>
<p>Text français</p>
<? } ?>
This solution is perfect to manage two languages in the same page.
But you still have duplicated tags.
3 - Change only content it's really satisfaction.
Maybe proliferate of if statements can weigh down php compiling... I don't know.
Anyway document can be more concise with this approach:
<?php
function interpreter($buffer) {
$pieces = explode('#', $buffer);
if (isset($_GET['lang'])) $begin=$_GET['lang'];
else $begin = 1; // 1 to display français, 2 to display english
$tot = count($pieces);
for ($i=$begin; $i<$tot; $i+=3) { // remove one language
unset($pieces[$i]); }
foreach ($pieces as $value) { // recompose the text
$output .= $value; }
return $output;
}
ob_start("interpreter");
?>
#Français#English#
<p>#English text#Texte français#.</p>
<?php ob_end_flush() ?>
The text between ob_start and ob_end_flush is parsed AFTER php compiling.
That means are affected strings coming eg. from echo statement, not inside < ?php ?> tags.
Also content coming from php include IS affected.
But NOT external css or javascript.
Keep attention delimiter # isn't a caracter yet used elsewhere.
Maybe you'll prefer to replace with || or ^^
Of course in the future you can adapt this solution into 3 languages or more. But if you have to insert the "Third language translation#" in many lines of a big site, maybe the solution from MatW fits you.