
mFilter
Faceted filtering for MODX 3 with SEO URL support


MODX system events for extending mFilter.
The plugin handles the following events:
| Event | Description |
|---|---|
OnHandleRequest | SEO URL routing |
OnLoadWebDocument | CSS/JS inclusion |
OnDocFormSave | Cache invalidation |
OnCacheUpdate | mFilter cache cleanup |
OnResourceDelete | Cleanup of related data |
Fires when the mFilter service is initialized. Used for:
| Parameter | Type | Description |
|---|---|---|
mfilter | MFilter | Main class instance |
<?php
// Plugin on event OnMFilterInit
/** @var MFilter\MFilter $mfilter */
$mfilter = $modx->event->params['mfilter'];
// Register custom filter type
$mfilter->getFilterTypeRegistry()->register(
'mytype',
new MyNamespace\MyFilterType($modx)
);<?php
/** @var MFilter\MFilter $mfilter */
$mfilter = $modx->event->params['mfilter'];
// Register source for custom table
$mfilter->getSourceRegistry()->register(
'myproducts',
new MyNamespace\MyProductsSource($modx, $mfilter)
);Handles incoming request, resolves filter SEO URL.
sendForward() to target resource| Placeholder | Description |
|---|---|
mfilter.filters | Array of active filters |
mfilter.sort | Sort (price-asc) |
mfilter.sortBy | Sort field |
mfilter.sortDir | Sort direction |
mfilter.page | Page number |
mfilter.limit | Items per page |
mfilter.seo.h1 | SEO H1 |
mfilter.seo.title | SEO Title |
mfilter.seo.description | SEO Description |
mfilter.seo.canonical | Canonical URL |
mfilter.seo.noindex | Noindex flag |
Includes frontend assets (CSS/JS) on pages.
Disable auto-include: mfilter.register_frontend = false
System setting mfilter.frontend_assets:
[
"[[+cssUrl]]web/mfilter.css",
"[[+jsUrl]]web/core/ApiClient.js",
"[[+jsUrl]]web/mfilter.js"
]Fires when a resource is saved.
Fires when MODX cache is cleared.
Fires when a resource is deleted.
<?php
/**
* My mFilter Extension
*
* Events: OnMFilterInit
*/
if ($modx->event->name !== 'OnMFilterInit') {
return;
}
/** @var MFilter\MFilter $mfilter */
$mfilter = $modx->event->params['mfilter'];
// Your extension codecore/components/mypackage/elements/plugins/OnMFilterInit<?php
// Plugin: mFilterLogger
// Events: OnMFilterInit
$mfilter = $modx->event->params['mfilter'];
// Add hook on filter apply
$mfilter->getFilter()->addHook('afterApply', function($result, $params) use ($modx) {
$modx->log(
modX::LOG_LEVEL_ERROR,
'[mFilter] Applied filters: ' . json_encode($params['filters']) .
', Results: ' . $result['total']
);
});<?php
// Plugin: mFilterValidator
// Events: OnMFilterInit
$mfilter = $modx->event->params['mfilter'];
// Validate before apply
$mfilter->getFilter()->addHook('beforeApply', function(&$params) use ($modx) {
// Limit max price
if (isset($params['filters']['price']['max'])) {
if ($params['filters']['price']['max'] > 1000000) {
$params['filters']['price']['max'] = 1000000;
}
}
});<?php
// Plugin: mFilterAnalytics
// Events: OnMFilterInit
$mfilter = $modx->event->params['mfilter'];
$mfilter->getFilter()->addHook('afterApply', function($result, $params) use ($modx) {
// Send to Google Analytics via Measurement Protocol
$data = [
'v' => 1,
'tid' => 'UA-XXXXX-Y',
'cid' => session_id(),
't' => 'event',
'ec' => 'filter',
'ea' => 'apply',
'el' => json_encode($params['filters']),
'ev' => $result['total']
];
// Async send
$ch = curl_init('https://www.google-analytics.com/collect');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
curl_close($ch);
});