As a small part of a university project I'm working on (custom MVC based project management system), I need to develop a template engine. I don't wish to use an off the self system such as Smarty because I've written every other part of the project myself and don't want to go back on that now.
Anyway, I've managed to code something simple so far, I have a class, create an instance of it, add some data to the instance, then pass in a template file. The file has a series of tags like {this} when then get replaced with the data. Simple.
The issue I'm having is when it comes to looping things - i.e. a table of users or a list of categories. At the moment I have a template file for the page (users.html) which contains the opening and closing tags, with a template tag between them called {users}. I then have another template file (users-detail.html) which displays a table row with the user info in. I'm creating a new instance of the users-detail.html template, adding the data, parsing it, then placing the output (string of HTML) into an array. I then loop this array, attach all the strings together, then assign this to the {users} tag in the users.html template file.
As you can probably tell from that explanation it is a bit of a bodge, and there are probably better methods out there for doing what I'm trying to achieve. Ideally I want to avoid using PHP in the template files if possible, and I often need to have multiple loops within one template file.
If anyone has any tips / advice on how I can achieve this, or any tutorials I could follow to get some inspiration that would be much appreciated.
Thanks in advance.
I've seen that approach before (including another template for the insides of loops). I used to work on an old version of vbulletin which does (or did) this. It makes things annoyingly complicated because you can't just add a loop to a template - without setting up a whole new template for each layer of looping.
I'd advise you instead to go along the route of Smarty.
Classically, this statement:
I don't wish to use an off the self system such as Smarty because I've written every other part of the project myself and don't want to go back on that now.
... indicates you really should just be using Smarty. In the real world that would be a poor justification for re-implementing something yourself. But I am like you, and I understand that you want to implement something yourself (because you want to learn, you find it fun, you are a perfectionist, etc). As long as you do it on your own time and it's a personal project, go for it.
It would be worth studying Smarty to see how it works (not just the syntax but how it compiles templates, stores the compiled version etc). Are you comfortable writing a tokeniser/parser in PHP which can compile your template language and output PHP? If you are advanced enough to do it, do it. At the very simplest, you read in a tag like {foreach from=$something} and somehow translate it to <?php foreach ($something as $thing) { ?>. You check token types, etc to make sure the template tag is valid, and so on.
Related
I would really appreciate if anybody could help me with this question :)
I want to know whether it's possible to create your own semantic markup in PHP, just like BB Codes, but I want to be able to use it within my template engine system, so I could use it to call custom modules like voting system, adding comments, login form, registration form and so on...
Let me make it clearer for you guys of how I mean;
I'm working on my own CMS not to use it for production purposes but to learn PHP in a better way;
So I had this idea to call specific modules in a page based on their position and in order to be able to do;
For instance we're having a login module which is simply a login form, nothing too crazy, however you want to be able to include that module dynamically in any page you want using the backend and not touching any code;
So all you do in the template page is using my bb codes that I told you earlier;
Something like this;
Remember this is only an idea;
<zone name="left_sidebar"></zone>
And you add this zone markup on your sidebar and if any of your module supposed to be displayed on your left sidebar, it will just by having this markup and nothing more...
And you gone have loads of these semantic markups based on how many editable blocks you have on your page; so you could have one for the right sidebar, one for footer and one for header... etc.
So I now need to know how to could lookup for opening and closing tags, in this case it would be <zone></zone> , then it need to lookup for its attribute and its value, in this case name="right_sidevar"
....
Anybody have any idea of how I could possibly do this kind of thing...
Thanks in advance :)
You could check out TWIG; while it doesn't directly support this kind of feature (because it uses a special syntax for its own elements) it does have very good support for making your own elements, tags, sub-applications and other funky things in the backend.
http://twig.sensiolabs.org/
There are also a number of systems that perform this kind of task in the front-end; this would mean that the substitution is done by Javascript in the browser. In addition to the already mentioned Polymer, there's also Google's framework, Angular.
https://angularjs.org/
Maybe you can use php's libxml module to parse your xml file.
I want to understand how to use templating system and permalinks on php websites :D !..
let me describe my self more,
1.currently i have 20 files each have its own php logic (index.php,wizard.php,search.php etc)
ALL use same class's and includes.(install.php include all the required for all class's in my project abd u require_once(install.php) in all files)
i wana remodel my website into.
Analyze URL requested ---> IDENTIFY requested page ---> GET TEMPLATE for THIS PAGE -->MODIFY header(meta) and footer(javascript) ---> add logic ---> display page :D.
can some one put me on right learning track :D !. cuz i hv coded my website fully in oop and made all its content loads dynamically from MYSQL (simple small CMS) but i have no clue how to join template and php into index without repeating my self and create different file for each page in my web ! (each file do different jobs of course like file users.php does login and registration and userprofile etc)
Hope my english wassnt too too bad and u could understand my question :D !
My current approach so far:
Mysql table : page_tbl
columns: pagename,LogicFile,templateFile,MetaTag.
index.php?pagename
will check if not already cached or not listed for chacing it will :
Mysql:SELECT * WHERE pagename='$_GET['page']'
loginfiles = cars.php,search.php (will be exploded with , and included)
Template files = will be also exploded and modified according to MetaTag.
Metatag: Serialized assoc array with ['name']=['value'];
Then i start buffer output , replace template with new descriptions and keywords(auto generated)
include logic files
include footer.php (which include the scripts)
am i near to correct rout or still far away ? or am did i lose my track and over killing
If you are unsure whether you want to write your own, or use an existing one.
It is going to be a quite possibly very rewarding experience but a very time consuming one to write your own.
If you have a task at hand that you need to be solved, use an existing one.
That being said there are plenty of templating systems, smarty being the most long-lived one. You can find a short discussion on 5 popular ones at phpbuilder.
You also have entire Frameworks that you might want to consider. They are more than just a templating system, where database stuff, ajax helpers etc are included. Zend, CakePHP, and Codeigniter being popular ones. You can find comparisons of these at phpframeworks.
The best way is to take this route:
parse request data
determine controller which will be used
in controller select layout and template [layout "includes" template, it hold the contents that are common to all pages and template has the request-specific content]
in controller also fetch the data from database [MVP way]
assign data to array and pass it to the layout, it'll pass the data futher to the template
in layout and template use data from that array and construct view
pass everything to the browser
This is the way the frameworks work, and it isn't that bad. ;]
For some years that I've been using my own PHP template engine, which is not really "my own" as I saw it on a tutorial many years ago. However, I've refactored most of the code making it simpler and easier to use. I rarely make a PHP project without it.
It's very basic and the class only has 3 methods, load, assign and render. The load loads the template file (usually HTML) and saves it as a string variable. The assign allows to assign references in the HTML to variables in the form of {reference}. The render parses the template file and replaces the references with the variables. That's basically it. Very basic, very simple and a time saver for me.
I like this template engine because I hate to mix PHP with HTML and whatever. And so I'm not very fond of PHP itself as template engine (like WordPress templates), although very powerful for such thing. I don't like the idea of saving my files as .php files and then include/require them with a bunch of mixed PHP code, I like to keep it simple.
However, has rudimentary as this template engine is, it doesn't allow for conditions and loops, two very important things that sometimes are needed. So far I've been working around that issue by separating template files and then do all the conditions/loops in the controller. For instance, I have the main template file which has a <ul> list where the items come from a database, I'll just have a separate template file with one line of code for the <li> item. Do the loop in the controller and render the as many <li>'s as needed.
This was an introduction so you understand where I come from. Now to the real question...
I've been thinking and experimenting alternatives to this method and start using PHP in the HTML template files with as little code as I can. For instance, like this:
<ul>
<?php foreach($array as $val): ?>
<li><?php echo $val; ?></li>
<?php endforeach; ?>
</ul>
And the in the controller something like this:
// assuming the data comes from a
$array = array('Item 1', 'Item 2', 'Item 3'); database...
ob_start();
eval(' ?>'.$TPL->render('main').'<php ');
echo ob_get_clean();
First point I want to make is that this presents a problem for me. It kinda defeats the purpose of this template engine. There I am, calling echo $val where I should have a reference to be replaced. But wouldn't it be completely idiotic to have a reference to be replaced in the template rendering when I have the $val variable right there waiting to be used? But I also don't like the idea of using lots of PHP code in my template files, I would prefer to avoid as much as I could without compromising the whole thing too much. However, I don't see how could I have a reference in the place of the echo and have it replaced by $val for each loop. What your take on this?
Secondly, I would like your opinion and [more] issues that you think this solution might have. Or if there's some thing wrong in the code or how could it be improved, etc... I know I could use an extra method to do all the output buffering and eval to simplify the template rendering, but I'm looking for other stuff I may have overlooked or completely forgot about or simply missing the knowledge, most likely.
Maybe I'm thinking too much into this, maybe I should just forget about the whole thing and keep doing this as I've been doing for the past few years. It worked very nicely for me and simplified all my projects. In the end, I'm basically looking for a way to simplify conditions and loops in my template files without requiring extra template files, some with only a couple of simple lines of code.
I believe the way other languages address this is by offering server side markup, like the asp repeater control and I found this question here too which suggests you stick with your solution and gives a -1 to person who suggests rolling their own custom template tags to achieve the same thing... maybe it just doesn't get much simpler and building it is over-design.
I'm hosting a multi area solution written in PHP, and each customer has its own template in some HTML files. Now I want these users to be able to use some chunks of dynamic content, but they can't be able to use PHP. I thought something like:
In the HTML file, if I put this:
<ul>[menu-list]</ul>
Will output something like:
<ul><li><a[...]>Home</a></li><li><a[...]>About</a></li>[...]</ul>
Is there any better way of doing it than keep parsing and caching files via file_get_contents() and preg_match_all()?
I want to create about 20 entries like [menu-list], and parsing every file for all of them seems quite expensive to me.
I'd appreciate any suggestion. =D
Perhaps you should consider using a template compiler instead of a template interpreter. That is, instead of each time the page is loaded doing this whole replacement procedure you could simply perform the replacement after the template has been modified. During template editing the cost should be negligible. To implement this compilation you could choose to "compile" in some breadcrumbs so you can go backwards, or you can simply save the original template files for later editing.
Alternatively, you could consider using PHP variable naming conventions and running your templates through an eval, but this poses a number of other issues (like security threats) and doesn't come highly recommended.
Why can't you use Smarty and friends? I would not want to write what you suggest myself.
I'm starting to understand the importance of templating in PHP. I'm using PHP itself as a template engine to avoid learning any new language. I'm still not clear on one thing tho, although I have an idea about it. I would like to know what the experts do.
Should I create a full page template, with all tables, forms and everything else (including header and footer), or should I put all of my tables, forms, etc in their own file and then add them to the template as needed.
Here's a small example to clear things up...
Should I
a) create one page with all the tables, forms, and other elements in it and use that as a final product
// Set all the information
$template->title = $username;
$template->user_info = get_user($user_id);
$template->articles = get_articles($user_id);
$template->ads = random_ad($user_info);
// Load the template with everything already in it
$template->load('user_page.tpl')
$template->display();
OR
b) create every table, form, related block element in its own file and then use those to create a final product
// set the title and load the header template
$header['title'] = $username;
$template->load('header.tpl', $header);
// get the user info as an array and load into user profile template
$user_info = get_user($user_id);
$template->load('user_profile.tpl');
// load the new article form
$template->load('new_article_form.tpl');
// get the articles as an array of info and load into user articles template
$articles = get_articles($user_id);
$template->load('user_articles.tpl', $articles);
// get a random ad based on user info
$ads = random_ad($user_info);
$template->load('advertisements.tpl');
// load the footer template and display final page
$template->load('footer.php');
$template->display();
Where every file loaded contains a small portion of what needs to be displayed on the final page.
Because of the Dont Repeat Yourself technique, I would think B, but i would like to know which and why
I would personally say the first approach is best, because it keeps all documents and document fragments semantically complete.
The second approach means that you'll have a <div> in your header.tpl that is closed by a </div> in your footer.tpl (except likely there will be a few tags that applies to). This means if you change your layout, by adding a wrapper div (for example) somewhere, you have to remember to also close it in another file (or, depending on your layout, two or three different files).
It's worse with several different embedded files. Think of how hard it is to debug a site, when one file - that gets included conditionally - has an extra </div>. You get a vague bug report "sometimes the page looks completely messed up, doesn't matter what browser I use" that is very very hard to track down. It's MUCH worse if you're using table-based layouts..
Using the first approach, you can still use the DRY principle. You load the template into a variable. eg:
$userVars['name'] = $currentUser->name;
$templateVars['userinfo'] = $template->load('userinfo.php', $userVars);
...
$template->display('template.tpl', $templateVars);
You can continually nest documents that way. There are many benefits:
Each file is semantically complete HTML - all tags that are opened, are also closed in the same document. It's easy to edit one part of the layout without breaking (possibly unknowningly) anything else.
It's each to cache the output of certain templates, and re-use them
It's easy to apply AJAX to the site. For example, you have a stats.tpl template rendering inside a <div id="stats"> on the first page load. You also have a view that just renders the stats.tpl template by itself, and then use jquery to do $('#stats').load('/ajaxstats.php'), which refreshes that div but without repeating code at all.
Template inheritance for structures common to every template (e.g. layout; header/footer), and template embedding (i.e. including) for reusable bits (e.g. forms).
With approach A and without inheritance, you'd be either including common layout elements (which is IMHO ugly), or duplicating entire layout in every template (which is even worse). And plain approach B would create massive amounts of tiny template bits for everything, which may reduce maintainability.
And for that, I really recommend using real, dedicated templating engine instead of plain PHP. They make life easier (inheritance is one thing; another - variable auto-escaping).
template inheritance would probably make the cleanest code. you can do this now in straight php using PHP Template Inheritance
There is no good or bad solution. There are techniques and guidelines but in time you will learn what approach is better than others.
Just by looking at it i would say that the second approach allows you to be more flexible and breaks down the page into smaller parts. Smaller might some times mean more manageable.
Also the second solution also allows more than 1 persons working on the page since they will only need to work/change parts of the page and not the whole page.
regards,
As gregmac suggested, the first solution is probably preferable. Having said that, I would also suggest to have a look at the various PHP frameworks available, most of which implement templates using various techniques.
Have a look at this list for a start. You may also want to take a look at some stand-alone template engines, such as Smarty, in order to get some ideas or to avoid implementing your own engine.