Custom php template engine: Am i finally on the right track? - php

Since I keep showing up late for answering questions tagged php where i actually know the answer i figured i'd try asking a question myself.
I've been working on so many complete rewrites of a custom template engine in php for so long and so many times that i thought i'd ask for opinions.
In short, this is the most important part i have implemented so far:
Any http request is routed to handler.php
based on the requested URL a controller is instantiated and a method on that controller is called.
The controller method must return an IView compatible class instance ( IView defines a Render() method)
The template engine does some xpath for every namespace that ends in 'serverside' sprintf('//%s:*[#runat="server"]', $namespaceprefix )
For every found tag, it looks up the php class identified by $tag.localName and instantiates one and attaches it to the original template.
Once attached, the original template node is fed to the 'ServerTag' so it can initialize properly
the fully complete IView compatible instance is assigned to a temporary variable in the controller method.
The controller asks pushes data from a Model class to the view which does some nifty xpath DOM replacement.
The controller returns the completely filled view to main()the handler, which renders it.
I am basing my template on xml. a simple template currently looks like:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:red="http://www.theredhead.nl/serverside">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Title will be filed by the View depending on the Controller</title>
<link rel="stylesheet" type="text/css" href="/Stylesheet/Get/Main/" />
</head>
<body>
<!-- the entire body may be reset by the view using it, using XPath and DOM functions -->
<!-- Usually the PageHeader and PageFooter would be put back after clearing the body -->
<div id="PageHeader">
<img src="/Image/Get/theredhead_dot_nl.png" alt="Site Logo" />
</div>
<h1>www.theredhead.nl :: Test Template</h1>
<p>
Lorum ipsum dolar sit amet. blah blah blah yackadee schmackadee.
</p>
<div id="PageFooter">
Built by
<br />
<red:UserProfileLink runat="server" Username="kris" />
</div>
</body>
</html>
At current, this outputs (including the broken indentation):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:red="http://www.theredhead.nl/serverside">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Welcome to my site</title>
<link rel="stylesheet" type="text/css" href="/Stylesheet/Get/Main/"/>
<link rel="stylesheet" type="text/css" href="/Stylesheet/Get/Custom/"/>
<link rel="stylesheet" type="text/css" href="/Stylesheet/Get/Profile/"/>
</head>
<body>
<!-- the entire body may be reset by the view using it, using XPath and DOM functions -->
<!-- Usually the PageHeader and PageFooter would be put back after clearing the body -->
<div id="PageHeader">
<img src="/Image/Get/theredhead_dot_nl.png" alt="Site Logo"/>
</div>
<h1>www.theredhead.nl :: ModelViewController</h1>
<p>
Lorum ipsum dolar sit amet. blah blah blah yackadee schmackadee.
</p>
<div id="PageFooter">
Built by
<br/>
<div><div xmlns:profile="http://www.theredhead.nl/profile" class="ProfileBadge" style="font-size : .8em;">
<a style="text-decoration : none; border: none;" href="/Profile/View/kris">
<img style="float : left;" src="http://www.gravatar.com/avatar/5beeab66d6fe021cbd4daa041330cc86?d=identicon&s=32&r=pg" alt="Gravatar"/>
 Kris
</a>
<br/>
<small>
 Rep: 1
</small>
</div></div>
</div>
</body>
</html>
I've only touched on the tip of the iceberg here and yes, I will be stripping unused xmlns attributes from the output once I'm happy with the functionality
there are currently just over 200 classes in my mvc and core frameworks
I am aware there are existing solutions that can do similar things, but I want to build my own.
So the big question is: Do you have any input on must-have functionality?
P.S. if anyone is interested in the complete source-code, please leave a comment, I will be providing it on my site when I reach reasonable developer usability levels.

Why not just use PHP as your templating system. PHP IS the template system.
What is wrong with just dumping <?php=$variable;?> in an HTML template? You can use foreach loops, etc.
Just make sure that you run it from within a scope that cannot access any variables you do not want.
I have a really deep founded hate for overcomplicated template systems like this since my Java/Struts nightmares. You have to dive into namespaces, xpath, custom namespaces and all that stuff before you can change just the one thing you need.

Here's an article on templating engines: http://massassi.com/php/articles/template_engines/
You're doing it wrong.

Seems to me only Phil Reif actually read and understood the question and its intention.
Those people claiming php is the template engine and that's that are ignoring too many facts and have blinded themselves from the real world where solid frameworks are important.
So, the points must have features so far (that haven't already been implemented) are:
Lists. I'll be handling those in controls similar to <asp:DataGrid>
Validation. Will be handled with validation controls. Regular expressions, comparisons etc.
Output is forcibly valid xhtml 1.0, at least until html 5 has sinked in.
Composite custom controls (based on xml templates instead of code)
inline php code... I'm considering it, <?php ... ?> is a valid xml DOMProcessingInstruction node, but the judges are undecided.
Configurable global exception handling.
I've set the first drafts online so you might take a look and maybe get back to me with some neat ideas.
By the way things look i'll have forms up and running in the next couple days. At the moment it's only a first draft of a design (both code and style wise)
Still hoping for some more input here, what kind of controls do you people use and love? (from any framework/language)
Kris

Related

Is it a good practice to store head tag information in a separate file and later include it?

<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="css/style.css"/>
<link rel="stylesheet" type="text/css" href="css/homepage.css"/>
<link rel="stylesheet" type="text/css" href="css/header.css"/>
<link rel="stylesheet" type="text/css" href="css/footer.css"/>
<link rel="stylesheet" type="text/css" href="css/navmenu.css"/>
<!-- more css here -->
<script type="text/javascript" src="js/jQuery.js"></script>
<script type="text/javascript" src="js/navmenu.js"></script>
<!-- more js here -->
</head>
i have all of that external css and javascripts inside the <head></head> tag in all of my pages and all of that are important in all pages.. is it appropriate to put all of that in a separate file and just include that using php? so if i want to make some changes on those externals it would be easy for me, because it will affect all my pages.. i just want to know if it is a good practice.. thanks in advance
Yes, it is. But why stop there? Ideally you should have all of your repetitive markup in a single file.
There are numerous approaches to sharing common markup in PHP, but the simplest way is to have a global "Top.php" and "Bottom.php" files, like so:
In Top.php:
<html>
<head>
<title><?php echo $pagetitle; ?></title>
<!-- your <meta /> elements go here -->
</head>
<body>
<!-- common page elements go here -->
In Bottom.php:
</body>
</html> <!-- This ensures all of the common markup is closed -->
Then for each page, do this:
<?php $pageTitle = "This page's title";
require("Top.php"); ?>
<!-- put your per-page markup and PHP code here -->
<?php require("Bottom.php"); ?>
Simples.
Now how I use require() instead of include(). The require function is more strict and basically ensures that the included files exist. I think it's better for an application to visibly break than to fail silently.
Save your snippets to separate files and then include() them.
And yes, it is a good practice, but much better is to use some decent templating system.
Look at Latte templating system from Nette Framework
Sure It is good practice. Put this in a separate PHP script ie head.php then include in all other pages using
<?php include('head.php'); ?>
To answer your question straight forwardly.
YES! It is a good practice.
A good programmer will not re-code everything at every page (one of the necessity lead to the invention of CLASS). So. Carry on! :)
Yes, it's appropriate to pull common data like that into separate files. The question really is, now that it's in a separate file, what do you do with it?
You have at least four options.
server-side (host-based) include files
php include statement
php require or require_once statement
make
Server-side includes are generally believed to hurt performance, especially on low-cost (oversold?) shared web hosting servers. There are other issues.
The include and the require statements in php differ mainly in how they respond to missing files. The include statement produces a warning; require produces a fatal error.
The make utility is less commonly used, but it's very useful. Using make, you can include any file within another file, producing output that has static content when it makes sense to have static content, and dynamic content when it makes sense to have dynamic content.
For information like you're talking about, you could use make to produce files in which the stylesheets and javascript references are static (so there's no performance hit), with all the maintainability of a single source file. A properly built makefile guarantees that any change to the stylesheet/javascript file will be incorporated in the next build.
Other text utilities can do some of the same things, especially if you're only talking about file inclusion. (m4, for example.)

How do You Call Header.html/Footer.html in a Web Page?

I've been making a website with about 25 pages and every time I want to update the nav bar, or the footer, I have to go through every page and make the change!
Surely there is a way to have the header and the footer (and the side bar!) in separate documents and call them in the same way a CSS is called so they don't have to be repeated on every page.
Bonus: Is this likely to affect SEO in any way? Might it slow down the site?
Thank you,
Tara
by using include():
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Your page</title>
<style type="text/css">
<!--Your styles ect that make your page-->
</style></head>
<body>
<div class="container">
<div class="header"><?php include('./site_content/header.html');?></div>
<div class="sidebar"><?php include('./site_content/sidebar.html');?></div>
<div class="content">
your content
</div>
<div class="footer"><?php include('./site_content/footer.html');?></div>
</div>
</body>
</html>
HTML itself - ignoring framesets and iframes which do have an effect on SEO and are generally not really recommended - does not have any method to include partial HTML.
You can however use PHP (or SSI if you're oldskool) for such. It has a command to include partial files, it's called include PHP Manual.
PHP needs to be activated on your server for it. To keep this transparent you might want to map the .html file extension to PHP or use Mod_Rewrite to do that. That depends on the type of server and it's configuration.
Might it slow down the site?
The server has more work to do to process the request, therefore it slows down the site a little bit. But normally for a simple site you won't notice that much.
To prevent such, it's possible to build a simple caching mechanism on top that will convert the dynamic PHP output into static files on the fly.

Is it a bad practice to create a template language that is not valid HTML nor PHP (Stacy CMS)?

This is the template language of Stacy (a super light HTML/PHP CMS that doesn't use database)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>#title, #name's Portfolio </title>
<link rel="alternate" type="application/atom+xml" href="#root_path/?/feed/">
<link rel="stylesheet" href="#root_path/public/docs/css/screen.css" type="text/css" media="screen">
</head>
<body>
<div id="container">
<h1 class="col three">
#name
<strong>#profession</strong>
</h1>
<em class="col three">#email</em>
<hr>
:navigation
<div id="content" class="col eight">
<p class="date col one">#date</p>
<div class="description col six">
<h2 class="col six">#title</h2>
#content
</div>
<hr>
<p id="project-count" class="col one"><em>№</em> #index/#siblings_count</p>
<p id="gallery-count" class="col one">
<em>№</em> <span>1/1</span>
</p>
<div id="gallery-navigation" class="col three">
<p>Next image <em>→</em></p>
<p>Previous image <em>←</em></p>
</div>
<div class="col four">
if $siblings do
:next-page
:previous-page
endif
</div>
:media
</div>
I wonder if those # and : would produce some sort of problems? Is it a bad practice since is not valid HTML nor PHP?
Is it a bad practice since is not valid HTML nor PHP?
As long as the end result the template engine generates is valid HTML, there is no fundamental problem with this. The template itself will never be shown to the end user, just the result.
However, this kind of syntax will break a HTML IDE's highlighting, or may cause problems when editing the template file with a WYSIWYG editor. If you do a lot of that (or have a non-programming person edit the templates), you may be better off looking for an engine that has a HTML compatible template format (although I can't think of one off the top of my head.)
This is definitely the way most template engines operate.
If it displays as valid HTML to the end user, it should be fine.
This looks like a template file, those : and # will be replaced with content from the CMS.
This actually isn't invalid markup, it's just not doing what you'd expect.
Arguably having a templating system that doesn't look like HTML or PHP is a good thing – you are less likely to accidentally forget to parse it, or accidentally parse it twice.
the point is is that those '#''s are variables that get replaced with valid content on the server side by your application before your web server ever serves it. That means when a browser queries the web server it gets back the page with the appropriate content plugged in where the '#''s were and it never sees the '#''s
if you want to see that in action just compare the page template in your app's source with the page source code in your browser

"echo" in functions or "echo" all page?

Is this a good method to save to all index in a variable and then echo this? for example
<?php
$txt='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-9" />
<link rel="stylesheet" type="text/css" href="css/style.css"/>
<title>Untitled Document</title>
</head>
<body>
<div class="wrapper">
<div class="header">
<h2>'.heaf_func().'</h2>
</div>
<div class="content">content</div>
<div class="footer">footer</div>
</div>
</body>
</html>';
echo $txt;
?>
I'd personally change your example to be like this;
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-9" />
<link rel="stylesheet" type="text/css" href="css/style.css"/>
<title>Untitled Document</title>
</head>
<body>
<div class="wrapper">
<div class="header">
<h2><?php echo heaf_func(); ?></h2>
</div>
<div class="content">content</div>
<div class="footer">footer</div>
</div>
</body>
</html>
Generally, no. If you need to do output buffering, just use the output buffering API. Even if you need to retrieve your output to do post-processing on it, you can do that using ob_get_contents. It won't be a big deal on most pages, but on large pages or under heavy server load you should use the output buffering support because it's better optimized for what you're trying to accomplish.
Generally, when looking at a method such as what you're contemplating, ask yourself "what does this gain me?" Your example above is clearly trivial, but unless you're planning on post-processing your results, what does it gain you?
EDIT:
I've used both the PHP-in-XML and XML-in-PHP approaches in various projects. My experience is that on a project of any significant size the PHP-in-XML (or HTML, but I try to always generate XML or XHTML) eventually turns into nasty spaghetti code that becomes a pain to maintain, whereas the XML-in-PHP approach eventually balloons into a mess of string-manipulation code that you also don't want to maintain.
Generally, I'd recommend going with an MVC (MVVM, MVP, etc. - up to you) framework for every web app, regardless of language. If applied correctly, the additionally framework complexity is more than compensated by the modularity and ease of maintenance and extensibility that you gain. If you don't feel the need or desire to target a framework (though, again, I STRONGLY recommend it), I typically follow these rules:
Whenever possible, limit PHP-in-XML to simple inclusion of values. E.g., <h1><?php echo $title; ?></h1> Try to avoid including logic in your spaghetti code (other than, perhaps, repetition, though I typically abstract that away, too).
Whenever possible, create XML documents using the XML API's instead of writing raw values to the output. XML has the advantage of being easily transformable, which in my experience is well worth the extra initial investment, at least in production apps.
Send the client an XML document representing your data with an xml-stylesheet processing instruction indicating the location of a stylesheet to apply for rendering and let the client do its own rendering. Failing that, put your data-to-presentation transformation logic in a stylesheet (XSLT, not CSS) and do the transformation server-side. I really enjoy the separation between data and presentation it allows me.
The question is why you want to do this. Just putting it in a variable and then echoing it isn't worth it but if you need to work on the string further (string replacement, etc.) it is useful.
If you're going to be doing massive multi-line text-into-variable assignments like that, consider using the HEREDOC syntax, which has the advantage of not forcing to you escape quotes, which makes the text blob far easier to read and cut/paste into other things without needing tweaks.
As for choosing if you should do PHP-in-HTML or HTML-in-PHP, it all comes down to which one would be more readable. If you have 500 lines of HTML, and only a small bit of PHP to insert, then go for PHP-in-HTML, and vice-versa. For a near even-balance, it'd come to whatever your preference is.

What's the best way to include external content using php includes? (For web developers who love optimal practices)

I've checked lots of tutorials about including header, navigation and footer using php "include". But I ended up separating my html tags. For instance, my <div id="content"> is in "header.html" while it closing </div> tag is in the footer. This gives me some problem when I use jQuery and looks kinda messy. Is there a better practice to generate external content? (is jQuery the solution?)
index.php
<?php include("header.html"); ?>
<?php include("navigation.html"); ?>
<div id="content">
<h2 class="clear">This is the contact page</h2>
<p>
Main content here... Main content here... Main content here... Main content here...
Main content here... Main content here... Main content here... Main content here...
Main content here... Main content here... Main content here... Main content here...
Main content here... Main content here... Main content here... Main content here...
Main content here... Main content here... Main content here... Main content here...
Main content here... Main content here... Main content here... Main content here...
</p>
</div>
<?php include("footer.html"); ?>
header.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Study at Best</title>
<script type="text/javascript" src="scripts/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="scripts/jquery.corner.js"></script>
<script type="text/javascript" src="scripts/jquery.dropshadow.js"></script>
<script type="text/javascript" src="scripts/jqueryScripts.js"></script>
<link rel="stylesheet" rev="stylesheet" href="styles/layout.css" />
<link rel="stylesheet" rev="stylesheet" href="styles/ddm.css" />
</head>
<body>
<div id="container">
<div id="header">
This is the header
</div>
footer.html
<div id="footer">
<p>BEST School © Copyright 2009</p>
</div>
</div>
</body>
</html>
What problem is this causing? This is a fairly standard practice (I use it), and I've never known it to create any problems. jQuery shouldn't be an issue, since no jQuery code is ran until all of the html has been joined together anyway.
Shouldn't be causing any problems.
Personally, If navigation was simple, i'd put it inside header, and if not, i'd dynamically generate it via PHP and put it in a class, and include that class in the header.
I do not see a problem with this. I have used this technique many times before. For me it keeps everything well organized. And like Jonathan Sampson said, there should not be any issue with jQuery.
In my personal opinion this doesn't look right. I mean simply don't do this to yourself. It will be a nightmare if the site becomes more complex. What about only putting the footer div in footer.html the same for header.html? The rest belongs in index.php. If index.php becomes to complex, split it up more (javascript.html..). – merkuro Jun 20 at 21:22
Hm, ok, not sure if this is better way of doing it, but what I tend to do is to have a template file that contains both the header, the footer, the menus, left side, right side, whatever else is not specific to just one page, including all the js includes and such.
And then the index.php would simply have a content variable in which all the index content goes. At the end of index i then require the template file which places the "content" variable inside where it belongs and tada, all your headaches are over.

Categories