19

What's the most elegant templating (preferably in pure PHP!) solution you've seen?

Specifically i'm interested in handling:

  1. Detecting in a repeating block whether it's the first or last element
  2. Easy handling of odd/even cases, like a zebra striped table, or similar
  3. Other modulos logic, where you'd do something every n'th time.

I'm looking for something that makes this less of a pain:

<?php
$persons = array('John', 'Jack', 'Jill', 'Jason');
?>

<?php $i = 0; ?>
<?php if (isset($persons)): ?>
<ul>
<?php foreach ($persons as $name): ?>
    <li class="<?= ($i++ % 2 === 0) ? 'odd' : 'even' ?>"><?= $name ?></li>
<?php endforeach ?>
</ul>
<?php endif ?>

Does it really take the mess above to create something like this below?

<ul>
    <li class="odd">John</li>
    <li class="even">Jack</li>
    <li class="odd">Jill</li>
    <li class="even">Jason</li>
</ul>

Is it only me that find the above near hideous?

All those starting and closing of php-tags makes me cringe.

alain.janinm
  • 19,951
  • 10
  • 65
  • 112
David
  • 1,031
  • 2
  • 10
  • 11

17 Answers17

11

You don't need to open the tags more than once. You can also make a function out of it if you do the same thing multiple times:

<?php
function makeul($items, $classes) {
  $c = count($classes);
  $out = "";

  if (isset($items) && count($items) > 0) {
    $out = "<ul>\n";
    foreach ($items as $item) {
      $out .= "\t<li class=\"" . $classes[$i++%$c] . "\">$item</li>\n";
    }
    $out .= "</ul>\n";
  }
  return $out;
}
?>

other page content

<?php
$persons = array('John', 'Jack', 'Jill', 'Jason');
$classes = array('odd', 'even');
print makeul($persons, $classes);
?>

Also, if you don't mind using Javascript, Jquery makes things done mod 2 pretty easy (e.g., for zebra striping a table):

$("tr:odd").addClass("odd");
$("tr:even").addClass("even");
Randy
  • 3,972
  • 19
  • 25
  • Totally agree with you here - no need to overcomplicate the solution when PHP already offers itself as a templating language. You can drop the 'classes' argument (at least in the default case) since the classes will normally be 'odd' + 'even'. – Bobby Jack Nov 04 '08 at 10:50
  • well, the function is written more generic so you can also pass more than two alternatives for classes. as you can see, modulo is taken according to count($classes). – markus Dec 08 '08 at 09:56
  • 1
    99%: "\"" . htmlspecialchars($classes[$i++%$c] . "\">" . htmlspecialchars($item) / "\n"; – jmucchiello Jan 09 '09 at 03:23
7

Tiny But Strong

www.tinybutstrong.com

It doesn't make the smarty mistake of embedding another macro language in the page, but does allow you to handle every practical web display issue I've ever thrown at it. In particular the above odd/even constructs are a doddle. For something like your code selecting from a database table

In the PHP file

$TBS->MergeBlock('blk1',$sqlconnect, "SELECT name from people ");

And in the HTML file

<ul>
    <li class="odd">[blk.name;block=ul]</li>
    <li class="even">[blk.name;block=ul]</li>
</ul>

And that's it. Notice that the HTML is completely Dreamweaver compatible. Furthermore if I wanted to make that alternate over three line styles all I'd need to do is add the extra line, maybe with different classes, so

<ul>
    <li class="linestyle1">[blk.name;block=ul]</li>
    <li class="linestyle2">[blk.name;block=ul]</li>
    <li class="linestyle3">[blk.name;block=ul]</li>
</ul>
Cruachan
  • 15,733
  • 5
  • 59
  • 112
5

A small help on the looping:

<? $b=false; foreach($MyList as $name) { ?>
   <li class="row<?= $b=!$b ?>"><?= htmlspecialchars($name); ?></li>
<? } ?>

By saying $b=!$b, it automatically alternates between true and false. Since false prints as "", and true prints as "1", then by defining css classes row and row1, you can get your altering rows without any trouble.

consider using :first-child css to style the first one differently.

gahooa
  • 131,293
  • 12
  • 98
  • 101
4

It ain't pure PHP (the templating syntax then), but it works realy nice; Smarty.

For loops you can do:


<ul>
{foreach from=$var name=loop item=test}
  {if $smarty.foreach.loop.first}<li>This is the first item</li>{/if}
  <li class="{cycle values="odd,even"}">{$var.name}</li>
  {if $smarty.foreach.loop.last}<li>This was the last item</li>{/if}
{/foreach}
</ul>
fijter
  • 17,607
  • 2
  • 25
  • 28
  • 10
    I know it's popular, but I think Smarty is one of the worst public libraries ever. – Peter Bailey Oct 02 '08 at 19:02
  • 3
    And why is it one of the worst public libraries? – fijter Oct 02 '08 at 19:26
  • 7
    I don't have enough space in these comments to write a real answer, but basically because it's a complete other language, and there are many things wrong with that. Maintainability, performance, transferrability, etc. It's just not a development approach I agree with. – Peter Bailey Oct 02 '08 at 19:47
  • 2
    And that example looks absolutely terrible! I'll take: "" any day. – Bobby Jack Nov 04 '08 at 10:52
  • 2
    -1 agreed. Smarty is evil. It just forces you to use *two* scrippting languages *in the same page*. There are better ways – Cruachan Feb 05 '09 at 21:30
  • Smarty isn't very secure either, I believe. – Eli Jun 27 '09 at 18:27
  • 1
    Personally Smarty is one of the only frameworks for PHP (other than Zend) I think is remotely worth using. It's worth noting the W3C website itself uses Smarty (Check the source of http://www.w3.org/). – Iain Collins Jan 11 '10 at 17:11
3

have you considered phptal?. one main benefit of it (or something similar) is that you get templates which can pass validation. most php template engines seem to ignore this.

Owen
  • 82,995
  • 21
  • 120
  • 115
3

I use PHPTAL for templating because it is written in 100% actual HTML with placeholder data, so it even works in a WYSIWYG editor for a web designer. That and it's just way easy to understand.

Here's what it would look like for me. Please forgive the markup, I'm new here and the four spaces block wasn't working right for me (the list was a list, not the markup).

PHP Code:

  $tal = new PHPTAL;
  $tal->setTemplate('people.htm')
      ->set('people', array('John', 'Jack', 'Jill', 'Jason'));
  echo $tal->execute();

Template:

  <ul>
    <li tal:repeat="person people" tal:content="person">John Doe</li>
  </ul>

Output:

  • John
  • Jack
  • Jill
  • Jason
  • Now obviously I wouldn't make a template for this little, but I could use a macro for it or build a whole page and include that variable. But you get the idea. Using PHPTAL has just about tripled my speed at templating and programming, just by the simplicity (no new syntax to learn like smarty).

    Robert K
    • 30,064
    • 12
    • 61
    • 79
    • 1
      How would you do zebra striping with phptal? I was doing the following, but it looks too verbose: item value item value – starmonkey Nov 25 '08 at 04:56
    • 1
      Not reading the manual careful enough? ;) http://phptal.org/manual/de/split/tal-attributes.html
    • does the trick. – Vadim Ferderer Jun 27 '09 at 08:36