To make it simple, we divide our resources into 4 different species.

This is only for resources that are able to be included into a page or template. Modules and plugins will not be part of this speciment.
- Chunks. It’s a static species, which only allow one fix chunk of code/text/content to be included in either a page or template. SO whatever value that you have in your chunk will be inserted to the chunk tag that you put in your template or content. The tag format is look like this {{chunk_name}}. Most snippet developers use this as a subtemplate to allow outputing data in certain template format. A good example will be newslisting snippet.
- Document Variables/Template Variables. It’s a dynamic species which allow the content to be different on each pages, and this need to be assigned on every template that you want to use this TV for. the tag format looks like this [*tv_name*]. If you use binding which is an input that start with @, you can output any dynamic content on tv. The reason why I combined doc vars and tpl vars, because they are almost the same species, except for the fact that pagetitle, longtitle, content, and etc are a default tv that are suppose to be available to every newly created document/page, while other TV can be assigned to specific Template to be available for the current document using that template freely. So actually, there is nothing different between [*content*] or [*other_tv_name*]. They are all the same species, and you can include or inheret them to each other and to be included in a template.
- Snippets. It’s a very dynamic species which allow programmer to include any programming logic being included in MODx page to output certain data or to process certain things. This like TV using @EVAL binding, except ith TV, if you set the page to be cached, the outputed data will be cached automatically, while in snippet you have 2 option. First you can ask MODx to cache the output using this tag format [[snippet_name]], or you can prohibit caching to the snippet using this tag format [!snippet_name!]. By calling it uncached, even if you have your page cached, the snippet will not be cached and it will be evaluated everytime the page is being requested.
- Placeholders. This is the most unknown species, but it usually an addition for snippet calling or plugin to output certain data. The tag format is [+placeholder_name+]. A good example will be newslisting snippet, which outputing certain placeholder for navigation that can be put all accross the page.
A rule of thumbs, you can include all this tag into any of those species. So I can call a snippet on a chunk, and later put the chunk on a template/page. I can also call snippet on a tv, and put tv on a page/template. I can even put a chunk on a tv, and put a snippet on that chunk, and later put the tv on the template or page. The variation is almost unlimited, and the more encapsulation that you do, there will always be a limit in the amount of the parsing function. As far as I know, MODx limit the parsing to 10 iterations, which in theory you can have 10 encapsulation/inheritance of the tag. But in practical there is certain think that might not work the way it looks to be. So the best way will be not to overuse this power and flexibility.
One thing to remember, all those thing is based on template. So MODx will always parse the data from template., and that’s why template doesn’t have any tag that can be used to be included in all those 4 speciments. So template is the root inheritence from document/page. When you create a document, it’s basically nothing, except for the fact that you just created a holder to tell MODx that there is a document with this id/alias that can be outputed to the screen. Now by assigning template to document, basically you start having this inheritence of tagging and data to be outputed to the screen.
I’ll try to explain the way how MODx parser works:
- 1. user requsting a page by id or alias, then MODx will look for that specific document/page. If nothing found, it will request a default page.
- 2. They found the page, now it’s time to look for the template associated with that specific document/page. They found it, then here comes the MODx parser. It will iterate the output based from the template and look for special MODx tags to be parsed and so on.
- 3. Parse each speciments tags described above:
[list]
[li] 3a. If they found document variables/template variables, it will fetch the data assigned to that TV specific to that current document and replace the output with the tv/docvar tag. If it’s using binding option, it will behave according to the binding functionality.
- 3b. Parse site config tag (special tag for outputing site config, not described above). This is the tag format for site config tag [(sample_tag)]. This tag is generated automatically by the system, but it will output all the general configuration such as site_url, and etc to the document.
- 3c. if they found chunks, it will fetch the chunks data and replace it with chunks tags.[/li
[list][li] 3d. If they found snippet, it will run the snippet and generate the output and include them in the template to replace the snippet tag.
- 3e. If they found placeholder, it will try to find the current placeholder name that are being assigned specific on that process. The reason why I use process instead of page/document is because placeholder is the most unique species. It doesn’t allow the end user to set their value and name, intead it’s solely to be used by snippets, plugins, and tv eval binding to output certain data. MODx default, whenever there is a page request, this placeholder data is empty, so if you use [+placeholder+] in your template or other speciment defined above, it will automatically removed by the parser. You will know when you need to use placeholder, if your snippets/plugins/tv eval binding stated that they outputed certain placeholder.
[/li]
[li] 4. Capture the formated template and redo the iteration from step 2 to parse the remaining speciment tags that haven’t been parsed by the parser on the previous run. Usually it is to parse the remaining tags that are being included inside other speciment, for example you put another tv tag inside another tv that you called inside your page template. Or it can any combination shown in the previous explanation. This iteration is limited to 10 runs only.[/li]
[/list]
In step 3, the order of the parsing is not in correct order, but it will give you guys the idea on how this MODx tag being parsed and included to return a final output that we can see as a web pages. So this robuts and flexible system won’t limit your creativity in creating a dynamic/static blocks, data or whatever other CMS system out there use, instead you have full control, as long as you guys know how the system works, and how to use it in the correct manner, following all the best practices.
Footnote: after step 4, usually the outputed data will be cached before it’s being displayed to the scree, and during this step, uncached snippet output will not be cached. So in a cached pages, this process from step 1-4 will not be repeated, instead the system will just fetch the cached output and reevaluate uncached snippets and output them to the users. It’s so simple, isn’t it
More detailed explanation, information and tutorial of each of those speciments, you can find it in our documentation.
I’m open to any correction from our expert users.
EDIT:
After further investigation, there will be 20 possible iteration on the document parser logic, with a minimum iteration at least 4. Now with the fix that I made for regClientStartupScript, the amount of max amount iteration increase from 20 to 30 and minimum amount of interation also increase from 4 to 6.
For more detailed of the iteration, most tag speciments will have a possibility to be process 30 time with the fix that I have, but any script/content included to the page using regClientScript API will only have 20 iteration. While for uncached snippet, it will only have 10 iteration from the point it produces the output and being included to the page until the final output. Same with regClientScript API that is being called on uncached snippet, it will only have 10 iteration, after it’s being included.[/list]