|
-
Jun 12th, 2010, 06:59 PM
#1
Thread Starter
Hyperactive Member
[RESOLVED] PHP Templating Engine Semantics
I'm working on a template engine in PHP to streamline dynamic web development. Technical details aren't really necessary, but I'm just wondering what anyone thinks about the syntax of my "language" and how I could improve it.
There are 3 kinds of tags that can be incorporated into HTML files to use the template system, they are:
Variables
HTML Code:
@@var name(myVar) default(Default Value)@@
Components
HTML Code:
@@component name(myComponent)@@
and Regions (the one I'm trying to figure out the syntax for, this is what I have so far)
HTML Code:
@@regionblock name(myRegionBlock)@@
@@region name(myFirstRegion)@@
.
.
.
@@end_region name(myFirstRegion)@@
@@region name(mySecondRegion)@@
.
.
.
@@end_region name(mySecondRegion)@@
@@end_regionblock name(myRegionBlock)@@
Just a bit of background on the tags;
The var tag takes data that you generate (from a database or text file or whatever) and replaces the instances of it in the HTML file with said data.
The component tag takes another full page, and places it at that location in the HTML file containing the tag (basically an advanced include();)
The regionblock/region tags allow you to define part of a document in different ways, and regions can be duplicated multiple times with different data in each copy. You can have any number of region tags in a regionblock, and they all define different things the page could display at that point.
A good example for regionblock/region usage would be search engine results. One regionblock could contain a region for the results with titles, authors and publish dates for books; another region that says there were no search results; and another one that says there was an error or other issue. Based on what happens in the actual script that calls the database, etc., you define what to show, whether its results or an error or whatever.
Here's an example:
HTML Code:
@@regionblock name(searchResults)@@
@@region name(result)@@
<h3>@@var name(bookTitle)@@</h3>
<p>@@var name(bookAuthor)@@</p>
<p>@@var name(bookPublished)@@</p>
@@end_region name(result)@@
@@region name(no_results)@@
<h3>There were no search results for your search. Try something else</h3>
@@end_region name(no_results)@@
@@region name(error)@@
<h3>There was an error connecting to the database.</h3>
<p>@@var name(errorMessage)@@</p>
@@end_region name(error)@@
@@end_regionblock name(searchResults)@@
Anyways, (hopefully that was kinda straight forward) the engine works for the most part, but I'm just concerned about the naming convention.
Should I keep using the @@ characters to delimit the template tags?
What should I call what is currently being called regionblock? (I don't like regionblock) Is there a more.. semantic name? Regionlist? Regionset?
Should I change the name from 'region' to something else altogether? Should I change any of the template tag names?
The regionblock tag uses the name() argument, but so does the regions inside. I think that may be confusing... Should I change any of the argument names?
I greatly appreciate all advice in advance!
-
Jun 12th, 2010, 07:27 PM
#2
Re: PHP Templating Engine Semantics
That looks like a solid structure.
I'm working on a template engine too.
It's pretty much the same, but I have a different naming convention.
The default value is a great idea. I might include that in the engine too.
As for the delimiter characters question; it should be fine, but you'll need to consider the engine.
If you want to run it recursively (so that you can include more template mark-up in a variable or something), you might want to add a @@noparse@@ tag for user input.
Of course mind I'm still in designing stages, so I could overlook something here.
Oh, and by the way, would you mind sharing the outlines of the template engine?
I'm happy to share what I have so far.
Delete it. They just clutter threads anyway.
-
Jun 12th, 2010, 07:38 PM
#3
Re: PHP Templating Engine Semantics
Oh, one thing I spotted is that you close the regions with the name as parameter.
I don't know if you allow nested regions.
If you do, I discourage this as it might cause crossing of regions and with that very unexpected results.
Take this example:
Code:
// This can come out really badly
@@region name(myFirstRegion)@@
@@region name(mySecondRegion)@@
...
@@end_region name(myFirstRegion)@@
@@end_region name(mySecondRegion)@@
// This should work fine
@@region name(myFirstRegion)@@
@@region name(mySecondRegion)@@
...
@@end_region@@
@@end_region@@
Although to a somewhat trained coder can easily spot the problem here, the latter always prevents this problem.
Delete it. They just clutter threads anyway.
-
Jun 12th, 2010, 07:47 PM
#4
Thread Starter
Hyperactive Member
Re: PHP Templating Engine Semantics
The interpreter determines the appropriate end region based on the name argument included in the end tag. There are no anonymous (thus possibly confusable) end tags. Much like XML, nesting must be done correctly, otherwise the page will render improperly. I'm working on a logging system to detect and record possible failures like this in the event of poor region nesting.
I'd be happy to share the entire script and manual with you once it's done. Once I get a few things sorted out, it'll be good for deployment. It's purpose wasn't for public use, personal rather, but anyone who wants it can have it.
Thanks for you insight!
-
Jun 12th, 2010, 10:58 PM
#5
Re: PHP Templating Engine Semantics
I don't really like the syntax, but that's because @ symbols are ugly. I think it could be easier to deal with (and code with) if you did something XML-esque like Flex and ASP.NET do with a namespace:
Code:
<mx:Tag />
<mx:Tag></mx:Tag>
<!-- or -->
<asp:Tag />
<asp:Tag></asp:Tag>
Regarding the "regionblock" and "region" names, I'll give you my thoughts: a region is a section of the page that can have multiple views, or templates. you could do something like:
Code:
<ns:region name="search">
<ns:view name="resultSet">
<h3><ns:var name="title" /></h3>
<ul>
<li>Author: <ns:var name="author" /></li>
<li>Year: <ns:var name="year" /></li>
<li>Description: <ns:var name="description" /></li>
</ul>
</ns:view>
<ns:view name="emptyResultSet">
<h3>There were no results</h3>
<p>Perhaps you could try another search query.</p>
</ns:view>
<ns:view name="error">
<h3>An error occurred</h3>
<p><ns:var name="error" /></p>
</ns:view>
</ns:region>
alternatively, you could name variables by using the variable name as the tag name rather than having a 'var' tag -- you would just have reserved variable names. <ns:title />, for example.
-
Jun 12th, 2010, 11:43 PM
#6
Thread Starter
Hyperactive Member
Re: PHP Templating Engine Semantics
 Originally Posted by kows
...if you did something XML-esque like Flex and ASP.NET do with a namespace:
[code]<mx:Tag />
<mx:Tag></mx:Tag>
Love it. I was going to go with a markup language syntax, but for some reason strayed.. I think it was because you'd need to escape certain characters within the quotes. I'm gonna implement this.
 Originally Posted by kows
...a region is a section of the page that can have multiple views, or templates.
Also love it. Regions contain views. Perfect.
-
Jun 13th, 2010, 01:05 AM
#7
Thread Starter
Hyperactive Member
Re: PHP Templating Engine Semantics
Alright, I've decided to go with the syntax of:
HTML Code:
<zl:var name="varName" default="Default Value" />
Now I'm concerned with the parsing method I've been using. Do you think it would likely be faster to utilize the PHP DOM class to find, parse, and manipulate the template tags, or would it remain efficient to use the RegEx parsing I've used thus far?
-
Jun 13th, 2010, 02:24 AM
#8
Re: PHP Templating Engine Semantics
it would be useful if you could use an XML parser, but only if you could tell it to ignore anything outside of the zl namespace. I'm not sure if you can do that or not.
what have you been doing to parse this? when I was doing something similar to this, I was using regular expressions to match tags. I abandoned this project in favour of another, but I have a tag parsing class that might be useful to look at, or something.
-
Jun 13th, 2010, 02:39 AM
#9
Thread Starter
Hyperactive Member
Re: PHP Templating Engine Semantics
(Note: For the moment, I've reverted to the @@type args@@ syntax... but altering it to markup syntax is really very simple in my implementation)
This is a snippet from the compile method, that performs the replacements:
PHP Code:
switch($type){ case "region": foreach($data as $name => $value){ $buffer = preg_replace("/@@ region \s name\(" . $name . "\) @@ (.*) @@ end_region \s name\(" . $name . "\) @@/xsi", $value->compile(), $buffer); } break; case "component": foreach($data as $name => $value){ $buffer = preg_replace("/@@ component \s name\(" . $name . "\) @@/xi", $value->compile(), $buffer); } break; case "var": foreach($data as $name => $value){ $buffer = preg_replace("/@@ var \s name\(" . $name . "\) @@/xi", $value, $buffer); } break; }
-
Jun 13th, 2010, 02:43 AM
#10
Thread Starter
Hyperactive Member
Re: PHP Templating Engine Semantics
I haven't tested it, but this is the region constructor:
PHP Code:
public function __construct($regionName, &$parentObject, $callbackFunction = false){ $this->name = $regionName; $this->parent = $parentObject; $this->parent->data[count($this->parent->data) - 1 > 0 ? count($this->parent->data) - 1 : 0]["region"][$regionName] =& $this; if($callbackFunction !== false){ $this->callback = $callbackFunction; } if(preg_match("/@@ region \s name\(" . $this->name . "\) @@ (?P<views>.*) @@ end_region \s name\(" . $this->name . "\) @@/xsi", $this->parent->template, $region)){ preg_match_all("/@@ view \s name\((?<name>.*)\) @@ (?P<template>.*) @@ end_view \s name\((?P=name)\) @@/xsi", $region["views"], $views); foreach($views as $view){ $this->template[$view["name"]] = $view["template"]; } } }
Edit: I think I need to add the PREG_SET_ORDER flag to the preg_match_all call
Last edited by tomcatexodus; Jun 13th, 2010 at 02:52 AM.
IWS
-
Jun 14th, 2010, 08:42 PM
#11
Re: PHP Templating Engine Semantics
 Originally Posted by kows
it would be useful if you could use an XML parser, but only if you could tell it to ignore anything outside of the zl namespace. I'm not sure if you can do that or not.
I would use a XSL stylesheet to transform the template markup into HTML. The XSL and XPath expressions can be composed to target elements and attributes within a particular namespace. Regular expressions are harder to maintain and test and a badly-written expression can easily invalidate the markup. Because your input stream is (should be) well-formed XML, it is best to treat it as such and thus ensure your output is also well-formed.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|