You are here: Re: Separation of logic, design and data « PHP Programming Language « IT news, forums, messages
Re: Separation of logic, design and data

Posted by Toby Inkster on 01/23/07 18:50

Frank van Wensveen wrote:

> I believe that in a perfect world the design of a website (or feature
> on a website) should be totally separated from its design and the data
> it serves up. I'd like some suggestions on good ways to do this,
> because in the real world it can be quite difficult.

Keeping styling separate from the rest is smiple (sic): just do all your
layout, colour schemes, etc with CSS.

After that you've still got the problem of the fact that your code has to
do things in the correct order to output the page -- say, output HTML
header stuff first, then body stuff, then sidebar stuff, and finish with
some legalese and footer stuff. This can be solved using a template
engine. There are several available, though I can't say I like any of
them, I generally write my own template engine using the interface pasted
below. (Infact, I've only recently coded it as a proper PHP Interface,
earlier I used a standard class, which I would extend one or two methods
of.

This interface allows you to use (note the seemingly random order):

$t = new StdTemplate('Foo Bar');
$t->add_section('Foo', '<p>Foo</p>', 'foo',
StdTemplate::DIVISION_MAIN, 2);
$t->add_section('Bar', '<p>Bar</p>', 'bar',
StdTemplate::DIVISION_EXTRA, 3);
$t->add_section('Foo Bar', '<p>The life of Foo Bar</p>', 'foobar',
StdTemplate::DIVISION_HEAD, 1);
$t->add_script('/js/prototype.js');
$t->add_meta('Author', 'Me', FALSE, array());
$t->add_filter(new SpellCheckFilter(),
StdTemplate::DIVISION_MAIN | StdTemplate::DIVISION_EXTRA);
$t->add_section('Baz', '<p>Baz</p>', 'baz',
StdTemplate::DIVISION_EXTRA, 3);
$t->output();

which might output this:

<html>
<head>
<title>Foo Bar</title>
<meta name="Author" content="Me">
<script type="text/javascript" src="/js/prototype.js"></script>
</head>
<body>
<div id="head">
<div class="section" id="foobar">
<h1>Foo Bar</h1>
<p>The life of Foo Bar</p>
</div>
</div>
<div id="main">
<div class="section" id="foo">
<h2>Foo</h2>
<p><span class="spelling" title="Fool?">Foo</span></p>
</div>
</div>
<div id="extra">
<div class="section" id="bar">
<h3>Bar</h3>
<p>Bar</p>
</div>
<div class="section" id="baz">
<h3>Baz</h3>
<p><span class="spelling" title="Bat?">Baz</span></p>
</div>
</div>
<div id="foot">
</div>
</body>
</html>

Anyway, interface follows. Implement this interface and you'll be
happy. :-)

<?php

/**
* @author Toby Inkster <demiblog@tobyinkster.co.uk>
* @copyright Copyright &copy; 2007, Toby Inkster
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public Licence
* @version 1.0
*/

/**
* The Template interface is a standard interface that you must implement
* if you would like to create a new template for Demiblog. In addition,
* your template class must define the following constants. (PHP does not
* allow constants to be defined within a template.)
*
* DIVISION_HEAD = 1
* DIVISION_MAIN = 2
* DIVISION_EXTRA = 4
* DIVISION_FOOT = 8
* (You may define up to four custom divisions with values 16, 32, 64
* and 128.)
* FULL_HTML = -1
*
* The StdTemplate class supplied with DemiBlog outputs a page with roughly
* the following structure (it may vary, depending on HTML flavour):
*
* <!DOCTYPE ...>
* <html>
* <head>
* <title>...</title>
* <meta ... /><!-- etc -->
* <link ... /><!-- etc -->
* <script src="..."></script><!-- etc -->
* </head>
* <body>
* <div id="page">
* <div id="head">##</div>
* <div id="body"><div id="main">##</div><div id="extra">##</div></div>
* <div id="foot">##</div>
* </div>
* </body>
* </html>
*
* where locations marked with a double-hash (##) can be filled with zero or
* more content panels. This structure should be adequate for expressing most
* site layouts and should provide enough id and class hooks to hang most CSS
* designs onto.
*
* In the case where it does not prove sufficient, you have two options:
*
* 1. Keep the existing StdTemplate, but write a filter to modify its
* output (using, for example, regular expressions). The filter
* can be attached to the existing template using its add_filter()
* method.
*
* 2. Write a new template class, implementing the Template interface.
* Use the existing StdTemplate as a guide -- simply extending the
* existing template is probably sufficient. You will probably want
* to modify the output() method.
*/
interface Template
{
/**
* Add a section to the template with a particular ID and Title. Add
* it to a particular division or divisions.
* @param string $title Title of section.
* @param string $body Body of section. This should be in the correct
* flavour of HTML. The template will not attempt to rewrite it.
* @param string $id HTML ID of section. The template will protect
* against multiple sections with the same ID.
* @param int $to_division Division(s) to add to.
* @return bool Success.
*/
public function add_section ($title, $body, $id, $to_division, $heading_level);

/**
* Filter for sections. An object with interface TemplateFilter must
* be supplied. Filters are not applied until $this->output() is called.
* @param Object $object Filter object.
* @return bool Success.
*/
public function add_filter (TemplateFilter $object);

/**
* Adds a META element to the template's document HEAD.
* @param string $name META name.
* @param string $content META content.
* @param bool $is_http_equiv Replace "name" attribute with "http-equiv".
* @param Array $more_attributes Extra attributes for META element.
* @return bool Success.
*/
public function add_meta ($name, $content, $is_http_equiv, $more_attributes);

/**
* Adds a LINK element to the template's document HEAD.
* @param string $rel LINK relationship.
* @param string $href LINK destination.
* @param string $type LINK MIME Type.
* @param Array $more_attributes Extra attributes for META element.
* @return bool Success.
*/
public function add_link ($rel, $href, $type, $more_attributes);

/**
* Adds a SCRIPT element to the template's document HEAD.
* @param string $src Script file.
* @return bool Success.
*/
public function add_script ($src);

/**
* @return bool HTML Flavour.
*/
public function get_flavour ();

/**
* @return string Finished page.
*/
public function output ();
}

/**
* The TemplateFilter interface is an interface for defining filters that
* act on templates and may modify their output. Filters can apply to the
* whole finished page, or just to specific sections within it. Examples of
* uses for filters:
*
* - Gzip finished pages.
* - Highlight search terms.
* - Expand abbreviations.
* - Remove/replace deprecated markup.
*
* The list is endless. (Well, obviously not the list above, as that has only
* four items, and certainly ends. But possible applications for output filters
* are infinite.)
*/
interface TemplateFilter
{
/**
* Determines suitability of this filter to a section, based on
* section position and ID.
* @param int $to_division Section position.
* @param string $to_division Section position.
*/
public function should_apply ($to_division, $id);

/**
* @param string $title Title to be filtered.
* @param string $body Body to be filtered.
* @return Array array(filtered title, filtered body)
*/
public function apply ($title, $body);
}

?>


--
Toby A Inkster BSc (Hons) ARCS
Contact Me ~ http://tobyinkster.co.uk/contact

 

Navigation:

[Reply to this message]


Удаленная работа для программистов  •  Как заработать на Google AdSense  •  England, UK  •  статьи на английском  •  PHP MySQL CMS Apache Oscommerce  •  Online Business Knowledge Base  •  DVD MP3 AVI MP4 players codecs conversion help
Home  •  Search  •  Site Map  •  Set as Homepage  •  Add to Favourites

Copyright © 2005-2006 Powered by Custom PHP Programming

Сайт изготовлен в Студии Валентина Петручека
изготовление и поддержка веб-сайтов, разработка программного обеспечения, поисковая оптимизация