Re: your mail

[email protected] (matthew patton) Tue, 29 Feb 2000 12:36:32 -0500 (EST)
Newsgroups php.template
Message-ID <[email protected]>
On Mon, 28 Feb 2000, Andrei Zmievski wrote:

> Ouch, %s? Come on, we're talking about designers here. They need to see
> how the things are named.

well, OK. that's what I was going to use inline comments for.
The thing is, the printf() style construct is rather useful when you've
got multiple variables per block. I'm not completely clear but I think
yours does support this, yes? And a designer is only worried about layout,
and the comments should provide him enough of a contextual reference to
figure it out. What the designer DOES NOT know though is the program flow
that is going to be controlled by the programmer. You can try to say
iterate thru arrays yourself by looping the template section but as I was
trying to demonstrate (poorly purhaps) is that the looping only works for
the simple case and runs into problems. Then again purhaps it's up to the
programmer to unroll the complex datastructure into a flat array. Now the
question is how do you indicate the loop iteration is over and to start
anew?

I've thought about it a bit more and here is my v0.2 proposal.

I think an example (better this time I hope) illustrates what I mean:
Scenario = weekly invoicing. I'm going to skip the HTML tags for
brevity. This is the output I want to happen.

Customer1
	item1_count item1_SKU (desc) item1_price subtotal
	item2_count ....
	item3_count ...

Customer2
	item1_count ....

Having looked at HTML::Template now, I see what you're trying to achieve.
Thus my data structure would look like (note, these are all values):

instance = { customer1,
	     {
		{ item1,
		  { quantity1,
		    price1,
		    descr1
		  }
		},
		{ item2,
		  { quantity2,
		    price2,
		    descr2
		   }
		},
		...
	     }
	  }

I then build an array of these instances. (BTW I can make this nesting
even deeper without much trouble. ex. group by PurchaseOrders, group by
day of week, or quantities of the same items bought on different days have different
prices etc.)

Let's call this array of 'instances', "orders."
so then I do in my main php file:

	<?php include(my_template_file) ?>

We have yet to introduce any non-standard PHP constructs.

So my template file looks something like this:
<HTML>
...
<TABLE>
<TR><TD>put column headers here</TD></TR>
<?php section $orders
  <TR><TD COLSPAN=3>$_customer</TD></TR>
  <?php section
    if #ODD
      <TR BGCOLOR="red">
    else
      <TR BGCOLOR="blue">
    <TD>$_item</TD>
    <?php section
      <TD>$_quantity<TD>$_price<TD>$_description
    ?>
  ?>
?>
...
<?php section $something_else
...
?>
</HTML>

What have I done? I've extended the PHP grammar with a single keyword
"section". The outermost section block takes a variable, the inner ones
don't unless they want to key off something else. It basically means that
the template parsing engine now knows which
varible is the one it needs to use. When an inner section specifies a
different variable, all those sections nested inside of it use that same
variable. When the nesting levels pop back up, the original variable is
resumed on subsequent processing.

Notice also in this example that the nesting of section blocks
corresponding precisely to where an array would be. In the case of only 1
customer and only 1 item bought, You'd still use the multidimentional
array since that is a special case. I would suggest that as the engine is
walking thru the structure and finds an element that is an array and it
can't find a nested "section" block then it 1) skips the element, and
2) logs an error as the section and provided data structure would appear
to be out of sync. This is not too surprising if the HTML monkey in
question does a massive reorganization of the layout. Feedback to the
developer will be required.

What I haven't addressed very well is terminating a section. I think 
though that "?>" should be adequate. PHP does support the nesting of
<?php ... ?> blocks, right? If not, I have a problem - maybe a magic
keyword called "end_section" would be OK.

Now here's another interesting twist. Notice that my
"plcae_holder" variables ($_customer, $_item, $_quantity, $_price) are
just that. Those names DO NOT EXIST in the passed multi-dimentional array
which is strictly a bunch of values. (this relieves the
programmer and the template engine from having to deal with
that particular mess) Furthermore, their visibility is restricted to
within enclosed "section" blocks. In other words, if you have a variable
in the main PHP file with the same name, it's value will be substituted
instead of being assigned the apropriate value from the parameter
array. (this may not be a desireable feature as it requires 'safe'
variable naming practices but it's the only way I can think of.) But on
the other hand a variable first seen within a section block will not be
visible to the rest of the PHP file or to outer "section" blocks. ie. it
will get unset as soon as execution pops out of a "section".

A further detail on the place_holder variables. They keep their values
while within an iteration of a session (eg. if a variable is
unset, assign it the value, otherwise skip). So let's suppose I want to
modify the item details section of my HTML like this:

      <TD>$_quantity ($_quantity)<TD>$_price
      <TD>$_description<TD>Subtotal: $_quantity * $_price

($_quantity has the same value, it was only assigned once, and doesn't
shift the array pointer)
and the numerical multiplication value is substituted to accompany
"Subtotal:". Now I'm not sure I like this "immediate evalutation" of
variables in templates but it can keep the amount of code down. Then
again, I think putting

	Subtotal: echo($_quantity * $_price)

is just as good. Perhaps we can support both?

Also, nested templates can
see the "place_holder" vars defined in outer layers but not the other way
around. So if wanted to keep a running total of the items customer1
ordered, I'd have to declare $_item_total in the customer (outermost in
this case) template scope and then within the items scope do

	$_item_total += $_quantity

There are a few more things that I haven't addressed in this alternative
design. Whether or not to URL escape variables, what to do about default
values [ maybe $_variable ?= default_value ], repeating etc. But at first
blush I think these "features" do not need special handling but for
the most part simply use already built-in PHP functions and program logic.

> borrowed some ideas from that. I wonder if you can tell us why you don't
> like the proposed template language and for what reasons.

My biggest issue is that yor propsal instroduces a dozen extra function
calls which break away from already available PHP functionality. I mean,
why have your own if/else construct? Use what already exists. Why make
your template (which is only going to work with PHP anyway), looks like
some alian creature? If for whatever reason logic NEEDS to be in the
template file, I don't have that luxury from the looks of
things. Should I have to precompute everything and worry about
getting variable order straight? I don't think so. (see 
Subtotal: example) Other benefits include not having to write your own
parsing engine, adding "section" as a recognized keyword of the main
parser is probably a whole lot easier. As is support for section only
variables like #FIRST, and immidiate evaluation and output of
variables. Third, your propposed process doesn't appear to handle more
than a level or two of nesting and the implementation will likely be very
hairy.

To be honest I was shocked that PHP didn't already have template
support. I was even further chagrined to notice that the database calls
are a mishmash of inconsistancy. PHP apparently expects me to rewrite
large chunks of code when I switch database engines? That's real funny.

-- 
Network Security Technologies Inc. - Commercial support for OpenBSD
www.netsec.net       (703) 561-0420       [email protected]

"Government is not reason; it is not eloquence; it is force!
 Like fire, it is a dangerous servant and a fearful master."
  - George Washington