Creating html templates using PHP - php

Im learning a lot about how MVC frameworks work by looking around and studying existing ones. It seems that every framework I see has a layout where each method in each controller has its own template file. So there will be a login template, a logout template, register, so on and so on.
My question is, how and why would you create a template for the entire page all within one file. Lets say you wanted to show the login form on more than one page, wouldn't you have to create the login form for each template that you want it to display on? Doesn't that go against the don't repeat yourself rule (DRY)?
The way i've been doing things so far is I've been creating liitle chunks of templates and then combining them to create each page. So instead of doing something like this,
$title = 'Blah Blah Blah';
$user = 'Jon Miller';
include 'index.phtml';
<html>
<head>
<title><?php echo $title; ?></title>
</head>
<body>
<h3><?php echo $user; ?></h3>
<form>login form</form>
</body>
</html>
I've been doing this
$title = 'Blah Blah Blah';
include 'header.phtml';
$user = 'Jon Miller';
include 'user.phtml';
include 'login_form.phtml';
include 'footer.phtml';
header.phtml
<html>
<head>
<title><?php echo $title; ?></title>
</head>
<body>
user.phtml
<h3><?php echo $user; ?></h3>
login_form.phtml
<form>login form</form>
footer.phtml
</body>
</html>
As alway, I would just like to know the proper way to do it, along with how and why...It just seems to go against the DRY rule.
Thanks

You should check out the concepts of 'layouts' and 'view helpers'. While I've linked to the Zend Framework version of those concepts, other MVC frameworks (and the MVC concept) should have them as well.
The basic idea is that your page 'view' - for example the login form - is included into your site 'layout' - the general template that is used throughout your site. When you request a different controller, with a different view - for example a user profile - that view is also included in the same layout.
To include something like a login form on all pages, a view helper can be used. That view helper could display the current user, or display a login form, depending on the login status. View helpers may be included in the layout, or included by the specific controller (as long as MVC framework allows some kind of named render segments).
The two step 'include' method works better than linear inclusion of parts (including header, then content, then footer - what you're doing now) because your templates do not have to split HTML tags. The Zend Guide has a good visual example of view templates in a layout.

One word: Organization. Separating each part of the page will allow each of them to be viewed/edited separately. This simple concept is very beneficial. For example, anyone in the team that want to handle login process can easily figure out that they have to edit login_form.phtml and they can be sure that editing login_form.phtml will less likely to unintentionally interfere with other functionalities.
As of the best practice, here is how I do it (not exactly but similar).
$Title = 'Blah Blah Blah';
$User = 'Jon Miller';
$ThemeName = "MyGreenPage";
$Contents = array("User", "Login_Form");
function Include($FileName) {
if (file_exists($FileName))
include $FileName;
}
MyGreenPage.phtml:
<html>
<head>
<title><?php echo $title; ?></title>
<?php
foreach($Contents as $Content)
Include("$Content.pcss");
?>
<?php
foreach($Contents as $Content)
Include("$Content.pjs");
?>
</head>
<body>
<?php
foreach($Contents as $Content)
Include("$Content.phtml");
?>
</body>
</html>
User.pcss:
/* Some styles needed by User */
User.pjs:
/* Some script needed by User */
User.phtml:
<h3><?php echo $user; ?></h3>
Login_Form.pcss:
/* Some styles needed by Login_Form */
Login_Form.pjs:
/* Some script needed by Login_Form */
Login_Form.phtml:
<form>login form</form>
Let me remind you again that this is not that exactly what I do (what I do use OOP) so this may not exactly run as is and you may need to edit it.

The most common way to do HTML templating with PHP, is to use one of these popular templating engines :
Smarty
Twig
Latte
Mustache
Alternatively, you can just put placeholders in your HTML that look something like <% variablename %>. Just load your HTML, do a regex do find all placeholders and replace them with the corresponding variables.
Alternatively, you can load your HTML, parse it as a DOM document and then modify your DOM. I created the library DOM Query to be able to do this with a jQuery-like syntax, but you could use vanilla PHP or one of several other libraries as well.
Alternatively, you can do some HTML templating in frontend with JavaScript. If you want to do HTML templating both on frontend and backend, you might want to consider using Mustache, because Mustache templates can be used both in frontend (with JavaScript) and in backend (with PHP).

For this project I am working on, all views are XSL templates. Instead of passing variables to the view, I generate all the XML in the controller and transform it with the view.
I like this structure because I can keep all my templates in one file, and arrange them anyway I want. It's also a standard template language which is very flexible and has tons of documentation. This has been working out really well so far.
A really good example of this structure is the WoW Armory website (view the source).

Related

Codeigniter - Templating with separate templates

I wish to have a codeigniter application with 3 templates.
a template for displaying a login view, or an error view.
a template with header body navigation
a template with header body sidebar footer
now I can build the codeigniter application, but I can't find a simple template system to accomplish this task. There are many recommendations for libraries available, but they lack implementation details.
Suggestions and guidance would be appreciated.
You can user CodeIgniter Template.
http://williamsconcepts.com/ci/codeigniter/libraries/template/index.html
Download here the library and also you have a full documentation.
With this library, you can use more than one template, and you can manage it easy and separate in groups.
It's quite simple once you get your head around it.
You need to create a view file for each of the things you've listed above, so you'll want something like this (folder/file wise):
views/page-login.php
views/page-error.php
views/header.php
views/footer.php
Then from your controller you will load one of the page views.
Within the page view you can then load the elements you require, so header and footer with the page specific code between them.
So for example your login page could be:
<?php $this->load->view('header'); ?>
<h1>Login</h1>
<p>Please login to my website.</p>
<?php $this->load->view('footer'); ?>
This is fairly simple.
A quick example:
In your controller you can put
//a test variable
$data["foo"] = 'bar';
$data["page"] = 'a_page'; // this will make sure it loads the views/pages/a_page.php in your template
$this->load->view('templates/login',$data);
And in your views/template/login.php you can put:
<!-- your login template html -->
<html>
...
<!-- include the view you want inside your login template -->
<?php $this->load->view('pages/'.$page);?><!-- As you can see it loads /views/pages/a_page.php -->
<?php echo $foo;?> //This will echo Bar
</html>
or:
<?php $this->load->view('template/login_header');?>
<?php $this->load->view('pages/'.$page);?>
<?php $this->load->view('template/login_footer');?>
views/pages/a_page.php will also know $foo.
This loads another view (views/pages/a_page.php) in your template.
This way you can create all the templates you want, and include your view in those templates.
TIP: Handling headers & footers this way get's unmanageable pretty quickly. And it's still better to use template libraries. Try Phil sturgeon's library

Do search engines have trouble with urls like somesite.com/index.php?page=photos

I'm new to php coding, web development, and search optimization - so newbie overall. In the process of learning php and web development I've been trying out different website architectures and layouts. One I'm working on uses an approach like the following:
I have one index.php page which always loads a header.php, sidebar.php, and footer.php. The index.php also contains a switch so that depending on the page variable the index.php is passed it loads different core content. So for example a examplesite.com/index.php?page=photos and examplesite.com/index.php?page=stories would both have the same header, footer, and side bar but one would have photos and one would have stories as the main content.
<?php $page = $_GET['page'];?>
<?php include("header.php"); ?>
<?php include("nav.php"); ?>
<?php
switch ($page)
{
case 'play':
include("photos.php");
break;
case 'cards':
include("stories.php");
break;
default:
include("frontpage.php");
}
?>
<?php include("footer.php"); ?>
My navigation is made up of href="index.php?page=..." links so choosing a menu button on the index page essentially calls itself passing it the new core to load.
I have no idea if this is a totally unorthodox approach but it all started because I was initially going to create a wordpress theme but then halfway through decided not to do it in wordpress.
What i'm concerned about are what drawbacks could be associated with this approach when it comes to search engines, indexing, seo etc.
What are other drawbacks or issues I should be thinking about that maybe I'm not?
Thanks in Advance!
I have no idea if this is a totally unorthodox approach
There is nothing essentially "unorthodox" in using a query string to load various pages. Billions of sites using this approach. Search engines can index such pages all right.
Nevertheless,
I have one index.php page which always loads a header.php, sidebar.php, and footer.php.
This is wrong concept.
Having an index.php file only to load header and footer makes no sense and makes your site plainly unusable.
Here are main faults in your design:
You're assuming that header.php would be called with the every page call. That's wrong.
You're assuming that header.php will always be static. That's wrong.
You forgot to create a template for the page itself.
The main rule everyone have to learn by heart:
Not a single character has to be sent into browser, until all data gets ready.
Why?
it's 2012 today. AJAX era. What if your code will have to send JSONed data instead of whole HTML page?
there is a thing called HTTP header. Sometimes we have to send them. And it's gets impossible if you already have your ornate HTML header sent.
Separating display logic from the business logic will let you use the same php code on many sites. You will have to change only templates and don't touch engine files. That's really great benefit.
Imagine you're going to make a custom <title> tag for your pages, based on the page content. Isn't it extremely common thing? But you can't make it without using templates.
So, you have to have one common site template containing header and footer and also dedicated templates for the every php script.
And these templates have to be called only when all business logic is done - i.e. you have got all your data ready.
An example layout is going to be like this:
.1. page itself.
it outputs nothing but only gathers required data and then calls a template:
<?
//include our settings, connect to database etc.
include dirname($_SERVER['DOCUMENT_ROOT']).'/cfg/settings.php';
//getting required data
$DATA=dbgetarr("SELECT * FROM links");
$pagetitle = "Links to friend sites";
//etc
//and then call a template:
$tpl = "links.tpl.php";
include "template.php";
?>
.2. template.php which is your main site template,
consists of your header and footer:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My site. <?=$pagetitle?></title>
</head>
<body>
<div id="page">
<? include $tpl ?>
</div>
</body>
</html>
.3. and finally links.tpl.php is the actual page template:
<h2><?=$pagetitle?></h2>
<ul>
<? foreach($DATA as $row): ?>
<li><?=$row['name']?></li>
<? endforeach ?>
<ul>
this way you'd need no index with includes at all

Converting a site from a PHP site into a full LemonStand e-commerce site

Brand new to LemonStand, and it's my front-runner for developing a client's web site.
This first candidate for utilizing LemonStand is a newly built web site I built in PHP.
I've got all of the non-e-commerce pages (things like about and contact) pulling from the LemonStand CMS.
But now I am trying to convert what were simple PHP includes to partials:.
Example:
<? include 'standard_include.php'; ?>
<? include 'header.php'; ?>
to LemonStand's
<? $this->render_partial('standard_include') ?>
<? $this->render_partial('header') ?>
I get an unhandled exception related to undefined variables:
This is what the beginning my page/template looks like
<?php
require_once('lib/php/configuration.php');
$pagetype = 'home';
$subpagetype = 'index';
$titleValue = 'Client Name';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<title><?php echo $titleValue ?></title>
<? $this->render_partial('standard_include') ?>
</head>
<body>
<? $this->render_partial('header') ?>
Do the partials not render till later in the page load process (as compared to PHP includes)?
Am I utilizing partials incorrectly? If so, what do I do to put the PHP includes into the LemonStand backdoor system?
I've never used Lemonstand, but if its MVC works like other MVC systems, then you need to inject the variables needed by standard_include into the view. Something like:
$this->renderPartial('standard_include', array('pagetype'=>$pagetype, ...)) ?>
Otherwise the partial won't have access to the variables you defined in your parent template because the partial is rendered in a different context.
PHP include works differently. It just literally inserts the included file in place at that point before the script is executed.
I'm thinking the render_partial is happening after the pages start rendering, while the include happens prior, so it has a value for pagetype.
I'm thinking the solution is going to be to keep them includes. I just won't be able to have every file in their admin/backend system.
For common elements, the included templates with LemonStand don't seem to do anything but have them inline, which obviously isn't optimal for making a change across a site for something like a header or footer.

Creating a custom PHP template

I created a custom PHP templating system and the way I built it seems, well, inefficient. The three main goals for my template was to:
Pull all site-wide HTML elements from a template.tpl include.
Be able to dynamically assign content in the template.tpl (like <title> or <script>)
Be as efficient and scalable as possible.
In the end, my template system looked something like this:
randomPage.php
<?php
// declare any page specific resources
$pageTitle = "Random Sub-Title";
$pageResources = "/css/someRandomCSS.css"
$pageContent = "/randomPage.tpl"
// include the generic page template
include dirname($_SERVER['DOCUMENT_ROOT']).'/includes/template.tpl'
?>
randomPage.tpl
<h1><?=$pageTitle?></h1>
<p>Some random page's content</p>
template.tpl
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Site -- <?=$pageTitle?></title>
<link href="/css/styles.css" rel="stylesheet" type="text/css">
<link href="<?=pageResources?>" rel="stylesheet" type="text/css">
</head>
<body>
<? include $pageContent ?>
</body>
</html>
The main problem with this system is that for every web page, I need to manage two files: one for logic/data and the other for the page template. This seems largely inefficient to me, and doesn't seem like a very scalable approach.
Recently, I come across the smarty framework, which would allow me to consolidate my system from randomPage.php and randomPage.tpl into something like:
randomSmartyPage.php
{extends file="template.tpl"}
{block name=pageTitle}My Page Title{/block}
{block name=pageResources}
<link href="/css/someRandomCSS.css" rel="stylesheet" text="text/css">
{/block}
{block name=pageContent}My HTML Page Body goes here{/block}
Seeing this approach raised three major questions for me:
Are there any fundamental flaws with how I am approaching my templating system?
Can my original php code be refactored so I don't have to create two files for every web page?
Would using the smarty (or perhaps an alternative framework) be a good idea in this case?
Your code isn't really using any templating engine besides PHP itself, which is fine. A flaw I can see is your template will have access to all variables, and the ones you create for it are all global.
Two files is a good system, one to change what is preprocessed and passed to the view, and one for the view itself, containing HTML or whatever. This allows you to easily swap views, for example, a view for standard browsing and a mobile view for mobile browsers.
It can be a good idea, but I'm a firm believer that using PHP is good enough.
Here is an example, untested. It will encapsulate all the variables so you don't pollute the global namespace.
index.php
function view($file, $vars) {
ob_start();
extract($vars);
include dirname(__FILE__) . '/views/' . $file . '.php';
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}
echo view('home', array('content' => Home::getContent()));
views/home.php
<h1>Home</h1>
<?php echo $content; ?>
The approach you are describing is part of MVC design pattern. Separating the different aspects of your application.
What you seem to have already understood is that PHP is a templating system in itself as have many others before you.
Take a look at this benchmark for a rough comparison of popular template systems.
Update 2022.08.29
Updated broken links to archived versions.
Note: The answer remains valid if you're trying to learn the language. But for anything serious, consider using a framework.

How is duplicate HTML represented in your codebase, in a non-duplicate way?

Most HTML in a large website is duplicated across pages (the header, footer, navigation menus, etc.). How do you design your code so that all this duplicate HTML is not actually duplicated in your code? For example, if I want to change my navigation links from a <ul> to a <ol>, I'd like to make that change in just one file.
Here's how I've seen one particular codebase handle this problem. The code for every page looks like this:
print_top_html();
/* all the code/HTML for this particular page */
print_bottom_html();
But I feel uncomfortable with this approach (partially because opening tags aren't in the same file as their closing tags).
Is there a better way?
I mostly work with PHP sites, but I'd be interested in hearing solutions for other languages (I'm not sure if this question is language-agnostic).
I'm not a php programmer, but I know we can use a templating system called Smarty that it works with templates(views), something like asp.net mvc does with Razor.
look here http://www.smarty.net/
One solution at least in the case of PHP (and other programming languages) is templates. Instead of having two functions like you have above it would instead be a mix of HTML and PHP like this.
<html>
<head>
<title><?php print $page_title ?></title>
<?php print $styles ?>
<?php print $scripts ?>
</head>
<body>
<div id="nav">
<?php print $nav ?>
</div>
<div id="content">
<?php print $content ?>
</div>
</body>
</html>
Each variable within this template would contain HTML that was produced by another template, HTML produced by a function, or also content from a database. There are a number of PHP template engines which operate in more or less this manner.
You create a template for HTML that you would generally use over and over again. Then to use it would be something like this.
<?php
$vars['nav'] = _generate_nav();
$vars['content'] = "This is the page content."
extract($vars); // Extracts variables from an array, see php.net docs
include 'page_template.php'; // Or whatever you want to name your template
It's a pretty flexible way of doing things and one which a lot of frameworks and content management systems use.
Here's a really, really simplified version of a common method.
layout.php
<html>
<body>
<?php echo $content; ?>
</body>
</html>
Then
whatever_page.php
<?php
$content = "Hello World";
include( 'layout.php' );
Sounds like you need to use include() or require()
<?php
include("header.inc.php");
output html code for page
include("footer.inc.php");
?>
The header and footer files can hold all the common HTML for the site.
You asked for how other languages handle this, and I didn't see anything other than PHP, so I encourage you to check out Rails. Rails convention is elegant, and reflects #codeincarnate 's version in PHP.
In the MVC framework, the current view is rendered inside of a controller-specific layout file that encapsulates the current method's corresponding view. It uses a "yield" method to identify a section where view content should be inserted. A common layout file looks like this:
<html>
<head>
<% #stylesheet and js includes %>
<body>
<div id="header">Header content, menus, etc…</div>
<%= yield %>
<div id="footer">Footer content</div>
</body>
</html>
This enables the application to have a different look and feel or different navigation based on the controller. In practice, I haven't used different layout files for each controller, but instead rely on the default layout, which is named "application".
However, let's say you had a company website, with separate controllers for "information", "blog", and "admin". You could then change the navigation for each in a clean and unobtrusive manner by handling the different layout views in their respective layout files that correspond to their controllers.
You can always set a custom layout in the controller method by stating:
render :layout => 'custom_layout'
There are also great helper methods built into Rails so you don't have to rely on $global variables in PHP to ensure your CSS and Javascript paths are correct depending on your development environment (dev, staging, prod…). The most common are:
#looks in public/stylesheets and assumes it's a css file
stylesheet_link_tag "filename_without_extension"
#looks in public/javascripts and assumes it's a js file
javascript_include_tag "jquery"
Of course, each of these sections could be expounded upon in much greater detail and this is just brushing the surface. Check out the following for more detail:
http://guides.rubyonrails.org/layouts_and_rendering.html
What you suggested works OK. As long as print_top_html and print_bottom_html stay in sync (and you can use automated tests to check this), then you never need to worry about them again, leaving you to focus on the real content of the site -- the stuff in the middle.
Alternatively, you can combine print_top_html and print_bottom_html into a single call, and send it HTML code (or a callback) to place in the middle.
I use the partials system of Zend_View (very similar to Rails). A partial is essentially a small HTML template that has its own variable scope. It can be called from inside views like:
<?php echo $this->partial('my_partial.phtml', array( 'var1' => $myvar ));
The variables that get passed into the construct get bound to local variables inside the partial itself. Very handy for re-use.
You can also render a partial from inside normal code, if you're writing a helper object where you have more complex logic than you'd normally feel comfortable putting in a view.
public function helperFunction()
{
// complex logic here
$html = $this->getView()->partial('my_partial.phtml', array('var1' => $myvar ));
return $html;
}
Then in your view
<?php echo $this->myHelper()->helperFunction(); ?>

Categories