MODX Revolution meets Fenom
recently in the English-speaking community of MODX a lot of discussion on the topic "how we live". All at stoppage to discuss the upcoming (in a few years, I believe) major version 3, and we still are improving their add-ons current.
A new event that I would like to share with a wider audience is the new release of pdoTools Fenom template engine, which will allow you to get rid of the clutter of tags in terms of chunks and rewrite them in plain language the template engine.
The procedure does not require changes in the site, simply update pdoTools to version 2.0 and you can use new syntax. The best part is that the MODX tags are the perfect complement to Fenom and work together without any problems. A simple example for starters:
the
So, the parser pdoTools is a separate class that is prescribed in the system settings MODX and intercepts the processing of the tags on the page.
In older versions of the component, the inclusion of the parser had to confirm with the installation, but with version 2.1.1-pl it is enabled by default. If, for some reason, you do not like it, delete the system settings.
the
By default MODX does not have these settings, they only need to connect a third-party parser, as in our case.
the
pdoParser can be used in two cases:
the
the
In the class pdoTools for this there are 2 methods that are very similar to those in the class modX:
the
The main feature of these methods is that to download the chunk used protected method _loadChunk, which can not only load the chunk from the database and converts them into arbitrary strings.
the
So, both methods pdoTools support the following types of names of chunks:
One of the most popular options — an indication of the body of the chunk right on the page. For example:
the
This indication is a feature which many people do not think — all the placeholders inside the chunk will be processed by the parser up of the call to the snippet.
That is, if you call the snippet on the page like so:
the
and in the memory of the system exhibited the placeholders
the
Just the same value, which put some other snippet before. That is why in the example we have such unusual placeholders —
You can use curly brackets as a frame of placeholders in all chunks pdoTools — he will turn them into
For this reason, you will never work challenges snippets and filters to INLINE chunks. the so will not work:
the
As pdoTools understands both the syntax for it test 2 — mode MODX tags and Fenom.
In the scripts there is an indication limit = 10, then in table I include the figures with his increase:
the
Now, let's complicate chunks — add them in the generation of links for a resource and the output
the
and
the
the
As you can see, processing chunks via pdoTools in all cases faster.
Much that chunks Fenom there is a minimum to start, which is due to the need to compile the template.
the
Let's summarize the capabilities of the parser pdoTools:
the
At the moment pdoTools downloaded more than 40,000 times from official repository and more than 10 000 of repository modstore.pro, which gives hope for a wide spread of new technologies of standardization in MODX.
A big thank you to abrowser aco a great templating engine!
Article based on information from habrahabr.ru
A new event that I would like to share with a wider audience is the new release of pdoTools Fenom template engine, which will allow you to get rid of the clutter of tags in terms of chunks and rewrite them in plain language the template engine.
The procedure does not require changes in the site, simply update pdoTools to version 2.0 and you can use new syntax. The best part is that the MODX tags are the perfect complement to Fenom and work together without any problems. A simple example for starters:
the
{if $parent == 3}
[[!pdoMenu?parents=`0`]]
{else}
[[!pdoResources?parents=`1,2,3`]]
{/if}
Under the cut is a huge amount of information about the parser pdoTools that I have never collected in one place.So, the parser pdoTools is a separate class that is prescribed in the system settings MODX and intercepts the processing of the tags on the page.
In older versions of the component, the inclusion of the parser had to confirm with the installation, but with version 2.1.1-pl it is enabled by default. If, for some reason, you do not like it, delete the system settings.
the
-
the
- parser_class — the class name of parser the
- parser_class_path — the class path of the parser
By default MODX does not have these settings, they only need to connect a third-party parser, as in our case.
the
working Principle
pdoParser can be used in two cases:
the
-
the
- when rendering a chunk with a snippet — it happens always and in all the snippets that use pdoTools, regardless of the system settings. the
- when rendering the page — but only if parser is enabled in the system settings.
the
Processing chunk
In the class pdoTools for this there are 2 methods that are very similar to those in the class modX:
the
-
the
- getChunk — complete processing of a chunk, it can use the native parser MODX the
- parseChunk — just substitute the placeholders for the values modParser is not called
The main feature of these methods is that to download the chunk used protected method _loadChunk, which can not only load the chunk from the database and converts them into arbitrary strings.
the
chunks
So, both methods pdoTools support the following types of names of chunks:
@INLINE or @CODE
One of the most popular options — an indication of the body of the chunk right on the page. For example:
the
[[!pdoResources?
&parents=`0`
&tpl=`@INLINE <p>{{+id}} - {{+pagetitle}}</p>`
]]
This indication is a feature which many people do not think — all the placeholders inside the chunk will be processed by the parser up of the call to the snippet.
That is, if you call the snippet on the page like so:
the
[[!pdoResources?
&parents=`0`
&tpl=`@INLINE <p>[[+id]] - [[+pagetitle]]</p>`
]]
and in the memory of the system exhibited the placeholders
[[+id]]
or [[+pagetitle]]
, then the snippet will be processed as a chunk and you get on the page same line, like:the
15 test
15 test
15 - test
Just the same value, which put some other snippet before. That is why in the example we have such unusual placeholders —
{{+}}
is [[+]]
. The system parser will not touch them, and pdoTools replaces them with normal during operation.You can use curly brackets as a frame of placeholders in all chunks pdoTools — he will turn them into
[[+]]
at startup.For this reason, you will never work challenges snippets and filters to INLINE chunks. the so will not work:
the
[[!pdoResources?
&parents=`0`
&tpl=`@INLINE <p>[[+id]] - [[+pagetitle:default=`page title`]]</p>`
And so — without problems.
the [[!pdoResources?
&parents=`0`
&tpl=`@INLINE <p>{{+id}} - {{+pagetitle:default=`page title`}}</p>`
]]
Be aware of this caveat when using INLINE chunks.
@FILE
Many people accuse MODX is that it cannot store chunks in file and forces the extra time to work with the database. It is inconvenient for a version control system, and slower.
With version 2.2 of MODX proposes to use for these purposes, the static elements, but for several reasons, this method may still be less convenient than direct work with the files.
pdoTools offers such an opportunity when specifying @FILE:
the [[!pdoResources?
&parents=`0`
&tpl=`@FILE resources/mychank.tpl`
]]
For security purposes, you can only use files with rasshireniem html and tpl, and only from a certain, predetermined directory. The default is: /assets/elements/chunks/
.
You can specify your own directory for files using the &tplPath
:
the [[!pdoResources?
&parents=`0`
&tpl=`@FILE resources/mychunk.tpl`
&tplPath=`/core/elements`
]]
The file will be loaded from the file /core/elements/resources/mychunk.tpl
from the root of the site.
@TEMPLATE
This type of the chunk allows you to use the system templates (i.e. objects modTemplate) to receive the output.
the [[!pdoResources?
&parents=`0`
&tpl=`@TEMPLATE Base Template`
]]
If you specify an empty pattern and in the selected records field template
with the id or name of the template, the record will be wrapped in this template:
the [[!pdoResources?
&parents=`0`
&tpl=`@TEMPLATE`
]]
It's such an analogue of a snippet renderResources.
When you output the template, you can specify a set of parameters (as in snippets):
the [[!pdoResources?
&parents=`0`
&tpl=`@TEMPLATE Base Template@MyPropertySet`
]]
Then the values from this set will be inserted into the template.
Common chunks
This is the default mode that loads the chunk from the database:
the [[!pdoResources?
&parents=`0`
&tpl=`MyChunk`
]]
Similarly, the supported parameter sets are:
the [[!pdoResources?
&parents=`0`
&tpl=`MyChunk@MyPropertySet`
]]
These ways of loading chunks work all native pdoTools snippets and all others that use methods pdoTools getChunk
and parseChunk
.
the getChunk Method
The Declaration of this method looks like this:
the getChunk(string $chunkName, array $properties, bool $fastMode = false)
Method loads the specified chunk (following the instructions @BINDING, if any) and fully ablative it, replacing all the placeholders on the passed value (parameter $properties).
The third parameter, fastMode
cuts out all the remaining unprocessed placeholders, to avoid unnecessary tags on the page. If this is not done, then the parser will attempt to recursively parse tags (up to 10 iterations by default), which can lead to slow down.
Recursive parser is one of the advantages of MODX and intentionally left tags are very common in the logic of the snippets system. Therefore, fastMode
is disabled by default and you need to use it only if you are confident in what you do.
Parser pdoTools will not cause the system parser if was able to parse all placeholders. If the chunk were some calls filters or snippets, the work is passed to modParser that requires additional processing time.
the Method parseChunk
And this method is declared like this:
the parseChunk(string $name, array $properties, string $prefix = '[[+', string $suffix = ']]')
It also creates a chunk from the specified name, sorting @BINDING, if any, and then simply replace the placeholders with values, without special treatments.
This is the easiest and fastest way of processing data in chunks.
the Edit page
If pdoParser enabled in the settings, it is called to process the entire page when displaying it to the user.
When you use this parser all the chunks and add MODX processed a little faster. Only "little" because it does not take filters and conditions, processing only simple tags, like [[+id]]
and [[~15]]
. However, he does modParser faster, because it does not create any objects.
In addition to possible gain speed, you get more and new opportunities for convenient output of data from different resources.
the Tags fastField
At the end of 2012 the public were presented small plugin to add new tags to the MODX parser, which then grew into component fastField.
It adds to the system processing more of the placeholders, type [[#15.pagetitle]]
. With permission, this functionality is already included in pdoParser, and even slightly expanded.
FastField tags all begin with #
and then contain or id of the desired resource, or the name of the global array.
Conclusion conventional resource fields:
the [[#15.pagetitle]]
[[#20.content]]
TV resource settings:
the [[#15.date]]
[[#20.some_tv]]
Goods field miniShop2:
the [[#21.price]]
[[#22.article]]
Arrays of resources and products:
the [[#12.properties.somefield]]
[[#15.size.1]]
Superglobal arrays:
the [[#POST.key]]
[[#SESSION.another_key]]
[[#GET.key3]]
[[#REQUEST.key]]
[[#SERVER.key]]
[[#FILES.key]]
[[#COOKIE.some_key]]
You can specify any fields in arrays:
the [[#15.properties.key1.key2]]
If you don't know what values are inside the array — just select it and it will be printed in full:
the [[#GET]]
[[#15.colors]]
[[#12.properties]]
Tags fastField can be combined with MODX tags:
the [[#[[++site_start]].pagetitle]]
[[#[[++site_start]]]]
the Fenom Template engine
Support Fenom template engine appeared in pdoTools with version 2.0, after which it began to require PHP 5.3+.
It works much faster than native modParser and if you rewrite your chunk so that it will not be a single tag, MODX, modParser and not to run. Of course, simultaneous operation of the old tags and the new in one chunk allowed.
Processed by the template engine be affected by the following system settings:
the
the - pdotools_fenom_default — enables processing via Fenom chunks pdoTools. Enabled by default.
the - pdotools_fenom_parser — enables the processing of a template of all pages of the website. That is, not only of chunks and templates.
the - pdotools_fenom_php — includes support for PHP functions in the template engine. Very dangerous, as any Manager will have access to PHP right out of the chunk.
the - pdotools_fenom_modx — adds system variables
{$modx}
and {$pdoTools}
in the templates Fenom. Also very dangerous — any Manager can manage objects of MODX chunks.
the - pdotools_fenom_options — a JSON string with an array of customization according to the official documentation. For example:
{"auto_escape":true,"force_include":true}
the - pdotools_fenom_cache — caching Kopeliovich templates. Only makes sense for complex chunks on working sites, is disabled by default.
So, by default, Fenom included only in chunks that pass through pdoTools. It is quite safe and the managers of the system do not acquire any additional than a more convenient syntax and high-speed operation.
The inclusion of pdotools_fenom_parser allows you to use the syntax Fenom directly in the content of documents and page templates, but there is one caveat — the template engine may not react to the curly parenthesis that in MODX very much.
In such cases, the author recommends to use the tag {ignore}.
If you plan to include Fenom globally for the whole site, you need to check whether all pages it works fine.
Syntax
For a start I advise to read official documentation, and then we will discuss syntax in relation to MODX.
All variables from the snippets passed to the chunk as they are and overwrite the old chunks to the new syntax — a real pleasure.
the
MODX
Fenom
the
[[+id]]
{$id}
the
[[+id:default=`test`]]
{$id ?: 'test'}
the
[[+id:is=`:then=`test`:else=`[[+pagetitle]]`]]
{$id == "? 'test': $pagetitle}
To use a more complex entity, provided pdoParser service variable {$_modx}, which gives secure access to some variables and methods in the system.
the
MODX
Fenom
the
[[*id]]
{$_modx->resource.id}
the
[[*tv_param]]
{$_modx->resource.tv_param}
the
[[%lexicon]]
{$_modx->lexicon('lexicon')}
the
[[~15]]
{$_modx->makeUrl(15)}
the
[[~[[*id]]]]
{$_modx->makeUrl($_modx->resource.id)}
the
[[++system_setting]]
{$_modx->config.system_setting}
In addition, you available variables:
the {$_modx->config} system settings
the {$_modx->config.site_name}
{$_modx->config.emailsender}
{$_modx->config['site_url']}
{$_modx->config['any_system_setting']}
the {$_modx->user} — an array of the current user. If it is authorized, then added the data from the profile:
the {if $_modx->user.id > 0}
Hi, {$_modx->user.fullname}!
{else}
You need to log in.
{/if}
the {$_modx->context} — an array with the current context
the You are in the context of {$_modx->context.key}
the {$_modx- > resource} — an array with the current resource, you have seen in the examples above
the {$_modx->resource.id}
{$_modx->resource.pagetitle}
{$_modx->makeUrl($_modx->resource.id)}
the {$_modx->lexicon} is the object (not array!) the modLexicon that can be used to download arbitrary dictionaries:
the {$_modx- > lexicon- > load('msearch2:default')}
Check dictionaries msearch2: {$_modx->lexicon('ms2gallery_err_gallery_exists')}
The output records are handled by a separate function {$_modx->lexicon()}
.
Placeholders with the point
Fenom uses a point to access the array value, and so usually fistulae MODX placeholders array. Appropriately, the tag [[+tag.sub_tag]] analogues in the Fenom is not provided.
Therefore, for these placeholders you need to use the second service variable is {$_pls}:
the {$_pls['tag.subtag']}
Output of snippets and chunks
Variable {$_modx}
actually is a simple and safe class microMODX
Therefore, snippets and chunks are called
the {$_modx- > runSnippet('!pdoPage@PropertySet', [
'parents' => 0,
'showLog' = > 1,
'element' => 'psoResources',
'where' => ['isfolder' = > 1],
'showLog' = > 1,
])}
{$_modx- > getPlaceholder('the page.total')}
{$_modx- > getPlaceholder('the page.nav')}
As you can see, the syntax is almost identical to PHP that opens new opportunities. For example, you can define arrays, instead of JSON strings.
By default, all snippets are called cached, but you can add !
before the name — tags in MODX.
If the call to the snippet uses the native method MODX, then the output chunks start pdoTools, and you can use all of its features:
the {$_modx->getChunk('MyChunk@PropertySet')}
{$_modx- > parseChunk('MyChunk', [
'pl1' => 'placeholder1',
'pl2' => 'placeholder2',
])}
{$_modx->getChunk('@TEMPLATE Base Template')}
{$_modx->getChunk('@INLINE
Site name: {$_modx->config.site_name}
')}
{$_modx->getChunk(
'@INLINE Transmission peremennoi in chunk: {$var}',
['var' => 'Test']
)}
{$_modx->getChunk('
@INLINE pass a variable in the snippet call:
{$_modx- > runSnippet("pdoResources", [
"parents" => $parents
])}
Total results: {$_modx- > getPlaceholder ('total')}
',
['parents' => 0]
)}
The above examples are a little crazy, but it is currently working.
cache Management
The object {$_modx} available services modX::cacheManager, which allows you to set an arbitrary time caused by the caching of snippets:
the {if !$snippet = $_modx- > cacheManager- > get('cache_key')}
'parents' => 0,
'tpl' => '@INLINE {$id} - {$pagetitle}',
'showLog' = > 1,
])}
{set $null = $_modx- > cacheManager- > set('cache_key', $snippet, 1800)}
{/if}
{$snippet}
To see this cache in /core/cache/default/
in the example it is saved for 30 minutes.
set $null = ...
is needed to cacheManager- > set
gave 1 (i.e. true) to the page.
And you can run the system processors (if you have enough)
the {$_modx- > runProcessor('resource/update', [
'id' => 10,
'alias' => 'test',
'context_key' => 'web',
])}
authorization Check
As the object user in the {$_modx}
, the methods of verification and authorization of access rights is outside the class:
the {$_modx->isAuthenticated()}
{$_modx->hasSessionContext('web')}
{$_modx->hasPermission('load')}
Other methods
These methods should be familiar to all developers of MODX, so just show them examples:
the {$_modx->regClientCss('/assets/css/style.css')}
{$_modx- > regClientScript('/assets/css/script.js')}
{$_modx->sendForward(10)}
{$_modx- > sendRedirect('http://yandex.ru')}
{$_modx->setPlaceholder('key', 'value')}
{$_modx- > getPlaceholder('key')}
{if $res = $_modx- > findResource('url to/doc/')}
{$_modx- > sendRedirect( $_modx->makeUrl($res) )}
{/if}
the Extension templates
Use of Fenom template engine allows you to include some chunks (in other templates) and even to expand them.
For example, you can just load the contents of the chunk:
the Common chunk {include 'chunk'}
Template modTemplate {include 'template:name of template'}
Chunk with a set of parameters
{include 'chunk@propertySet'}
{include 'template:Name@propertySet'}
Read more about {include} read in the official documentation.
A much more interesting feature — {extends} templates, it requires an enabled system settings pdotools_fenom_parser.
Write a basic template "Fenom Base":
the <!DOCTYPE html>
<html lang="en">
<head>
{include 'head'}
</head>
<body>
{block 'navbar'}
{include 'navbar'}
{/block}
<div class="container">
<div class="row">
<div class="col-md-10">
{block 'content'}
{$_modx->resource.content}
{/block}
</div>
<div class="col-md-2">
{block 'sidebar'}
Sidebar
{/block}
</div>
</div>
{block 'footer'}
{include 'footer'}
{/block}
</div>
</body>
</html>
It includes the usual chunks (which, by the way, the usual placeholders from MODX component Theme.Bootstrap) and defines several block{block}
, which can be expanded in a different template.
Now write "Fenom Extended":
the {extends 'template:Fenom Base'}
{block 'content'}
<h3>{$_modx->resource.pagetitle}</h3>
<div class="jumbotron">
{parent}
</div>
{/block}
So you can write a base template and extend its child.
It is also possible to write and extend chunks, just note that to work with modTemplate you need to specify the prefix template:, and no chunks — they work by default in all {include}
and {extends}
.
the performance Testing
Create a new site and add to it a 1000 resources so the console script:
the <?php
define('MODX_API_MODE', true);
require 'index.php';
$modx- > getService('error','error.modError');
$modx- > setLogLevel(modX::LOG_LEVEL_FATAL);
$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
for ($i = 1; $i <= 1000; $i++) {
$modx- > runProcessor('resource/create', array(
'parent' => 1,
'pagetitle' = > 'page_' . rand ()
'template' => 1,
'published' => 1,
));
}
Then create 2 chunk: modx
and fenom
with the following content, respectively:
the <p>[[+id]] - [[+pagetitle]]</p>
and
the <p>{$id} - {$pagetitle}</p>
And add two cantilever test script. For the native parser MODX
the <?php
define('MODX_API_MODE', true);
require 'index.php';
$modx- > getService('error','error.modError');
$modx- > setLogLevel(modX::LOG_LEVEL_FATAL);
$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
$res = array();
$c = $modx- > newQuery('modResource');
$c->select($modx- > getSelectColumns('modResource'));
$c->limit(10);
if ($c->prepare() && $c->stmt->execute()) {
while ($row = $c->stmt->fetch(PDO::FETCH_ASSOC)) {
$res .= $modx- > getChunk('modx', $row);
}
}
echo number_format(microtime(true) - $modx- > startTime, 4), 's<br>';
echo number_format(memory_get_usage() / 1048576, 4), 'mb<br>';
echo $res;
And pdoTools:
define('MODX_API_MODE', true);
require 'index.php';
$modx- > getService('error','error.modError');
$modx- > setLogLevel(modX::LOG_LEVEL_FATAL);
$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
$pdoTools = $modx- > getService('pdoTools');
$res = array();
$c = $modx- > newQuery('modResource');
$c->select($modx- > getSelectColumns('modResource'));
$c->limit(10);
if ($c->prepare() && $c->stmt->execute()) {
while ($row = $c->stmt->fetch(PDO::FETCH_ASSOC)) {
$res .= $pdoTools- > getChunk('fenom', $row);
//$res .= $pdoTools- > getChunk('modx', $row);
}
}
echo number_format(microtime(true) - $modx- > startTime, 4), 's<br>';
echo number_format(memory_get_usage() / 1048576, 4), 'mb<br>';
echo $res;
As pdoTools understands both the syntax for it test 2 — mode MODX tags and Fenom.
In the scripts there is an indication limit = 10, then in table I include the figures with his increase:
Limit | MODX | pdoTools (MODX) | pdoTools (Fenom) |
10 | 0.0369 s 8.1973 mb | 0.0136 s 7.6760 mb | 0.0343 s 8.6503 mb |
100 | 0.0805 s 8.1996 mb | 0.0501 s 7.6783 mb | 0.0489 s 8.6525 mb |
500 | 0.2498 s 8.2101 mb | 0.0852 s 7.6888 mb | 0.0573 s 8.6630 mb |
1000 | 0.4961 s 8.2232 mb | 0.1583 s 7.7019 mb | 0.0953 s 8.6761 mb |
Now, let's complicate chunks — add them in the generation of links for a resource and the output
menutitle
:the
<p><a href="[[~[[+id]]]]">[[+id]] - [[+menutitle:default=`[[+pagetitle]]`]]</a></p>
and
the
<p><a href="{$_modx->makeUrl($id)}">{$id} - {$menutitle ?: $pagetitle}</a></p>
Limit | MODX | pdoTools (MODX) | pdoTools (Fenom) |
10 | 0.0592 s 8.2010 mb | 0.0165 s 7.8505 mb | 0.0346 s 8.6539 mb |
100 | 0.1936 s 8.2058 mb | 0.0793 s 7.8553 mb | 0.0483 s 8.6588 mb |
500 | 0.3313 s 8.2281 mb | 0.2465 s 7.8776 mb | 0.0686 s 8.6811 mb |
1000 | 0.6073 s 8.2560 mb | 0.4733 s 7.9055 mb | 0.1047 s 8.7090 mb |
As you can see, processing chunks via pdoTools in all cases faster.
Much that chunks Fenom there is a minimum to start, which is due to the need to compile the template.
the
Conclusion
Let's summarize the capabilities of the parser pdoTools:
the
-
the
- Quick operation the
- Download of chunks from different sources, including files the
- tag Support fastField the
- Support Fenom template engine
the-
the
- template Inheritance the
- Extension templates the
- Secure access to advanced features of MODX
At the moment pdoTools downloaded more than 40,000 times from official repository and more than 10 000 of repository modstore.pro, which gives hope for a wide spread of new technologies of standardization in MODX.
A big thank you to abrowser aco a great templating engine!
How would you get these in fenom:
ОтветитьУдалить[[#POST.key]]
[[#SESSION.another_key]]
[[#GET.key3]]
[[#REQUEST.key]]
[[#SERVER.key]]
[[#FILES.key]]
[[#COOKIE.some_key]]