Речь пойдет о вызове внешних файлов PHP через сниппеты, при выводе ресурса.

Все чаще использую в шаблонах такой сниппет [ [inc_out?&outFile=`/assets/cppv/QandA/getCustJsCss.php`]]. Сниппет примитивен по содержанию, но очень крут для тех кто понимает.

Вот его содержание:
	<?php
include($_SERVER['DOCUMENT_ROOT'].$outFile);
    

Смысл этого чуда - подключать произвольный PHP код в шаблоны, чанки и т.п. без создания сниппета. Что очень удобно.

Вся мощь в возможности передать неограниченное количество параметров:
[ [inc_out?
&outFile=`/assets/cppv/TPL/m.php`
&var1=`:FILE /assets/cppv/TPL/katalog/var1.tpl`
&var2=`:PHP /assets/cppv/TPL/katalog/var2.php`
&var3=`:CHUNK var3`
&pagetitleC=`:CODE <h3>[*pagetitle*]</h3>`
&contentC=`:FILE /assets/cppv/TPL/USLUGI/ReclPoligraf/konverty.tpl`
&headCustomC=`:CODE <?script src='assets/cppv/TPL/USLUGI/ReclPoligraf/ReclPoligraf.js'>
              <?link rel='stylesheet' href='assets/cppv/TPL/USLUGI/ReclPoligraf/ReclPoligraf.css'/>
`
]] 
    

Как было сказано выше вызов сниппета из шаблонов выглядит так:

[ [имяСниппета?
    &имяПарам1:`значПарам1`
    &имяПарам2:`значПарам2`
    &имяПарам3:`значПарам3`
    ]]
    
При этом в сниппете параметры доступны как обычные переменные PHP:
   
      $out="";
      $out.='$имяПарам1='.$имяПарам1;
      .......
      echo $out;
    
Если в сниппете подключить внешний файл таким образом:
[ [имяСниппета?
    &имяПарамФ:`имяФайла`   //напр. &outFile=`/assets/cppv/TPL/m.php`
    &имяПарам1:`значПарам1`
    &имяПарам2:`значПарам2`
    &имяПарам3:`значПарам3`
    ]]
    
Казалось бы: ну что?
А то, что в файле `имяФайла` все переменные будут доступны как массив $arrParam=$modx->event->params. Естественно если его подключить(include($_SERVER['DOCUMENT_ROOT'].$outFile);)
   
    <?php
      if(isset($modx)) {
         $arrParam=$modx->event->params;
         foreach($arrParam as $k=>$p){              //$k - key placeholders
           $keyP=substr($p, 1, strpos($p,' ')-1);   //$keyP - key type
           $varP=substr($p,strpos($p,' ')+1);       //$varP - value type
           if($keyP==='FILE'){
             $filename=$_SERVER['DOCUMENT_ROOT'].$varP;
             if(!file_exists($filename)) {
                echo $filename, ' NOT EXIST!!!';       
             }else{        
                $fCont=file_get_contents($_SERVER['DOCUMENT_ROOT'].$varP);     
                $modx->placeholders[$k]=$fCont;        
             } 
           }
        }
      }
    
Далее можно расставить плейсхолдеры($modx->placeholders[$k]=$fCont;) И во всех нижерасположенных чанках и просто в шаблоне они будут доступны по тэгу [[+имяПлейсхолдера]]

Может показаться что все это несколько замороченно. Для простой лигики на сайте, может действительно не стоит так делать. Но когда есть ветвления, когда у нескольких страниц при одном шаблоне, нужно включать индивидуальные куски(не влезая в контент) и прочее, без подобного решения не обойтись. Это лучше, чем плодить несколько шаблонов. Хотя у каждого свой стиль. Мне лично нравится так. И все новые сайты, даже простые, делаю только так. По мне лучше набросать php скрипт, чем корячиться с фильтрами и модификаторами. К тому же подключение внешних php файлов позволяет редактировать у себя на компе, в любимом редакторе.

Т.к. вызовы PHP идут в данном случае через сниппеты из ресурса - то можем получить ИД текущего ресурса.

       $idResurs=$modx->resourceIdentifier;
    
Далее в некоторых примерах делают запрос к базе и получают запись. Или объект.
    $res=$modx->getObject("modResource",56);
    
И из него уже получают все поля черех синтаксис XPDO. Тут описано как. Но поскольку мы уже в ресурсе, надо полагать уже все выбрано. И на самом деле все поля находятся в массиве $modx->resource->_fields:
$modx->resource->_fields=Array
(
    [id] => 4
    [type] => document
    [contentType] => text/html
    [pagetitle] =>NEW my page
    [longtitle] => 
    [description] => 
    [alias] => new-page
    [link_attributes] => 
    [published] => 0
    [pub_date] => 0
    [unpub_date] => 0
    [parent] => 0
    [isfolder] => 0
    [introtext] => 
    [content] => 
    [richtext] => 1
    [template] => 3
    [menuindex] => 3
    [searchable] => 1
    [cacheable] => 1
    [createdby] => 2
    [createdon] => 1495722298
    [editedby] => 2
    [editedon] => 1495723425
    [deleted] => 0
    [deletedon] => 0
    [deletedby] => 0
    [publishedon] => 0
    [publishedby] => 0
    [menutitle] => 
    [donthit] => 0
    [privateweb] => 0
    [privatemgr] => 0
    [content_dispo] => 0
    [hidemenu] => 0
    [class_key] => modDocument
    [context_key] => web
    [content_type] => 1
    [uri] => 
    [uri_override] => 0
    [hide_children_in_tree] => 0
    [show_in_tree] => 1
    [properties] => 
    [_content] => ....  //- тут код шаблона. Один раз пропарсенный.
    [_isForward] =>
    [cppvSeoKeyWords] => Array
        (
            [0] => cppvSeoKeyWords
            [1] => я из лесу вышел, я снова зашел, и так раз 20, кто этот парень с гитарой!
            [2] => default
            [3] => 
            [4] => text
        )

    [migxSlider] => Array
        (
            [0] => migxSlider
            [1] => [{"MIGX_id":"1","title":"\u041e\u041e\u041e \"\u0412\u0441\u0435 \u041e\u041a!\"","image":"orderPage\/pageTest\/12.jpg","descr":"1231312312312312<\/p>"},{"MIGX_id":"2","title":"\u041e\u0410\u041e \"\u0412\u043e\u0445\u0442\u043e\u0433\u0430\"","image":"orderPage\/pageTest\/13.jpg","descr":"\u0443\u043a\u0443\u0446\u043a\u0443\u0446\u043a\u0446\u0443\u043a\u0446\u0443\u043a\u0443\u0446\u043a<\/p>"},{"MIGX_id":"3","title":"\u0418\u041f \u041f\u043e\u043f\u043e\u0432\u0430 \u041d.\u0418.","image":"orderPage\/pageTest\/3.jpg","descr":"\u044b\u0444\u0432\u0444\u044b<\/strong><\/em> \u0444\u044b\u0432 \u0444\u0444\u044b\u0432 \u0444\u0444\u044b\u0432<\/p>"},{"MIGX_id":"4","title":"\u041e\u041e\u041e \"\u041a\u0430\u043a \u043d\u0438\u0431\u0443\u0434\u044c\"","image":"orderPage\/pageTest\/2.jpg","descr":"\u0446\u0443\u043a\u043a\u0443 \u0441\u043c \u0446\u0443\u043a\u0446 \u0443\u043a\u0446\u043a\u0446\u043a\u0446\u0443\u043a\u0446\u0443<\/span><\/em><\/p>"},{"MIGX_id":"5","title":"\u0421\u0425\u041f \"\u0423\u0441\u0442\u044c-\u041a\u0443\u0431\u0435\u043d\u0441\u043a\u043e\u0435\"","image":"orderPage\/pageTest\/14.jpg","descr":"\u043a\u0446\u0443\u043a\u0443\u0446\u043a \u043c\u0446\u0443\u043a\u0446\u0443\u043a \u0446\u0443<\/em>\u043a\u0446\u0443<\/p>"}]
            [2] => default
            [3] => 
            [4] => migx
        )
    
)
Т.е. чтобы получить заголовок выводимого ресурса(страницы):
$PageTytle=$modx->resource->_fields['pagetitle'];
А к TV:
$PageTytle=$modx->resource->_fields['cppvSeoKeyWords'][1];

Плейсходеры - это переменные, принициализированные где-то в сниппетах и PHP, которые потом отображаются в тэги [[+имя_плейсхолдеоа]]. Условие - чтобы инициализация была перед тэгом. Хотя, если учесть многопроходность парсера, должно быть без разницы. Но по возможности лучше до, чтоб понапрасну не напрягать парсер.

Мне часто приходится менять чанки вывода товаров. Иногда много времени уходит, пока пройдещь несколько уровней вызовов чанков, сниппетов, опять чанков. Да еще фильтры и модификаторы. Приходилось даже документировать. Помучавшись вволю я стал применять вызов внешнего PHP. Там выбираю все необходимое, расставляю плейсхолдеры. А потом в одном чанке расставляю все плейсхолдеры. В PHP:

    .....
    $modx->placeholders['CustHead']=$fCont;
в чанке:
      
    [[+headC]]
	[[+CustHead]]    
	.....
Как бы не был крут Smarty и модификаторы MODX, на PHP код намного эффективнее и проще.

PS

У вас может возникнуть вопрос: откуда я знаю про $modx->resource->_fields и прочее. Ответ классический: "Читайте первоисточники!". Т.е. исходники).