Relax...

What if someone told you that there is a simple and powerful tool to quickly develop HTML, XHTML, and XML that works standalone, with Smarty, and with the Zend Framework? Welcome...

Opps, did we mention that it has been used in production since 2006?

But we are not done...there is a new version in testing...it is even cooler...and should be out Q4 of 2009...stay tuned.

pHAML User's Guide

This work is licensed under the Creative Commons Attribution License. To view a copy of this license, visit http://creativecommons.org/licenses/by/2.0/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.

Edition for pHAML .9 Beta

Props: My family, the HAML folks, everybody at Applied Autonomics LLC.


Cheat Sheet

Cheat Sheet

pHAML What it does
%tagname.class1.class2#id{attribute_1="value 1"...} Element Content Create and element and put the content after it
A text line without preceding command Just print as is (according to indent)
\ the line Eat the '\', print the line as is
/ the line Create HTML comment from the line
<<< >>> Print everything between <<< & >>> verbatim
- Wrap what follows in PHP tags
? Turn on/off debug HTML comments
?? Turn on/off rendering as browser viewable HTML
!!! & !!!! Opening doctype elements
Spacing

Indentation is how pHAML determines the tag structure. Elements indented more than the elements above will be contained within the one above. Elements with the same (or less) indentation will cause all elements above with more indentation to close.

Simple HTML Document Simple XML Document
!!!!
%html
  %head
    %title Simple Document
  %body
    %p this is the body, 5 lines=real document
!!! XML
%element_1 
  %element_2 <![CDATA[ Stuff ]]>
%element_3
Debug Hints

Try the following, turn on the debug comments, then show the HTML:

%pre
?
??
%problem_element(s)
...
??
?

Here are some common debug issues, in order of occurence:

  1. Lead Spacing (is your editor using tabs, pHAML assumes they are 4 spaces wide)
  2. Is the command/element syntax correct (as a PHP guy, I have a very quick '$' instead of '%')
  3. Use the debug system, or the pHAML Live tool (the reference implementation).

When in doubt, you can look through the documentation code, since that is all pHAML, or read the source.

If after all that, and you have found an undocumented feature (ok, call it a bug), or have a suggestion, submit it please.

You can test/learn/build all of this code and your code using our pHAML Live testing tool.


Why pHAML?

PHP. Very fast to produce well formed code. Built in templating for simple projects, integrates with Smarty for complex projects. Used in enterprise projects. Easy to learn. Fast to use. Did we say easy and fast?

Try it for a few days...it can save you hours.

Preface

This project is truly a work of accident. While working on an implementation of our Autonomic Services Framework, there was the need to quickly develop a web site. Somewhere in the midst of trying to figure out which table data tag to change the class of, the thought occurred that maybe a new way was needed. HAML ( http://haml.hamptoncatlin.com/ ) showed up. HAML looked like a nice implementation of a �templating� system for HTML and XML. Templating systems are not new, and there are several ways to do them, HAML seemed like a nice approach. The problem was that it was not in PHP, but Ruby�Ruby is nice, but PHP has always stood out as the fastest way to develop applications for web services (and yes, we tried RAILS, but that is still a technical distance from the data warehousing/AI work that we do).

The great thing about open source is that you can view the code, take a look at how others do it. HAML is well written and documented�so it did not take long to get the gist. The first step was to copy in the core code of HAML and rewrite it in PHP, but that approach left a lot of strengths of PHP on the table. So quickly, the approach changed to what you see in this implementation. That was a good thing, since I later found a PHP implementation of HAML. Which in itself was a good thing since I do not like rewriting code, I may have never written this.

The first production level release of the code was written in two days�the core has remained the same, there has been some refactoring, and some added functions. But the entire functionality boils down to around 160 lines of code�which keeps it simple, yet powerful�and that is the combination that creates value.

The name is pun on Pig Latin, and HAML. So this is like HAML, only different--in ways good for PHP and getting code done.

How pHAML is Like HAML

There is no greater fan of the principles behind HAML than pHAML, markup should be beautiful, DRY (don't repeat yourself), well-indented, and the XHTML structure should be clear.

How pHAML is different from HAML

This solution was created to enhance Smarty (it evolved a bit since then). There have been other tweaks to assist in the creation of code. Also, PHP and Ruby share a bit, but are a bit different as well.

Differences from HAML Syntax

This entire document has been produced in pHAML, it is included in the examples, and shows almost all of the functionality.

Using pHAML

Basic Structure

The basic structure of a line of pHAML code is:  %tagname.class1.class2#id{attribute_1="value 1"...} Element Content

Since experience is the best teacher, we are going to use examples.

A Simple Tag

pHAML HTML Result
%tagname
<tagname>
</tagname>

A Tag With a Class

pHAML HTML Result
%tagname.class
<tagname class="class">
</tagname>

A Tag With Two Classes

pHAML HTML Result
%tagname.class.class_two
<tagname class="class class_two">
</tagname>

A Tag With a Class and ID

pHAML HTML Result
%tagname.class#id
<tagname class="class" id="id">
</tagname>

A Tag with Content

pHAML HTML Result
%tagname Some content
<tagname>
Some content
</tagname>

Please note that the content has a space before it.

A Tag with Attributes

pHAML HTML Result
%tagname{att1="v1" att2="v2"}
<tagname att1="v1" att2="v2">
</tagname>

This is a different structure than HAML. pHAML takes everything in brackets and adds it to the tag literally.

Bare Class Creates a DIV Tag with that Class

pHAML HTML Result
.class
<div class="class">
</div>

Bare ID Creates a DIV Tag with that ID

pHAML HTML Result
#id
<div id="id">
</div>

Same for Attributes

pHAML HTML Result
{att1="v1" att2="v2"}
<div att1="v1" att2="v2">
</div>

Mix and Match

pHAML HTML Result
.class1.class2#id{a="1" b="2"}
<div class="class1 class2" id="id" a="1" b="2">
</div>

More Interesting Examples

An Ordered List

pHAML HTML Result
  %ol
    %li Hello
    %li World
<ol>
<li>
Hello
</li>
<li>
World                  
</li>
</ol>

A Table

pHAML HTML Result
  %table.table#t_1{width="100%"}
    %tr
      %td.sam{valign="top" style="color:white;bgcolor:red;"} Data
    %tr
      %td.bob Other Data 
<table class="table" id="t_1" width="100%">
<tr>
<td class="sam" valign="top" style="color:white;bgcolor:red;">
Data
</td>
</tr>
<tr>
<td class="bob">
Other Data 
</td>
</tr>
</table>

That is 12 lines of XHTML for 5 lines of code, better than two to one--and you can read it easily.

Commands and Tools

Kick it Up a Notch

This is where we diverge from HAML. HAML folks may ask themselves "how do I debug", pHAML has a simple answer. PHP folks may ask themselves "where did all the commands go?". This section answers both and more.

Commands

pHAML has a rich set of commands, so let's walk through those.

The "!!!" Command

Like it's HAML progenitor, pHAML provides shortcuts for your coding pleasure. The first is the !!! command.

To start your document as XHTML:

!!!
Will create the following:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

How about an XML header:

!!! XML
Creates:
<?xml version="1.0" encoding="utf-8" ?>

1.1 XML:

!!! 1.1
Will create the following:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

Strict XHTML:

!!! Strict
Will create the following:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

The "!!!!" Command (HTML4 Doctypes)

We use this class for standard HTML4, so why would we leave these out?

To start your document as Strict HTML 4:

!!!!
Will create the following:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

Transitional HTML4:

!!!! Transitional
Creates:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

HTML4 Frameset:

!!!! Frameset
Will create the following:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">

No Command? Print the line as is

If a line of pHAML does not start with a "%", ".", "#", "{", "!!!", "!!!!","-", "/" , "//" , "<<< or >>>", "?", "??", "$", "\" it will be printed as is. The line will also be printed if a command is not understood. The system should never "eat" a line without some kind of result--this is to prevent frustrating "silent errors" that slow the speed of coding. By the way, this is why there is no annoying "|" following a line for continuation, just put the continuation on the next line, the system understands.

The system will not ignore leading whitespace before a command (except inside a heredoc and the debug detail command, explained later). The system will also "eat" the command itself, good to keep in mind when formatting.

Please feel free to use &nbsp; and it's kin, if you need accurate spacing in text that spans lines--or to force a character (see? check the source for this document, this line has one).

The "\" Command (Escape Line)

The "\" at the start of the line (after whitespace) will be eaten, and the remainder of the line is printed out as is. That is how you can start a line with any of the command letters mentioned above.

Escape Lines

pHAML HTML Result
  \%donottagme.meneither#ohnoo{not="us"}
  %tagme.meto#cool
  \/do not comment me
  /comment me
%donottagme.meneither#ohnoo{not="us"}
<tagme class="meto" id="cool">
</tagme>
/do not comment me
<!-- comment me -->

The "/" Command (HTML Comment)

The "/" command will wrap what follows it with an HTML comment.

HTML Comments

pHAML HTML Result
  /this is a comment
<!-- this is a comment -->

The "//" Command (Non Rendered Comment)

The "//" command will "hide the line" during rendering, and allows comments.

Non Rendered Comments

pHAML HTML Result
  now you see me!!
  //now you don't
  good to see you again!!
now you see me!!
good to see you again!!

The "<<<" and ">>>" or Heredoc Command

The "<<<" is used to set off a heredoc. All of the following code will be printed verbatim, including returns and spacing, until a ">>>" preceded by white space is seen.

As pHAML heredoc commands (both "<<<" and ">>>") are "preceding space sensitive" (indents will force preceding tag closures). The content between the tags is not.

Unlike the rest of the commands, heredoc will render empty lines and "//" (comment lines) verbatim.

Here Doc Example

pHAML HTML Result
  %style{type="text/css"}
     <<<
        body {
        height:100%;
        font-size:11px;
        margin-left:5%;
        margin-right:5%;
        background-color:white;
        color:black;
        }
     >>>
<style type="text/css">
        body {
        height:100%;
        font-size:11px;
        margin-left:5%;
        margin-right:5%;
        background-color:white;
        color:black;
        }
</style>

Here Doc Example(Indents Matter)

pHAML HTML Result
  %style{type="text/css"}
     <<<
body {
height:100%;
font-size:11px;
margin-left:5%;
margin-right:5%;
background-color:white;
color:black;
}
     >>>
<style type="text/css">
body {
height:100%;
font-size:11px;
margin-left:5%;
margin-right:5%;
background-color:white;
color:black;
}
</style>

Here Doc Example(Renders "//" and empty lines)

pHAML HTML Result
     <<<
line

line
//comments are rendered. When bug stomping,
//not a good idea to wisecrack on users here.
line
     >>>
line

line
//comments are rendered. When bug stomping,
//not a good idea to wisecrack on users here.
line

The "-" Command (Embed PHP Code)

The "-" command will wrap the following code with tags, so that the rendered template can be evaled as PHP code (the class has a command to do it for you).

This class was written for two groups of users, developers and web users. The - command will create the PHP, but will not execute it, that is performed by a different class command. So you could have web users create their own templates, and render them, but they cannot execute PHP on the system host, unless you--the implementor--make a subsequent "phpExec" call to the object explicitly. You are warned.

It is at this point that you may want to consider a much richer set of templating functionality that is achieved by using Smarty and pHAML together.

Embedded PHP Example

pHAML HTML Result
  - for($x;$x<=10;$x++){
    %p hello world
  - }
<?PHP for($x;$x<=10;$x++){ ?>
<p>
hello world
</p>
<?PHP } ?>
    %table
        - $arr = array();
        - $arr[0] = array('a','b','c');
        - $arr[1] = array('d','e','f');
        - foreach($arr as $row){
            %tr 
              - foreach($row as $col){
                %td
                  - echo $col;
              - }
        - }
<table>
<?PHP $arr = array(); ?>
<?PHP $arr[0] = array('a','b','c'); ?>
<?PHP $arr[1] = array('d','e','f'); ?>
<?PHP foreach($arr as $row){ ?>
<tr>
<?PHP foreach($row as $col){ ?>
<td>
<?PHP echo $col; ?>
</td>
<?PHP } ?>
</tr>
<?PHP } ?>
</table>

The "?" Command (Toggle Debug)

The "?" command will toggle the debug mode. If the debug mode is on, it is turned off, if off; it is turned on. Debug mode will print an HTML comment before each processed line of pHAML code, which can be very useful during design.

The "??" Command (Toggle Show HTML)

The "??" command will toggle the HTML mode. If the HTML mode is on, it is turned off; if off, it is turned on. The HTML mode will print everything in HTML characters, allowing the generated HTML to be seen (this is used in this document).

The "$" and "$-" Command (Insert Value from Passed PHP Array)

The "$" command will turn the pHAML renderer into a simple template system. You set the values of the assignment using the classes assign method. If you pass an array to the render call, the text following the $ will be used as an array key. The $- will strip the whitespace from both sides of the inserted value (good for textarea elements and such).

Debugging

Motivation

The debugging system inside of pHAML was developed quickly as pHAML was used to creating working sites. It consists of two principal commands.

The "?" (Show Line Information)

The "?" can be place on a single line at any horizontal location, it is not "preceding space sensitive". When on, an HTML comment containing useful information is created.

The debug information is provided in a format of:

<!-- the_line_number:the_number_of_indent_spaces{the_command_if_there}[the_status_off_the_herdoc]: The pHAML line -->

Debug Command Example

pHAML HTML Result
  No debug info for this line, turn it on--
  ?
  This text line is simple, it is indented by 20
  /This is a comment line-see the / show up
  Now start a here doc
    <<<
     In the here doc, see the [on]?
    >>>
  Out of heredoc
  Turn off the debug
  ?
  This line does not have debug info  
No debug info for this line, turn it on--
<!-- Debug on -->
  <!-- 870:20: This text line is simple, it is indented by 20 -->
This text line is simple, it is indented by 20
  <!-- 871:20{/}: /This is a comment line-see the '/' show up? -->
<!-- This is a comment line-see the '/' show up? -->
  <!-- 872:20: Now start a here doc -->
Now start a here doc
    <!-- 873:22{<<<}: <<< -->
     <!-- 874:23[on]: In the here doc, see the [on]? -->
     In the here doc, see the [on]?
    <!-- 875:22{>>>}[on]: >>> -->
  <!-- 876:20: Out of heredoc -->
Out of heredoc
  <!-- 877:20: Turn off the debug -->
Turn off the debug
  <!-- 878:20{?}: ? -->
<!-- Debug off -->
This line does not have debug info  

The "??" (Show the HTML)

The second tool in the debug toolbox is the "??" toggle, this command is "preceding space sensitive". When on, the content that follows is converted to HTML compatible characters, so that is will show up in the browser. This is the command that is used to show all of the HTML results in this document.

Show HTML Command Example

pHAML HTML Result
  ??
    %element#id data
  ?? 
<element id="id">
data
</element>

Makes it easy to see everything.

The Most Useful Debug Combination

Combine the two commands to see both the code and debug info (use a %pre to help):

%pre
?
??
%problem_element(s)
...
??
?    

Installation

pHAML is contained entirely in one class: class.pHAML.php. You may put the class anywhere in your web directory, it is safe. The easiest way to install is to put it in your class path.

Just include the class in your PHP code, create an instance--and of you go. Here is an example:

<?PHP
//include the pHAMLClass here
include('class.pHAML.php');
//create a template
$template=
'!!!!
%html
  %head
    %title Hello From pHAML!!
  %body
    %p Hello World';
//instantiate the class
$pHAML = new pHAML();
//render the content
$content = $pHAML->render($template);
//echo to the browser
echo $content;
?>

To turn pHAML into a simple templating system (good for prototyping sites), send an array along with the template, and use the "$" command.

<?PHP
//include the pHAMLClass here
include('class.pHAML.php');
//create an array composed of: name_of_variable_in_template_without_leading_dollar=>value_of_replacement_text
$values = array('greeting'=>'Hello World, I am a template!!!!');
//create a template
$template=
'!!!!
%html
  %head
    %title Hello From pHAML!!
  %body
    %p 
      $greeting';
//instantiate the class
$pHAML = new pHAML();
//render the content
$content = $pHAML->render($template,$values);
//echo to the browser
echo $content;
?>

pHAML has a recursive feature in the rendering of $key_name. If it cannot find the key that matches in the value array, it will look for a template in the template array, and compile that...and so on.

What template array? Good question, the render function can take an array of templates, and will compile them all, but return only the final result of the one with the array key of 'contents'. This allows the design to break into several different templates, maybe an example will help.

<?PHP
//include the pHAMLClass here
include('class.pHAML.php');
//create an array composed of: name_of_variable_in_template_without_leading_dollar=>value_of_replacement_text
$values = array('greeting'=>'Hello World, I am a template!!!!');
//create a template for a simple web site
$template['content']=
'!!!!
%html
  %head
    %title Hello From pHAML!!
  %body
    %table{width ="1300px"  border="0" cellspacing="0" cellpadding="0"}
      %tr
        %td
          $banner
      %tr
        %td
          $center
      %tr
        %td
          $footer';
$template['banner']='%b I am a banner';
$template['center']=
'I am center content, and I say
$greeting';          
$template['footer']='I am footer content';          
//instantiate the class
$pHAML = new pHAML();
//render the content
$content = $pHAML->render($template,$values);
//echo to the browser
echo $content;
?>

That is really cool...let's see the other implementations of HAML do that! So now you can break up a web site, build a CMS, whatever.

Smarty Integration

Both the Smarty and the Zend Framework implementations are used in our enterprise level web services, should you need some experience and help, please feel free to contact us.

The original target of this code was a Smarty template system, to simplify writing templates.

Smarty Considerations

Smarty is a well developed template system, that in today's web server environment is fast and expandable. Still, you are stuck with HTML writing, and in today's Web 2.0 "div rich" world, it is easy to get lost in the depths of a large template. Hours doing that led to the writing of this code.

Smarty and pHAML combine to create a very powerful and fast content design tool.

OK, so you are going to Smarty

The implementation selected was a Smarty "Block" command. Block commands are nice, since they process after the Smarty replacement. This means that you can use Smarty variables, looping, commands, formating...you name it. The pHAML code will be rendered after Smarty puts everything in.

There are two differences in the Smarty implementation from the stand alone class. The first is that the PHP command "-" does not exist. This is because Smarty is a "compiling" template engine, and the PHP code would get parsed and run by the Smarty engine--creating a security risk. The second is minor, Smarty passes the block as a string, so there is no array processing or assigning of template values by the pHAMLSmarty class. The functionality that is lost can be replaced by using Smarty assigns and Smarty variables ({$variable}).

Bad News and Good News on "{}"'s

The bad news, Smarty uses curly braces as a command delimeter. This creates a conflict with the pHAML, IE: %element{v="v"}. This can be solved by setting Smarty to use different delimeters, or the easier route of using {ldelim} and {rdelim} that Smarty offers. The good news, a tool has been written to do this for you, simply enter your standard pHAML code and see the Smarty compatible code created before your eyes, pHAML Live tool .

Installation

There are three ways to install the pHAMLSmarty class:

  1. Drop the block.pHAML.php class into your Smarty plugin directory, SMARTY_DIR/plugins_dir.
  2. Put the block.pHAML.php class into a directory, and append that directory via PHP code using $smarty->plugins_dir[] ='your/directory'.
  3. Use the Smarty register_block() function.

Smarty Examples

Hello World

Here is an example based on the Quick Start example from the Smarty Documentation:

The PHP Code

include('Smarty.class.php');
// create object
$smarty = new Smarty;
// assign some content. This would typically come from
// a database or other source, but we'll use static
// values for the purpose of this example.
$smarty->assign('greeting', 'Hello World');
// display it
$smarty->display('index.tpl');

The Smarty Template

{pHAML}
!!!!
%html
  %head
    %title Simple Document
  %body
    %p {$greeting}
{/pHAML}

Hello World

Here is a more complex example based again on the Quick Start example from the Smarty Documentation:

The PHP Code

include('Smarty.class.php');

// create object
$smarty = new Smarty;

// assign an array of data
$smarty->assign('name', array('bob','jim','joe','jerry','fred'));

// assign an associative array of data
$smarty->assign('users', array(
	array('name' => 'bob', 'phone' => '555-3425'),
	array('name' => 'jim', 'phone' => '555-4364'),
	array('name' => 'joe', 'phone' => '555-3422'),
	array('name' => 'jerry', 'phone' => '555-4973'),
	array('name' => 'fred', 'phone' => '555-3235')
	));


// display it
$smarty->display('index.tpl');

The Smarty Template

{pHAML}
%table
{section name=mysec loop=$name}
   %tr{ldelim}bgcolor="{cycle values="#eeeeee,#dddddd"}"{rdelim}
      %td {$name[mysec]}
{/section}

%table
{section name=mysec loop=$users}
   %tr{ldelim}bgcolor="{cycle values="#aaaaaa,#bbbbbb"}"{rdelim}
      %td {$users[mysec].name}
      %td {$users[mysec].phone}</td>
{/section}
{/pHAML}

Smarty Tips

Experience has provided some quick tips on using pHAML and Smarty:

  1. The {strip} Smarty block function is always a bad idea, it removes indents and returns, pure badness for a spacing sensitive syntax like pHAML.

Zend Framework Integration

The pHAML class is a good fit with the Zend Framework. The pHAML object, AA_View_pHAML offers a full Zend View Interface implementation, this means that you can use pHAML in your Zend Framework solution seemlessly.

Mind Numbing Technical Discussion

The following is a deeper technical discussion of some of the theory in the implementation, you should still be able to get the examples to work without knowing all this�it is included to hopefully help in understanding.

The easiest option may be to leave the Zend View object intact, and placing all of the logic into the phtml template file. Incidentally, the default Zend View object just includes the phtml file, and wraps it with output buffer start (ob_start) and get_clean (ob_get_clean) methods. So this is the simplest implementation, works out of the box, but requires that php code be put into each template.

Everything in the Zend Framework flows through an �index.php� file, this is called the bootstrap file. The bootstrap then creates a controller. The controller then will call the appropriate controller class and action function call based on the url (www.myzendframework.com/controller_class/action). The action object has a default viewer implementation, that will render the view script using a series of defaults for location and type. This is good behavior if we want to override the action viewer helper and use pHAML system wide.

This is not so good when you want to constrain the pHAML rendering to a specific module, controller, or action. The pHAML will compile and be added to the response object, but so will the default .phtml script, which will also be rendered and added to the response object afterwards by postDispatch afterwards. You can prevent this by setting �$this->getFrontController()->setParam('noViewRenderer', true);� in the controller under the action. If you want the entire controller to turn off the native view renderer--put the command in the preDispatch.

The following provides examples of each of the solutions. Here is a copy of the httpd.conf that was used (this is a bit different than the Zend tutorial, the rewrite routes all unresolved documents through the index, simpler when adding css and such):

	Alias /hlzendex1/ "/your/web/zend/root/hlzendex1/www/"
	<Directory "/your/web/zend/root/hlzendex1/www/">
		AllowOverride None
		RewriteEngine on
		RewriteCond %{REQUEST_FILENAME} !-f
		RewriteRule ^.*$ /hlzendex1/index.php
	</Directory>        
	Alias /hlzendex2/ "/your/web/zend/root/hlzendex2/www/"
	<Directory "/your/web/zend/root/hlzendex2/www/">
		AllowOverride None
		RewriteEngine on
		RewriteCond %{REQUEST_FILENAME} !-f
		RewriteRule ^.*$ /hlzendex2/index.php
	</Directory>        

Installation

The best way to install is to place the pHAML class in the same library directory as the Zend directory. That will allow us to use the class loader. Simply create an /AA/View directory tree, and put the class in it.

--library (Zend Library)
       |
       --AA--View
       |     |
       |      -pHAML.php
       --Zend
          |
         (Zend lib files)

hlzendex1:The Simple Approach, Put Everything in the Action phtml File

This is trivial to do, just use the following structure, there are five files needed (this mirrors the Zend Framework Zend_Controller Quickstart documentation):

The index.php (Bootstrap) Code

The index is usually named /app/www/index.php (i.e. 'hlzendex1/www/index.php')

<?php
/* hlzendex1/www/index.php */
/** Zend Bootstrap File */
require_once 'Zend/Controller/Front.php';
Zend_Controller_Front::run('/your/web/zend/root/hlzendex1/controllers');          

The IndexController.php Code

The controller is usually named /app/controllers/IndexController.php (i.e. 'hlzendex1/controllers/IndexController.php')

/* hlzendex1/controllers/IndexController.php */
/** Zend_Controller_Action */
require_once 'Zend/Controller/Action.php';

class IndexController extends Zend_Controller_Action
{
    public function indexAction()
    {
    }

}          

The ErrorController.php Code

The controller is usually named /app/controllers/ErrorController.php (i.e. 'hlzendex1/controllers/ErrorController.php')

<?php
/* hlzendex1/controllers/ErrorController.php */
/** Zend_Controller_Action */
require_once 'Zend/Controller/Action.php';

class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
    }
}

The index.phtml Template Code

The template is usually named /app/views/scripts/controller/index.phtml (i.e. 'hlzendex1/views/scripts/index/index.phtml'')

<?PHP
/* hlzendex1/views/scripts/index/index.phtml */
//The heredoc syntax works great, just backslash all of the "$"'s
$template =<<<EndOfTemplate
!!!!
%html
  %head
    %title Simple Document
  %body
    %p Hello World Simple from the .phtml Template
EndOfTemplate;
//instance and invoke
require_once('AA/View/pHAML.php');
$hl = new pHAML();
echo $hl->render($template);
?>          

The error.phtml Template Code

The template is usually named /app/views/scripts/controller/error.phtml (i.e. 'hlzendex1/views/scripts/error/error.phtml'')

<?php
/* hlzendex1/views/scripts/error/error.phtml */
//The heredoc syntax works great, just backslash all of the "$"'s
$template =<<<EndOfTemplate
!!!!
%html
  %head
    %meta{http-equiv="Content-Type" content="text/html; charset=utf-8"}
    %title Simple Document
  %body
    %h1 An error occurred
    %p An error occurred; please try again later.
EndOfTemplate;
//instance and invoke
require_once('AA/View/pHAML.php');
$hl = new pHAML();
echo $hl->render($template);

hlzendex2:A Better Solution, Use AA_View_pHAML Class

This is a better solution, as it allows you to render pHAML and do assigns using the Zend Framework way.

The index.php (Bootstrap) Code

The index is usually named /app/www/index.php (i.e. 'hlzendex2/www/index.php')

<?php
/* hlzendex2/www/index.php */
/** Zend Bootstrap File */
require_once 'Zend/Controller/Front.php';
Zend_Controller_Front::run('/your/web/zend/root/hlzendex2/controllers');          

The IndexController.php Code

The controller is usually named /app/controllers/IndexController.php (i.e. 'hlzendex2/controllers/IndexController.php')

/* hlzendex2/controllers/IndexController.php */
/** Zend_Controller_Action */
require_once 'Zend/Controller/Action.php';

class IndexController extends Zend_Controller_Action
{
    //uncomment the following to turn off default view for the entire module
    /*public function preDispatch()
    {
        // Turn off the default view for everything in this module
        $this->getFrontController()->setParam('noViewRenderer', true);
    }*/
    
    public function indexAction()
    {
        //grab the front controller and turn off the default view rendering
        //(you can delete this line if the noViewRenderer is set in the preDispatch)
        $this->getFrontController()->setParam('noViewRenderer', true);
        //since the class is in the Zend lib tree, can find it using the loader
        Zend_Loader::loadClass('AA_View_pHAML');
        //instance the Zend compliant class
        $view = new AA_View_pHAML();
        //tell the class where to find the template, this can be any path
        $view->setScriptPath('D:/wamp/asf/hlzendex2/views/scripts/index');
        //here is how we assign variables
        $view->assign('greeting','Hello from the index action!!');
        //pass the name of the template to be rendered
        echo  $view->render('index.hml');
    }

}          

The ErrorController.php Code

The controller is usually named /app/controllers/ErrorController.php (i.e. 'hlzendex2/controllers/ErrorController.php')

<?php
/* hlzendex2/controllers/ErrorController.php */
/** Zend_Controller_Action */
require_once 'Zend/Controller/Action.php';

class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
    }
}

The index.hml Template Code

The template will be in the path is set in the controller (here we use 'hlzendex2/views/scripts/index/index.hml'')

// hlzendex2/views/scripts/index/index.hml //
!!!!
%html
  %head
    %title Document With Assigns
  %body
    %p Hello World :
       $greeting
EndOfTemplate;
//instance and invoke
require_once('AA/View/pHAML.php');
$hl = new pHAML();
echo $hl->render($template);
?>          

The error.phtml Template Code

The template is usually named /app/views/scripts/controller/error.phtml (i.e. 'hlzendex2/views/scripts/error/error.phtml'')

<?PHP /* hlzendex2/views/scripts/error/error.phtml */ ?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Error</title>
</head>
<body>
    <h1>An error occurred</h1>
    <p>An error occurred; please try again later.</p>
</body>
</html>

Final Notes

Thank you for taking the time to read and I hope that you find pHAML as productive as we have.

I am sure that we will be improving pHAML, but we will work very hard to keep it compatable with what is out there.

Please feel free to use our pHAML live site to make suggestions and file bugs.

The latest code drop and documentation will always be found at our pHAML live site.


The source for this document:
!!!
---
%html
  %head
     %title pHAML Documentation
     %style{type="text/css"}
       <<<
	        body {
	        background-color:white;
	        height:100%;
	        font-size:11px;
	        margin-left:5%;
	        margin-right:5%;
	        color:black;
	        font-family:verdana,sans-serif;
	        font-weight:normal;
	        }
	        tr {
	        vertical-align:top;
	        }
	        th {
	        text-align:left;
	        }
	        a {
	        color:#00217B;
	        text-decoration:none;
	        }
	        a:hover {
	        text-decoration:underline;
	        }
	        h1 {
	        color:#9F0000;
	        display:block;
	        font-size:30px;
	        font-weight:normal;
	        margin:0px 0px 7px 0px;
	        padding:0px 0px 3px 0px;;
	        border-bottom:1px solid #CFCFCF;
	        }
	        h2 {
	        color:#2F395F;
	        display:block;
	        font-size:20px;
	        font-weight:normal;
	        margin:0pt 0pt 4px;
	        padding:0pt;
	        border:medium none;
	        }
	        h3 {
	        color:#000000;
	        display:block;
	        font-size:14px;
	        font-weight:bold;
	        margin:15px 5px;
	        padding:0pt;
	        }
	        p {
	        display:block;
	        margin-bottom:15px;
	        margin-top:15px;
	        }
	        code, .result, .example {
	        font-size:100%;
	        color:#000066;
	        font-family:'Courier New',Courier,monospace;
	        border:1px solid #EEEEEC;
	        }
	        .table table {
	        border:1px solid #EEEEEC;
	        border-spacing:0px;
	        margin:0px 0px 7px 0px;
	        
	        }
	        .table th {
	        background:#EEEEEC none repeat scroll 0%;
	        border:1px solid #EEEEEC;
	        text-align:left;
	        vertical-align:top;
	        }
	        .table td {
	            border:1px solid #EEEEEC;
	            text-align:left;
	            vertical-align:top;
	        }
	        p.title{
	            font-weight:bold;
	        }
	        .note, .example {
	        background-color:#EEEEEC;
	        margin:1em 0pt;
	        padding:0.2em;
	        }
	        .note:first-letter {
	         color:#9F0000;
             font-size:200%;   
	        }
	        .box {
	        background:transparent url(emblem-important.png) no-repeat scroll 0%;
	        padding:5px 5px 5px 50px;
	        border:1px solid #D3D7CF;
	        background-color:#EEEEEC;
	        margin:0px 0px 7px 0px;
	        }
        >>>
  %body
    .box
      %h1 Relax...
        %h3 What if someone told you that there is a simple and powerful tool to quickly develop HTML, XHTML, and XML that works standalone, with Smarty, and with the Zend Framework?  Welcome...
        %h3 Opps, did we mention that it has been used in production since 2006?
        %h3 But we are not done...there is a new version in testing...it is even cooler...and should be out Q4 of 2009...stay tuned.
    %h1 pHAML User's Guide
    %h3 This work is licensed under the Creative Commons Attribution License. To view a copy of this license, visit http://creativecommons.org/licenses/by/2.0/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
    %h2 Edition for pHAML .9 Beta
    %p
      %b Props: My family, the HAML folks, everybody at Applied Autonomics LLC.
    %hr
    %h1 Cheat Sheet
    .table
       %p.title Cheat Sheet
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th What it does
            %tr
              %td %tagname.class1.class2#id{attribute_1="value&nbsp;1"...}&nbsp;Element&nbsp;Content
              %td Create and element and put the content after it
            %tr
              %td A text line without preceding command
              %td Just print as is (according to indent)
            %tr
              %td \ the line
              %td Eat the '\', print the line as is
            %tr
              %td / the line
              %td Create HTML comment from the line
            %tr
              %td &lt;&lt;&lt;  &gt;&gt;&gt;
              %td Print everything between &lt;&lt;&lt; &amp; &gt;&gt;&gt; verbatim
            %tr
              %td -
              %td Wrap what follows in PHP tags
            %tr
              %td ?
              %td Turn on/off debug HTML comments
            %tr
              %td ??
              %td Turn on/off rendering as browser viewable HTML
            %tr 
              %td !!! & !!!!
              %td Opening doctype elements
            %tr
              %th{colspan="2"} Spacing
            %tr
              %td{colspan="2"} 
                %p Indentation is how pHAML determines the tag structure.  Elements indented more than the elements above will be contained within the one above.  Elements with the same (or less) indentation will cause all elements above with more indentation to close.
            %tr 
              %th Simple HTML Document
              %th Simple XML Document
            %tr
              %td
                %pre 
                 <<<
!!!!
%html
  %head
    %title Simple Document
  %body
    %p this is the body, 5 lines=real document
                 >>>
              %td
                %pre 
                 <<<
!!! XML
%element_1 
  %element_2 &lt;![CDATA[ Stuff ]]&gt;
%element_3
                 >>>
            %tr 
              %th{colspan="2"} Debug Hints
            %tr 
              %td 
                %p Try the following, turn on the debug comments, then show the HTML:
                  %pre
                    \%pre
                      \?
                      \??
                         \%problem_element(s)
                         \...
                      \??
                      \?
              
              %td
                 %p Here are some common debug issues, in order of occurence:
                 %ol 
                   %li Lead Spacing (is your editor using tabs, pHAML assumes they are 4 spaces wide)
                   %li Is the command/element syntax correct (as a PHP guy, I have a very quick '$' instead of '%')
                   %li Use the debug system, or the
                      %a{href="http://www.appliedautonomics.com/pHAML/pHAML_Live.php"} pHAML Live tool
                      (the reference implementation).
                 %p When in doubt, you can look through the documentation code, since that is all pHAML, or read the source.
                 %p If after all that, and you have found an undocumented feature (ok, call it a bug), or have a suggestion, submit it please.
    %h3
      You can test/learn/build all of this code and your code using our 
      %a{href="http://www.appliedautonomics.com/pHAML/pHAML_Live.php"} pHAML Live
      testing tool.        
    %hr
    %h1 Why pHAML?
      %p
        %h4 PHP. Very fast to produce well formed code.  Built in templating for simple projects, integrates with Smarty for complex projects. Used in enterprise projects.  Easy to learn.  Fast to use.  Did we say easy and fast?
      %p Try it for a few days...it can save you hours.
    %h1 Preface
    .normal
        %p This project is truly a work of accident.  While working on an implementation of our Autonomic Services Framework, there was the need to quickly develop a web site.  Somewhere in the midst of trying to figure out which table data tag to change the class of, the thought occurred that maybe a new way was needed.  HAML (
            %a{href="http://haml.hamptoncatlin.com/"} http://haml.hamptoncatlin.com/
            ) showed up.  HAML looked like a nice implementation of a �templating� system for HTML and XML.  Templating systems are not new, and there are several ways to do them, HAML seemed like a nice approach.  The problem was that it was not in PHP, but Ruby�Ruby is nice, but PHP has always stood out as the fastest way to develop applications for web services (and yes, we tried RAILS, but that is still a technical distance from the data warehousing/AI work that we do).
        %p The great thing about open source is that you can view the code, take a look at how others do it.  HAML is well written and documented�so it did not take long to get the gist.  The first step was to copy in the core code of HAML and rewrite it in PHP, but that approach left a lot of strengths of PHP on the table.  So quickly, the approach changed to what you see in this implementation.  That was a good thing, since I later found a PHP implementation of HAML.
          Which in itself was a good thing since I do not like rewriting code, I may have never written this.
        %p The first production level release of the code was written in two days�the core has remained the same, there has been some refactoring, and some added functions.  But the entire functionality boils down to around 160 lines of code�which keeps it simple, yet powerful�and that is the combination that creates value.
        %p The name is pun on Pig Latin, and HAML.  So this is like HAML, only different--in ways good for PHP and getting code done.
    %h2 How pHAML is Like HAML
    .normal
        %p There is no greater fan of the principles behind HAML than pHAML, markup should be beautiful, DRY (don't repeat yourself), well-indented, and the XHTML structure should be clear.
        %ul
            %li The tag creating syntax was kept the same.
            %li Spaces are VERY important�tabs and spaces are not equal and may produce �interesting� results (hence the addition of the debugging capability).
    %h2 How pHAML is different from HAML
    .normal
        %p This solution was created to enhance 
            %a{href="http://smarty.php.net/"} Smarty
            (it evolved a bit since then).  There have been other tweaks to assist in the creation of code.  Also, PHP and Ruby share a bit, but are a bit different as well.
    %h3 Differences from HAML Syntax
    %ul
       %li Attributes are literal: there is no Ruby array notation for attribute arrays.
       %li Spaces are not tied to a multiple of two (fight the man!!), but you should make your code spacing consistent in practice.
       %li There are comments (not just the HTML kind).
       %li There is no Ruby code integration.
       %li There is PHP integration.
       %li There are debugging commands, a simple template system, heredoc syntax, html character output, and html4 doctype tags.
       %li Smarty integration.
       %li Zend Framework integration.
       %li All in a compact single PHP class (~160 lines, with comments, no libraries or directory structure needed).
    .box
       %p.note This entire document has been produced in pHAML, it is included in the examples, and shows almost all of the functionality.
    %h1 Using pHAML
    %h2 Basic Structure
    .box
      %p.note The basic structure of a line of pHAML code is:&nbsp;
        %code.code %tagname.class1.class2#id{attribute_1="value 1"...} Element Content
    %p Since experience is the best teacher, we are going to use examples.
    .table
        %p.title A Simple Tag
        .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %code.code
                  \%tagname
              %td{width="50%"}
                %pre
                  ?? C  
              	    %tagname
              	  ??
    .table
       %p.title A Tag With a Class
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %code.code
                 \%tagname.class
              %td{width="50%"}
                %pre
                    ?? C
                      %tagname.class
                    ??
    .table
       %p.title A Tag With Two Classes
       
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %code.code
                  \%tagname.class.class_two
              %td{width="50%"}
                %pre
                  ?? C
                    %tagname.class.class_two
                  ??                             
    .table
       %p.title A Tag With a Class and ID
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %code.code
                  \%tagname.class#id
              %td{width="50%"}
                %pre
                  ?? C
                    %tagname.class#id
                  ??              
    .table
       %p.title A Tag with Content
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %code.code.code
                  \%tagname Some content
              %td{width="50%"}
                %pre
                  ?? C
                    %tagname Some content
                  ??
       .box
         %p.note Please note that the content has a space before it. 
       
    .table
       %p.title A Tag with Attributes
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %code.code
                  \%tagname{att1="v1" att2="v2"}
              %td{width="50%"}
                %pre
                  ?? C
                    %tagname{att1="v1" att2="v2"}
                  ??      
        .box
          %p.note This is a different structure than HAML. pHAML takes everything in brackets and adds it to the tag literally.
    .table
       %p.title Bare Class Creates a DIV Tag with that Class
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %code.code
                  \.class
              %td{width="50%"}
                %pre
                  ?? C
                    .class
                  ??              
    .table
       %p.title Bare ID Creates a DIV Tag with that ID
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %code.code
                  \#id
              %td{width="50%"}
                %pre
                  ?? C
                    #id
                  ??              
    .table
       %p.title Same for Attributes
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %code.code
                  \{att1="v1" att2="v2"}
              %td{width="50%"}
                %pre
                  ?? C
                    {att1="v1" att2="v2"}
                  ??               
    .table
       %p.title Mix and Match
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %code.code
                  \.class1.class2#id{a="1" b="2"}
              %td{width="50%"}
                %pre
                  ?? C
                    .class1.class2#id{a="1" b="2"}
                  ??              
    %h2 More Interesting Examples
    .table
       %p.title An Ordered List
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
               %td{width="50%"}
                %pre
                  <<<
  %ol
    %li Hello
    %li World
                  >>>
              %td{width="50%"}
                %pre
                    ?? C
                      %ol
                        %li Hello
                        %li World                  
                    ??
    .table
       %p.title A Table
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %pre
                  <<<
  %table.table#t_1{width="100%"}
    %tr
      %td.sam{valign="top" style="color:white;bgcolor:red;"} Data
    %tr
      %td.bob Other Data 
                  >>>
              %td{width="50%"}
                  %pre
                    ?? C
                      %table.table#t_1{width="100%"}
                        %tr
                          %td.sam{valign="top" style="color:white;bgcolor:red;"} Data
                        %tr
                          %td.bob Other Data 
                    ??
    %p That is 12 lines of XHTML for 5 lines of code, better than two to one--and you can read it easily.
                
    %h1 Commands and Tools
    %p.title Kick it Up a Notch
    %p
        This is where we diverge from HAML. HAML folks may ask themselves "how do I debug", pHAML has a simple answer.  PHP folks may ask themselves "where did all the commands go?".  This section answers both and more.
    %h2 Commands
    %p pHAML has a rich set of commands, so let's walk through those.
    %h3 The "!!!" Command
    %p Like it's HAML progenitor, pHAML provides shortcuts for your coding pleasure.  The first is the !!! command.
        %h4 To start your document as XHTML:
        .example
          %code 
            \!!!
        Will create the following:
        .example
          %pre
            ?? C
            !!!
            ??
        %h4 How about an XML header:
        .example
          %code 
            \!!! XML
        Creates:
        .example
          %pre
            ?? C
            !!! XML
            ??
        %h4 1.1 XML:
        .example
          %code 
            \!!! 1.1
        Will create the following:
        .example
          %pre
            ?? C
            !!! 1.1
            ??
        %h4 Strict XHTML:
        .example
          %code 
            \!!! Strict
        Will create the following:
        .example
          %pre
            ?? C
            !!! Strict
            ??
    %h3 The "!!!!" Command (HTML4 Doctypes)
    %p We use this class for standard HTML4, so why would we leave these out?
        %h4 To start your document as Strict HTML 4:
        .example
          %code 
            \!!!!
        Will create the following:
        .example
          %pre
            ?? C
            !!!!
            ??
        %h4 Transitional HTML4:
        .example
          %code 
            \!!!! Transitional
        Creates:
        .example
          %pre
            ?? C
            !!!! Transitional
            ??
        %h4 HTML4 Frameset:
        .example
          %code 
            \!!!! Frameset
        Will create the following:
        .example
          %pre
            ?? C
            !!!! Frameset
            ??
    %h3 No Command? Print the line as is
    %P If a line of pHAML does not start with a "%", ".", "#", "{", "!!!", "!!!!","-", "/" , "//" , "<<< or >>>", "?", "??", "$", "\" it will be printed as is.
        The line will also be printed if a command is not understood.  The system should never "eat" a line without some kind of result--this is to prevent frustrating "silent errors" that slow the speed of coding.
        By the way, this is why there is no annoying "|" following a line for continuation, just put the continuation on the next line, the system understands.
     .box
       %p.note
        The system will not ignore leading whitespace before a command (except inside a heredoc and the debug detail command, explained later).  The system will also "eat" the command itself, good to keep in mind when formatting.
     .box
       %p.note
        Please feel free to use &amp;nbsp; and it's kin, if you need accurate spacing in text that spans lines--or to force a character (see? check the source for this document, this line has one). 
     %h3 The "\" Command (Escape Line)
     %P The "\" at the start of the line (after whitespace) will be eaten, and the remainder of the line is printed out as is.  That is how you can start a line with any of the command letters mentioned above.
     .table
       %p.title Escape Lines
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %pre
                  <<<
  \%donottagme.meneither#ohnoo{not="us"}
  %tagme.meto#cool
  \/do not comment me
  /comment me
                  >>>
              %td{width="50%"}
                %pre
                    ?? C
                      \%donottagme.meneither#ohnoo{not="us"}
                      %tagme.meto#cool
                      \/do not comment me
                      /comment me
                    ??
     
    %h3 The "/" Command (HTML Comment)
    %P The "/" command will wrap what follows it with an HTML comment.
    .table
       %p.title HTML Comments
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %pre
                  <<<
  /this is a comment
                  >>>
              %td{width="50%"}
                %pre
                  ?? C
                    /this is a comment
                  ??
    %h3 The "//" Command (Non Rendered Comment)
    %P The "//" command will "hide the line" during rendering, and allows comments.
    .table
       %p.title Non Rendered Comments
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %pre
                  <<<
  now you see me!!
  //now you don't
  good to see you again!!
                  >>>
              %td{width="50%"}
                %pre
                  ?? C
                    now you see me!!
                    //now you don't
                    good to see you again!!
                  ??
    %h3 The "<<<" and ">>>" or Heredoc Command
    %p The "<<<" is used to set off a heredoc.  All of the following code will be printed verbatim, including returns and spacing, until a ">>>" preceded by white space is seen.
    .box
      %p.note As pHAML heredoc commands (both "<<<" and ">>>") are "preceding space sensitive" (indents will force preceding tag closures).  The content between the tags is not. 
    .box
      %p.note Unlike the rest of the commands, heredoc will render empty lines and "//" (comment lines) verbatim.
    .table
       %p.title Here Doc Example
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %pre
                  <<<
  %style{type="text/css"}
     <<<
        body {
        height:100%;
        font-size:11px;
        margin-left:5%;
        margin-right:5%;
        background-color:white;
        color:black;
        }
     &gt;&gt;&gt;
                  >>>
              %td{width="50%"}
                %pre
                    ?? C
                      %style{type="text/css"}
                         <<<
                            body {
                            height:100%;
                            font-size:11px;
                            margin-left:5%;
                            margin-right:5%;
                            background-color:white;
                            color:black;
                            }
                          >>>
                    ??
    .table
       %p.title Here Doc Example(Indents Matter)
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %pre
                  <<<
  %style{type="text/css"}
     <<<
body {
height:100%;
font-size:11px;
margin-left:5%;
margin-right:5%;
background-color:white;
color:black;
}
     &gt;&gt;&gt;
                  >>>
              %td{width="50%"}
                %pre
                  ??
                    %style{type="text/css"}
                       <<<
body {
height:100%;
font-size:11px;
margin-left:5%;
margin-right:5%;
background-color:white;
color:black;
}
                        >>>
                  ??
.table
       %p.title Here Doc Example(Renders "//" and empty lines)
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %pre
                  <<<
     <<<
line

line
//comments are rendered. When bug stomping,
//not a good idea to wisecrack on users here.
line
     &gt;&gt;&gt;
                  >>>
              %td{width="50%"}
                %pre
                  ??
                       <<<
line

line
//comments are rendered. When bug stomping,
//not a good idea to wisecrack on users here.
line
                        >>>
                  ??
    %h3 The "-" Command (Embed PHP Code)
    %P The "-" command will wrap the following code with <?PHP ... ?> tags, so that the rendered template can be evaled as PHP code (the class has a command to do it for you).
    .box
      %p.note This class was written for two groups of users, developers and web users.  The - command will create the PHP, but will not execute it, that is performed by a different class command.  So you could have web users
       create their own templates, and render them, but they cannot execute PHP on the system host, unless you--the implementor--make a subsequent "phpExec" call to the object explicitly.  You are warned.
    .box
      %p.note It is at this point that you may want to consider a much richer set of templating functionality that is achieved by using Smarty and pHAML together.
    .table
       %p.title Embedded PHP Example
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %pre
                  <<<
  - for($x;$x<=10;$x++){
    %p hello world
  - }
                  >>>
              %td{width="50%"}
                %pre
                  ?? C
                  - for($x;$x<=10;$x++){
                    %p hello world
                  - }
                  ??
            %tr
              %td{width="50%"}
                %pre
                  <<<
    %table
        - $arr = array();
        - $arr[0] = array('a','b','c');
        - $arr[1] = array('d','e','f');
        - foreach($arr as $row){
            %tr 
              - foreach($row as $col){
                %td
                  - echo $col;
              - }
        - }
                  >>>
              %td{width="50%"}
                %pre
              		?? C
	                    %table
							- $arr = array();
							- $arr[0] = array('a','b','c');
							- $arr[1] = array('d','e','f');
							- foreach($arr as $row){
							    %tr 
							      - foreach($row as $col){
							        %td
							          - echo $col;
							      - }
							- }
                  	??
                
       
       
    %h3 The "?" Command (Toggle Debug)
    %p The "?" command will toggle the debug mode.  If the debug mode is on, it is turned off, if off; it is turned on.  Debug mode will print an HTML comment before each processed line of pHAML code, which can be very useful during design.
    %h3 The "??" Command (Toggle Show HTML)
    %p The "??" command will toggle the HTML mode.  If the HTML mode is on, it is turned off; if off, it is turned on.  The HTML mode will print everything in HTML characters, allowing the generated HTML to be seen (this is used in this document).
    %h3 The "$" and "$-" Command (Insert Value from Passed PHP Array)
    %p The "$" command will turn the pHAML renderer into a simple template system.  You set the values of the assignment using the classes assign method.  If you pass an array to the render call, the text following the $ will be used as an array key.  The $- will strip the whitespace from both sides of the inserted value (good for textarea elements and such).
    %h1 Debugging
    %p.title  Motivation
    %p The debugging system inside of pHAML was developed quickly as pHAML was used to creating working sites.  It consists of two principal commands.
    %h2 The "?" (Show Line Information)
    %p The "?" can be place on a single line at any horizontal location, it is not "preceding space sensitive".  When on, an HTML comment containing useful information is created.
    .box
      %p.note The debug information is provided in a format of:
        %br
        &lt;!-- the_line_number:the_number_of_indent_spaces{the_command_if_there}[the_status_off_the_herdoc]: The pHAML line --&gt;
    .table
       %p.title Debug Command Example
       .table
         .table-contents#test
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %pre
                  <<<
  No debug info for this line, turn it on--
  ?
  This text line is simple, it is indented by 20
  /This is a comment line-see the / show up
  Now start a here doc
    &lt;&lt;&lt;
     In the here doc, see the [on]?
    &gt;&gt;&gt;
  Out of heredoc
  Turn off the debug
  ?
  This line does not have debug info  
                  >>>
              %td{width="50%"}
                %pre
                  ?? C
                    No debug info for this line, turn it on--
                    ?
                    This text line is simple, it is indented by 20
                    /This is a comment line-see the '/' show up?
                    Now start a here doc
                      <<<
                       In the here doc, see the [on]?
                      >>>
                    Out of heredoc
                    Turn off the debug
                    ?
                    This line does not have debug info  
                  ??
    %h2 The "??" (Show the HTML)
    %p The second tool in the debug toolbox is the "??" toggle, this command is "preceding space sensitive".  When on, the content that follows is converted to HTML compatible characters, so that is will show up in the browser.
       This is the command that is used to show all of the HTML results in this document.  
    .table
       %p.title Show HTML Command Example
       .table
         .table-contents
           %table{width="100%"}
            %tr
              %th pHAML
              %th HTML Result
            %tr
              %td{width="50%"}
                %pre
                  <<<
  ??
    %element#id data
  ?? 
                  >>>
              %td{width="50%"}
                %pre
                  ?? C
                    %element#id data
                  ??
    %p Makes it easy to see everything.
    %h2 The Most Useful Debug Combination
    %p.title   Combine the two commands to see both the code and debug info (use a %pre to help):
    %pre.example
        \%pre
          \?
            \??
              \%problem_element(s)
              \...
            \??
          \?    
    %h1 Installation
    %p pHAML is contained entirely in one class: class.pHAML.php.  You may put the class anywhere in your web directory, it is safe.  The easiest way to install is to put it in your class path.
    %p Just include the class in your PHP code, create an instance--and of you go.  Here is an example:
    %p
      %pre.example
        ??
          <<<
<?PHP
//include the pHAMLClass here
include('class.pHAML.php');
//create a template
$template=
'!!!!
%html
  %head
    %title Hello From pHAML!!
  %body
    %p Hello World';
//instantiate the class
$pHAML = new pHAML();
//render the content
$content = $pHAML->render($template);
//echo to the browser
echo $content;
?>
          >>>
        ??
     %p To turn pHAML into a simple templating system (good for prototyping sites), send an array along with the template, and use the "$" command.
      %pre.example
        ??
          <<<
<?PHP
//include the pHAMLClass here
include('class.pHAML.php');
//create an array composed of: name_of_variable_in_template_without_leading_dollar=>value_of_replacement_text
$values = array('greeting'=>'Hello World, I am a template!!!!');
//create a template
$template=
'!!!!
%html
  %head
    %title Hello From pHAML!!
  %body
    %p 
      $greeting';
//instantiate the class
$pHAML = new pHAML();
//render the content
$content = $pHAML->render($template,$values);
//echo to the browser
echo $content;
?>
          >>>
        ??
     %p pHAML has a recursive feature in the rendering of $key_name.  If it cannot find the key that matches in the value array,
        it will look for a template in the template array, and compile that...and so on.
     %p What template array?  Good question, the render function can take an array of templates, and will compile them all, but return only the final result
        of the one with the array key of 'contents'.  This allows the design to break into several different templates, maybe an example will help.
      %pre.example
        ??
          <<<
<?PHP
//include the pHAMLClass here
include('class.pHAML.php');
//create an array composed of: name_of_variable_in_template_without_leading_dollar=>value_of_replacement_text
$values = array('greeting'=>'Hello World, I am a template!!!!');
//create a template for a simple web site
$template['content']=
'!!!!
%html
  %head
    %title Hello From pHAML!!
  %body
    %table{width ="1300px"  border="0" cellspacing="0" cellpadding="0"}
      %tr
        %td
          $banner
      %tr
        %td
          $center
      %tr
        %td
          $footer';
$template['banner']='%b I am a banner';
$template['center']=
'I am center content, and I say
$greeting';          
$template['footer']='I am footer content';          
//instantiate the class
$pHAML = new pHAML();
//render the content
$content = $pHAML->render($template,$values);
//echo to the browser
echo $content;
?>
          >>>
        ??
     %p That is really cool...let's see the other implementations of HAML do that!  So now you can break up a web site, build a CMS, whatever.  
     %h1 Smarty Integration
     .box
       %p.note Both the Smarty and the Zend Framework implementations are used in our enterprise level web services, should you need some experience and help, please feel free to contact us.
     %p The original target of this code was a Smarty template system, to simplify writing templates.
     %h2 Smarty Considerations
     %p Smarty is a well developed template system, that in today's web server environment is fast and expandable.
        Still, you are stuck with HTML writing, and in today's Web 2.0 "div rich" world, it is easy to get lost in the
        depths of a large template.  Hours doing that led to the writing of this code.
     %p Smarty and pHAML combine to create a very powerful and fast content design tool.
     %h3 OK, so you are going to Smarty
     %p The implementation selected was a Smarty "Block" command.  Block commands are nice, since they process after the Smarty replacement.  This
        means that you can use Smarty variables, looping, commands, formating...you name it.  The pHAML code will be rendered after Smarty puts everything
        in.
     .box
       .note There are two differences in the Smarty implementation from the stand alone class.  The first is that the PHP command "-" does not exist.  This
         is because Smarty is a "compiling" template engine, and the PHP code would get parsed and run by the Smarty engine--creating a security risk.  The second is minor, Smarty passes the block as a string, so there is no array processing or assigning of template values by the pHAMLSmarty class.
         The functionality that is lost can be replaced by using Smarty assigns and Smarty variables ({$variable}).
     %h3 Bad News and Good News on "{}"'s
     %p The bad news, Smarty uses curly braces as a command delimeter.  This creates a conflict with the pHAML, IE: %element{v="v"}.  This can be solved by setting
          Smarty to use different delimeters, or the easier route of using {ldelim} and {rdelim} that Smarty offers.
          The good news, a tool has been written to do this for you, simply enter your standard pHAML code and see the Smarty
          compatible code created before your eyes,
          %a{href="http://www.appliedautonomics.com/pHAML/pHAML_Live.php"} pHAML Live tool
          \.              
     %h2 Installation
     %p There are three ways to install the pHAMLSmarty class:
        %ol
           %li Drop the block.pHAML.php class into your Smarty plugin directory, SMARTY_DIR/plugins_dir. 
           %li Put the block.pHAML.php class into a directory, and append that directory via PHP code
               using $smarty->plugins_dir[] ='your/directory'. 
           %li Use the Smarty register_block() function. 
     %h2 Smarty Examples
     %h3 Hello World
     %p Here is an example based on the Quick Start example from the Smarty Documentation:
     %p.title The PHP Code
       %pre.example
        ??
          <<<
include('Smarty.class.php');
// create object
$smarty = new Smarty;
// assign some content. This would typically come from
// a database or other source, but we'll use static
// values for the purpose of this example.
$smarty->assign('greeting', 'Hello World');
// display it
$smarty->display('index.tpl');
          >>>
        ??    
     %p.title The Smarty Template        
       %pre.example
        ??
          <<<
{pHAML}
!!!!
%html
  %head
    %title Simple Document
  %body
    %p {$greeting}
{/pHAML}
          >>>
        ??    
     %h3 Hello World
     %p Here is a more complex example based again on the Quick Start example from the Smarty Documentation:
     %p.title The PHP Code
       %pre.example
        ??
          <<<
include('Smarty.class.php');

// create object
$smarty = new Smarty;

// assign an array of data
$smarty->assign('name', array('bob','jim','joe','jerry','fred'));

// assign an associative array of data
$smarty->assign('users', array(
	array('name' => 'bob', 'phone' => '555-3425'),
	array('name' => 'jim', 'phone' => '555-4364'),
	array('name' => 'joe', 'phone' => '555-3422'),
	array('name' => 'jerry', 'phone' => '555-4973'),
	array('name' => 'fred', 'phone' => '555-3235')
	));


// display it
$smarty->display('index.tpl');

          >>>
        ??    
     %p.title The Smarty Template        
       %pre.example
        ??
          <<<
{pHAML}
%table
{section name=mysec loop=$name}
   %tr{ldelim}bgcolor="{cycle values="#eeeeee,#dddddd"}"{rdelim}
      %td {$name[mysec]}
{/section}

%table
{section name=mysec loop=$users}
   %tr{ldelim}bgcolor="{cycle values="#aaaaaa,#bbbbbb"}"{rdelim}
      %td {$users[mysec].name}
      %td {$users[mysec].phone}</td>
{/section}
{/pHAML}
          >>>
        ??
     %h2 Smarty Tips
     %p Experience has provided some quick tips on using pHAML and Smarty:
        %ol
          %li The {strip} Smarty block function is always a bad idea, it removes indents and returns, pure badness for a spacing sensitive syntax like pHAML.
     %h1 Zend Framework Integration
     %p The pHAML class is a good fit with the Zend Framework.  The pHAML object, AA_View_pHAML offers a full Zend View Interface implementation, this means that you can use pHAML in your Zend Framework solution seemlessly.
     %h2 Mind Numbing Technical Discussion
     %p The following is a deeper technical discussion of some of the theory in the implementation, you should still be able to get the examples to work without knowing all this�it is included to hopefully help in understanding.
     %p The easiest option may be to leave the Zend View object intact, and placing all of the logic into the phtml template file.  Incidentally, the default Zend View object just includes the phtml file, and wraps it with output buffer start (ob_start) and get_clean (ob_get_clean) methods.  So this is the simplest implementation, works out of the box, but requires that php code be put into each template.
     %p Everything in the Zend Framework flows through an �index.php� file, this is called the bootstrap file.  The bootstrap then creates a controller.  The controller then will call the appropriate controller class and action function call based on the url (www.myzendframework.com/controller_class/action).  The action object has a default viewer implementation, that will render the view script using a series of defaults for location and type.  This is good behavior if we want to override the action viewer helper and use pHAML system wide. 
     %p This is not so good when you want to constrain the pHAML rendering to a specific module, controller, or action.  The pHAML will compile and be added to the response object, but so will the default .phtml script, which will also be rendered and added to the response object afterwards by postDispatch afterwards.  You can prevent this by setting  �$this->getFrontController()->setParam('noViewRenderer', true);� in the controller under the action.  If you want the entire controller to turn off the native view renderer--put the command in the preDispatch.
     %p The following provides examples of each of the solutions.  Here is a copy of the httpd.conf that was used (this is a bit different than the Zend tutorial, the rewrite routes all unresolved documents through the index, simpler when adding css and such):
        %pre.example
          ??
            <<<
	Alias /hlzendex1/ "/your/web/zend/root/hlzendex1/www/"
	<Directory "/your/web/zend/root/hlzendex1/www/">
		AllowOverride None
		RewriteEngine on
		RewriteCond %{REQUEST_FILENAME} !-f
		RewriteRule ^.*$ /hlzendex1/index.php
	</Directory>        
	Alias /hlzendex2/ "/your/web/zend/root/hlzendex2/www/"
	<Directory "/your/web/zend/root/hlzendex2/www/">
		AllowOverride None
		RewriteEngine on
		RewriteCond %{REQUEST_FILENAME} !-f
		RewriteRule ^.*$ /hlzendex2/index.php
	</Directory>        
	        >>>
          ??
     %h2 Installation
     %p The best way to install is to place the pHAML class in the same library directory as the Zend directory.  That
        will allow us to use the class loader.  Simply create an /AA/View directory tree, and put the class in it.
        %pre
          \--library (Zend Library)
          \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|
          \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--AA--View
          \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|     |
          \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|      -pHAML.php
          \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--Zend
          \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|
          \&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Zend lib files)
     %h2 hlzendex1:The Simple Approach, Put Everything in the Action phtml File
     %p This is trivial to do, just use the following structure, there are five files needed (this mirrors the Zend Framework Zend_Controller Quickstart documentation):
     %p.title The index.php (Bootstrap) Code
     %p  The index is usually named /app/www/index.php (i.e. 'hlzendex1/www/index.php')
     %pre.example
        ??
          <<<
<?php
/* hlzendex1/www/index.php */
/** Zend Bootstrap File */
require_once 'Zend/Controller/Front.php';
Zend_Controller_Front::run('/your/web/zend/root/hlzendex1/controllers');          
          >>>
        ??     
     %p.title The IndexController.php Code
     %p  The controller is usually named /app/controllers/IndexController.php (i.e. 'hlzendex1/controllers/IndexController.php')
     %pre.example
        ??
          <<<
/* hlzendex1/controllers/IndexController.php */
/** Zend_Controller_Action */
require_once 'Zend/Controller/Action.php';

class IndexController extends Zend_Controller_Action
{
    public function indexAction()
    {
    }

}          
          >>>
        ??     
     %p.title The ErrorController.php Code
     %p  The controller is usually named /app/controllers/ErrorController.php (i.e. 'hlzendex1/controllers/ErrorController.php')
     %pre.example
        ??
          <<<
<?php
/* hlzendex1/controllers/ErrorController.php */
/** Zend_Controller_Action */
require_once 'Zend/Controller/Action.php';

class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
    }
}
          >>>
        ??     
     %p.title The index.phtml Template Code
     %p  The template is usually named /app/views/scripts/controller/index.phtml (i.e. 'hlzendex1/views/scripts/index/index.phtml'')
     %pre.example
        ??
          <<<
<?PHP
/* hlzendex1/views/scripts/index/index.phtml */
//The heredoc syntax works great, just backslash all of the "$"'s
$template =<<<EndOfTemplate
!!!!
%html
  %head
    %title Simple Document
  %body
    %p Hello World Simple from the .phtml Template
EndOfTemplate;
//instance and invoke
require_once('AA/View/pHAML.php');
$hl = new pHAML();
echo $hl->render($template);
?>          
          >>>
        ?? 
     %p.title The error.phtml Template Code
     %p  The template is usually named /app/views/scripts/controller/error.phtml (i.e. 'hlzendex1/views/scripts/error/error.phtml'')
     %pre.example
        ??
          <<<
<?php
/* hlzendex1/views/scripts/error/error.phtml */
//The heredoc syntax works great, just backslash all of the "$"'s
$template =<<<EndOfTemplate
!!!!
%html
  %head
    %meta{http-equiv="Content-Type" content="text/html; charset=utf-8"}
    %title Simple Document
  %body
    %h1 An error occurred
    %p An error occurred; please try again later.
EndOfTemplate;
//instance and invoke
require_once('AA/View/pHAML.php');
$hl = new pHAML();
echo $hl->render($template);
          >>>
        ??     
     %h2 hlzendex2:A Better Solution, Use AA_View_pHAML Class
     %p This is a better solution, as it allows you to render pHAML and do assigns using the Zend Framework way.
     %p.title The index.php (Bootstrap) Code
     %p  The index is usually named /app/www/index.php (i.e. 'hlzendex2/www/index.php')
     %pre.example
        ??
          <<<
<?php
/* hlzendex2/www/index.php */
/** Zend Bootstrap File */
require_once 'Zend/Controller/Front.php';
Zend_Controller_Front::run('/your/web/zend/root/hlzendex2/controllers');          
          >>>
        ??     
     %p.title The IndexController.php Code
     %p  The controller is usually named /app/controllers/IndexController.php (i.e. 'hlzendex2/controllers/IndexController.php')
     %pre.example
        ??
          <<<
/* hlzendex2/controllers/IndexController.php */
/** Zend_Controller_Action */
require_once 'Zend/Controller/Action.php';

class IndexController extends Zend_Controller_Action
{
    //uncomment the following to turn off default view for the entire module
    /*public function preDispatch()
    {
        // Turn off the default view for everything in this module
        $this->getFrontController()->setParam('noViewRenderer', true);
    }*/
    
    public function indexAction()
    {
        //grab the front controller and turn off the default view rendering
        //(you can delete this line if the noViewRenderer is set in the preDispatch)
        $this->getFrontController()->setParam('noViewRenderer', true);
        //since the class is in the Zend lib tree, can find it using the loader
        Zend_Loader::loadClass('AA_View_pHAML');
        //instance the Zend compliant class
        $view = new AA_View_pHAML();
        //tell the class where to find the template, this can be any path
        $view->setScriptPath('D:/wamp/asf/hlzendex2/views/scripts/index');
        //here is how we assign variables
        $view->assign('greeting','Hello from the index action!!');
        //pass the name of the template to be rendered
        echo  $view->render('index.hml');
    }

}          
          >>>
        ??     
     %p.title The ErrorController.php Code
     %p  The controller is usually named /app/controllers/ErrorController.php (i.e. 'hlzendex2/controllers/ErrorController.php')
     %pre.example
        ??
          <<<
<?php
/* hlzendex2/controllers/ErrorController.php */
/** Zend_Controller_Action */
require_once 'Zend/Controller/Action.php';

class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
    }
}
          >>>
        ??     
     %p.title The index.hml Template Code
     %p  The template will be in the path is set in the controller (here we use 'hlzendex2/views/scripts/index/index.hml'')
     %pre.example
        ??
          <<<
// hlzendex2/views/scripts/index/index.hml //
!!!!
%html
  %head
    %title Document With Assigns
  %body
    %p Hello World :
       $greeting
EndOfTemplate;
//instance and invoke
require_once('AA/View/pHAML.php');
$hl = new pHAML();
echo $hl->render($template);
?>          
          >>>
        ?? 
     %p.title The error.phtml Template Code
     %p  The template is usually named /app/views/scripts/controller/error.phtml (i.e. 'hlzendex2/views/scripts/error/error.phtml'')
     %pre.example
        ??
          <<<
<?PHP /* hlzendex2/views/scripts/error/error.phtml */ ?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Error</title>
</head>
<body>
    <h1>An error occurred</h1>
    <p>An error occurred; please try again later.</p>
</body>
</html>
          >>>
        ??     
     %h1 Final Notes
     %p Thank you for taking the time to read and I hope that you find pHAML as productive as we have.
     %p I am sure that we will be improving pHAML, but we will work very hard to keep it compatable with what is out there.
     %p Please feel free to use our pHAML live site to make suggestions and file bugs.
     %p The latest code drop and documentation will always be found at our pHAML live site.