After creating a fresh MODX install, the next step is often to install a number of extras to add functionality to the site.
The usual set is well-known:
- getResources for list your documents
- getPage for pagination of your lists
- Wayfinder for build menus
- Breadcrumb(s) for, hm, breadcrumbs
- GoogleSitemap for sitemap
But it's possible to replace all of them with one package: pdoTools!
Let's start with an introduction of what pdoTools can do.
9 snippets
Yes, I'm serious. pdoTools contains 9 snippets that can perform almost any functionality of usual website. And almost all of them are a drop-in replacement for other popular snippets.
pdoResources
pdoResources is a replacement for getResources.
As all other snippets in pdoTools, it doesn't use xPDO objects for representation of resources. It works directly with database tables. This makes it faster.
You don't have to convert resources dates to timestamps before you can pass pass them to "date" output filter. And it joins only needed TVs, so you must specify them in the &includeTVs
property as comma-separated list.
[[pdoResources?
&parents=`0`
&includeTVs=`my_tv1,my_tv2`
&tvPrefix=`tv.`
&processTVs=`1`
&includeContent=`1`
&showLog=`1`
]]
One of the most important features of pdoTools is the &showLog
property. It allows you to check how fast the snippet is. Is it a slow SQL query, or too complicated chunk? The &showLog
property will help you figure it out.
The second important feature is SQL joins. With pdoResources you can create complex queries and select only what you need.
[[!pdoResources?
&parents=`0`
&class=`modResource`
&leftJoin=`{
"Parent": {
"class": "modResource",
"on": "modResource.parent = Parent.id"
},
"CreatedBy": {
"class": "modUserProfile",
"on": "modResource.createdby = CreatedBy.internalKey"
}
}`
&select=`{
"modResource": "modResource.id, modResource.pagetitle",
"Parent": "Parent.pagetitle as parent",
"CreatedBy": "CreatedBy.fullname as author"
}`
&showLog=`1`
]]
With the above example, you don't have to call any snippets or output filters to get the parent of the resource or the creator name. How fast it works? Let's look at the log output..
There are many other cool features, but these are the most important.
pdoPage
pdoPage is a replacement for getPage. There are a few differences compared to getPage:
- It do not shows empty pages. If you do not have results on the page, or the user entered wrong page manually - you will get redirected to the first page.
- It has a property
&maxLimit
, which is set to 100 by default. It makes sure users can not slow down your site by setting&limit=100000
in the url. If you are using getPage - just try to do it on your site. - It sets metatags to previous and next pages for crawlers in the page header.
- It has built-in ajax pagination. Here's how that works:
<div id="pdopage">
<div class="rows">
[[!pdoPage?
&parents=`0`
&ajaxMode=`default`
]]
</div>
[[!+page.nav]]
</div>
Of course, you can change the markup by specifying additional parameters to snippet.
pdoMenu
This snippet can replace Wayfinder. It mostly works the same, but it is a bit faster.
Because xPDO objects are bypassed, you need to check permissions of items in menu with a special property manually:
[[!pdoMenu?
&parents=`0`
&checkPermissions=`list`
]]
By default, all permission checks are disabled. This property can be used on all pdoTools snippets, by the way.
pdoUsers
This snippets lists users of your site. You can filter them by groups and roles:
[[!pdoUsers?
&groups=`Authors`
&sortdir=`asc`
]]
You can combine this with pdoPage to provide a paginated list of users:
[[!pdoPage?
&element=`pdoUsers`
&groups=`Authors`
&roles=`Member`
&sortby=`id`
&sortdir=`asc`
]]
[[!+page.nav]]
Placeholders are all fields from the modUser
and modUserProfile
objects. You can see them all if you will just set blank &tpl
parameter (or do not set it at all, if snippet does not have a default tpl value).
The empty &tpl
is another common feature of all pdoTools snippets.
pdoSitemap
pdoSitemap creates a fast sitemap that does not require the resource to be set to XML if the property &forceXML
is enabled (by default).
It caches data, and the cache key depends on the snippet params, but you can also set your own key.
To see how fast it is, we can test it by disabling &forceXML
and enabling &showLog
. On my site it takes almost 30 seconds for the first run and only 0.03 for the second:
[[!pdoSitemap?
&forceXML=`0`
&showLog=`1`
]]
There are 6873 resources in my sitemap.
pdoNeighbors
Snippet for make links to previous, next and upper pages of the current document.
[[!pdoNeighbors?
&sortby=`menuindex`
&sortdirc=`desc`
]]
pdoCrumbs
My version of a simple snippet for breadcrumbs on the site. Nothing special, except it uses the pdoTools core with fast chunks processing and data fetching.
[[!pdoCrumbs]]
pdoTitle
This snippet generates the "title" tag of pages. It runs pdoCrumbs and shows the path to the current document in the title.
<title>[[!pdoTitle]] / [[++site_name]]</title>
It supports pdoPage by default, so you will see the number of pages in title.
<title>Questions / page 5 from 593 / Sections / mysite.com</title>
Crawlers love it!
pdoField
And, finally, pdoField is a snippet that allows you to get any field from any resources. It is a replacement both for UltimateParent and getResourceField snippets.
For example, we need to get longtitle
of resource with id = 15
[[pdoField?
&id=`15`
&field=`longtitle`
]]
Or if we want to get pagetitle
of grandparent of current document:
[[pdoField?
&id=`[[*id]]`
&field=`pagetitle`
&top=`2`
]]
Conclusion
I can write more and more about pdoTools, but this is enough for the first article. In the next two articles I will talk about speed, and the pdoParser.
It is important to remember, that all pdoTools snippets use the same core and most parameters can be used for all of them.
You can use &showLog
to see how the snippets work, you can specify empty chunks to see the available placeholders, and you can join tables on the fly.
pdoTools is a library, not just set of snippets. Many MODX extras uses pdoTools for their own snippets, like miniShop2, Tickets, BannerY, AjaxForm, and more.
The biggest drawback of pdoTools is the limited English documentation. All we have is here https://github.com/bezumkin/Docs/tree/master/en/01_Components/01_pdoTools. If you're interested, you can help by adding more pages to the documentation.
And don't forget that all of snippets parameters are described inside them. Just open the snippet in the manager and see the Properties tab.