1

I find myself creating various tables for tabular data quite a bit, and would like to create a macro that can dynamically create tables based on a data structure defined in the calling template (not in the PHP code). Here's a simplistic example:

<!-- Define the macro -->
<tal:block metal:define-macro="table">
    <table>
        <tr tal:repeat="row data">
            <td tal:repeat="col row" tal:content="col" />
        </tr>
    </table>
</tal:block>

<!-- Use the macro -->
<tal:block tal:define="data ???" metal:use-macro="table" />

What I'm looking for is how to define data (an array structure) from within PHPTAL itself. The reason I can't define this as a template variable in PHP (ex. $tpl->data = array(...)) is because the order and layout of the data belongs in the template. So, for example, if I wanted to flip the X and Y axes of the table, I should only have to modify the template, not the PHP code.


Edit:

To give an example, say I have arbitrary template variables foo, bar, and baz. I can use these in the templates like so:

<span tal:content="foo" /><br />
<span tal:content="bar" /><br />
<span tal:content="baz" />

How can I construct these variables into a two-dimensional data structure of rows and columns which I can then feed into a table-generating macro? Something like this (note: this doesn't actually work):

<tal:block tal:define="data [foo, bar; baz]" metal:use-macro="table" />

Where the desired output from the macro would be:

<table>
    <tr>
        <td>foo</td>
        <td>bar</td>
    </tr>
    <tr>
        <td>baz</td>
    </tr>
</table>

And later on, if I wanted to swap the positions of foo and bar, I'd only need to modify the template and change the definition of data to data [bar, foo; baz].

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
FtDRbwLXw6
  • 27,774
  • 13
  • 70
  • 107

2 Answers2

1

You should probably use helper methods, e.g. either php:transpose_table(input_data) or wrap it in a TALES function:

function phptal_tales_transposed($expr, $nothrow) {
    return 'transpose_table(' . phptal_tales($expr, $nothrow) . ')';
}


<tal:block tal:define="data transposed:input_data" metal:use-macro="table" />

Transposition or sorting in PHPTAL itself would be unnecessarily complicated (PHPTAL is not XSLT :)


Answer to edit :)

If you want to combine multiple variables into array, then use:

<tal:block tal:define="data php:array(foo, bar, baz)" metal:use-macro="table" />

array_chunk() function may be useful if you want to have certain number of columns.

and if you like custom syntax, then write phptal_tales_… function that translates your […] syntax to PHP code.

Kornel
  • 97,764
  • 37
  • 219
  • 309
  • I'm not sure how this would apply to my particular problem? – FtDRbwLXw6 Dec 14 '11 at 18:09
  • Please see my edit. Maybe this explains my problem a bit better. Thanks :) – FtDRbwLXw6 Dec 14 '11 at 18:14
  • Since TALES functions need to evaluate to expressions, it's very difficult to convert a string to 2-dimensional array without help from `json_decode()` or similar built-in goodies. I came to the conclusion that `php: array(...)` syntax will be necessary. Thanks for your help :) – FtDRbwLXw6 Dec 15 '11 at 22:23
  • @drrcknlsn: I don't see where the difficulty is: `array(array(),array())` is a valid expression in PHP. You can also do `array_chunk($1d_array, $number_of_columns)`. – Kornel Dec 15 '11 at 23:01
  • The `array(array(),array())` syntax is what I decided to use. It does not require a TALES function, as it's defined directly in the template. If I had tried to do it via TALES, I would have had to find some way of converted a string representing a 2D array (ex. `a,b,c;x,y,z`) into an actual array `array(array('a', 'b', 'c'), array('x', 'y', 'z'))` within an expression. Because the number of columns is unknown, this is actually a very difficult thing to do. – FtDRbwLXw6 Dec 16 '11 at 20:36
0

For a Generic Table Generation: PHPTAL: Repeat Column headers and values

<table>
    <thead>
        <tr>
            <th tal:repeat="r results/0">${repeat/r/key}</th>
        </tr>
    </thead>
    <tbody>
        <tal:block tal:repeat="r results">
        <tr>
           <td tal:repeat="t r">${t}</td>
        </tr>
        </tal:block>
    </tbody>
</table>