We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 23219
    • 18 Posts
    Hi all,

    I used to work with Smarty and basic PHP templating. The idea of templating is to separate the display logic from the processing logic.
    Recently I was trying to do just this with MODx. So what I’m looking for is the best way to achieve this with this CMS.

    Here is basically a thing:

    - You create a snippet - which a picks up an array from a database and place it in a PHP variable
    - You use this array output in either template or chunk or the page itself but you want to apply some formatting

    So far I only found and seen snippets doing the entire thing - without separation. However the preferred way of doing this is not like that.

    First part of the problem are arrays. When I used setPlaceholder I found no way to place an array into it. Instead I found a workaround - recursive setPlaceholders function (used in Ditto for example) that separates the items with dots e.g. [+arrayvar1.subarray1+].

    OK, let’s say that isn’t the problem, you can always copy-paste setplaceholders function.

    But the second part is worse: now you need to format the array output e.g.

    <table cellspacing="0" cellpadding="5" border="1">
    <?php foreach($users as $user): ?>
    <tr>
    <td><?=$user[’id’];?></td>
    <td><?=$user[’name’];?></td>
    <td><a href="mailto:<?=$user[’email’];?>"><?=$user[’email’];?></a></td>
    <tr>
    <?php endforeach; ?>
    </table>

    This is simply formatting an array $users into a 3 column table in some imaginary template. No big deal.

    But the problem is - because Chunks don’t execute PHP code, this type of formatting is impossible so you have to use snippets to create the HTML. There goes the separation of display logic and the business logic.

    Maybe I haven’t looked hard enough into the available examples and sources but at this moment I don’t see better way than to use snippets to "template" the custom output.

    Does anyone have better idea?
      • 34127
      • 135 Posts
      I think I understand what you’re saying: most of the snippets you see output HTML themselves, when the output should be formatted in a chunk itself. I came across the same issue recently when building a polling snippet/module (which I’m planning on posting in the dev forum shortly laugh ). It’s easy to create a chunk for the basic poll layout, but the rows themselves need to repeat to show the choices. I hate having HTML markup in my PHP code, so I felt that a much better way would be to create a separate chunk just for the repeating rows.

      What I did was create a placeholder for the repeating data (call it "repeater") and put it where the rows would appear. Bow, obviously setPlaceholder isn’t going to work here, because, it’s my understanding that chunks are cached when they’re called (correct me if I’m wrong). So if you call it multiple times on the same chunk, it’s just going to repeat the same results over and over. str_replace works just as well then. I created two additional variables: one for a copy of the chunk (so we have something with the original placeholder later), and another for the final result of the repeating rows. The chunk itself contains more placeholders for each bit of repeating data. So I loop through an array of data (from an SQL query), replace the placeholders with the data (we’re using the copy variable for this) with a foreach loop. After the foreach loop is done, we concatenate the final result variable with the result from the foreach loop. We then copy the original value of the chunk back over the copy (which currently has NO placeholders -- they’ve been replaced with the last result), and then after the rows have finished repeating, we simply assign the final value to the placeholder in the "big" chunk.

      Hopefully that made sense... I’ve spent the afternoon remodeling my living room and sometimes I shout incoherent things. rolleyes If it doesn’t make sense, I’ll post my poll snippet within a couple of days and you can have a look at what I’ve done.
        • 23219
        • 18 Posts
        @ganeshXL:
        no problem for static variables, only for repeating ones e.g. lines from the array presented in the table

        @Eleventeen:
        I had to read that few times to understand it.

        So basically you created a template engine smiley
        Yes, the repeating lines are the problem.

        That gave me following idea (basically the similar thing but different in approach):

        1. create a chunk with the following type of data for the repeating variables - i’ll use %% for my own formatting - of course you can use anything else:

        <table>
        <!-- the following could be for example some parameters for the universal parser -->
        <!-- begin repeat start=1 end=20 step=2 -->
        <tr>
        <td>%%somedata1%%</td>
        <td>%%somedata2%%</td>
        <td>%%somedata3%%</td>
        </tr>
        <!-- end repeat
        <td>

        of course, you can "call" these repeaters anytime in the chunk.

        2. load a chunk and parse it and look for "repeater" comments. obviously you need a parser function that will parse this data. anything between begin and end is repeated in a loop and %% variables are replaced with actual data using str_replace. This could be done as separate snippet called at the end of the original snippet. it would be basically a very simple template engine.

        3. store the output of this processed chunk template in a variable and return it as output at the end of the snippet.

        4. use [[snippetname]] instead of chunk - but the chunk really holds the template data.

        Now obviously there are problems. You won’t be able to use anything else in such templates like [+variables+] so you’d have to apply similar mechanism for formatting output of static (non-repeating) variables as well. But this looses the point of CMS then.

        I also hate to put HTML in my snippets but so far that seems the most elegant solution.

        Perhaps when you post that code for polling snippet that could give me some more ideas...
          • 22303 MODX Staff
          • 10,725 Posts
          This is how snippets can use chunks to replace placeholders at the time of execution. This way the placeholders will be processed at the time the chunk is included in your output (or set to another placeholder).

          $output.= $modx->parseChunk('chunkName', $modx->placeholders, '[+', '+]');
            • 23491 ☆ A M B ☆
            • 1,056 Posts
            Quote from: OpenGeek at Aug 20, 2007, 11:34 AM

            $output.= $modx->parseChunk('chunkName', $modx->placeholders, '[+', '+]');


            Yes, parseChunk is your friend! It is especially nice being able to pass an array of placeholders to replace, NTM custom placeholder identifiers ([+, +])

            If you ever need to manipulate the cached version of your chunk (prior to output), simply reference via:

            $modx->chunkCache['name_of_chunk']
            


            In some instances, I have even forced HTML into $modx->chunkCache solely for the purpose of using $modx->parseChunk.
              Mike Reid - www.pixelchutes.com
              MODx Ambassador / Contributor
              [Module] MultiMedia Manager / [Module] SiteSearch / [Snippet] DocPassword / [Plugin] EditArea / We support FoxyCart
              ________________________________
              Where every pixel matters.
              • 23219
              • 18 Posts
              Thanks guys,

              That one helped! I also discovered that Wayfinder uses similar templating and places single row into a chunk which obviously it calls and repeats the rows as much as needed.

              Also found an example for this on the wiki if someone else looks for similar thing:
              http://wiki.modxcms.com/index.php/API:parseChunk