Modx Evo Api Mode

Режим API нужен во многих случаях. Естественно, что админка создана для пользователей. Но для программиста чаще удобнее многие вещи делать в коде PHP. Тут уж как вырываешься в степь после душной комнаты). А там уж не обойтись без API. Вернее, можно. Но удобнее с API. Все таки не стоит впадать в пуризм и пренебрегать удобством и комфортом парсера modx. К тому же написание чанков - вообще то дело верстальщика. Но если не контролировать это процесс, можно скатиться в хаос. Приходилось видеть, когда владея только возможностями админки, верстальщики создавали монстрообразные многоуровневые чанки с бесконечным вызовом сниппетов, снова чанков. Приходилось иной раз пол-дня разматывать все связи. Тоже самое можно сделать одним чанком и одним сниппетом. Но это уже другой разговор. Особая вещь - обработка ajax-запросов. Много читал я про извращения с прерываемыми ресурсами, плагинами. Практика показала, что тут больше геморою, чем толку.

Скрипт-ответку на ajax-запрос я, как и многие, называю коннектором. Может это и не очень правильно. Ну да ладно. Далее речь пойдет о скриптах запускаемых вне модх. Т.е. автономно. Например если хотим подсунуть Яндексу онлайн XML-карту сайта. Можно, конечно создать ресурс, но проще запустить внешний скрипт. Чтоб не корячиться с "человеческими урлами", шаблонами, чанками, сниппетами. Иногда удобнее, когда все в одном компактном скрипте. Если мы хотим использовать api modx, парсить чанки, сниппеты, то нужно загрузить сам объект модх. И проинициализировать его. Я использую след код. Взят из генератора XML-карты сайта.

    
<?php

$MngrDir=$_SERVER['DOCUMENT_ROOT'].'/manager';

define('MODX_MANAGER_PATH', $MngrDir."/");
require_once(MODX_MANAGER_PATH . 'includes/config.inc.php');
require_once(MODX_MANAGER_PATH . 'includes/protect.inc.php');
define('MODX_API_MODE', true);
require_once(MODX_MANAGER_PATH.'/includes/document.parser.class.inc.php');

session_name($site_sessionname);
session_id($_COOKIE[session_name()]);
session_start();

$modx = new DocumentParser;
$modx->db->connect();
$modx->getSettings();
$modx->config['site_url'] = isset($request['site_url']) ? $request['site_url'] : '';

header('Content-Type: text/xml'); 
После этого можно вызывать методы api. Пользоваться DB-api, парсить чанки, запускать сниппеты и прочее.

Не удалось мне это сделать просто и быстро. Тут словил проблемы. Парсилось не полностью. Меня по началу это сильно озадачило. Нашел таки решение, когда парсятся чанки и сниппеты. Необходимо сначала загрузить текст чанка. И потом пропарсить. На остальном не проверял. Короче делаю вот так:

  • Загрузка шаблона(чанка): $tpl=file_get_contents($_SERVER['DOCUMENT_ROOT'].'/assets/TPL/ditto.tpl');
  • Если хотите пропарсить реальный чанк, хранящийся в базе MODX: $tpl = $modx->getChunk('ditto_blog'); Надо помнить, что эта функция вернет только текст чанка(сырой чанк). Необработанный. Как есть.
  • Назначаем плейсхолдеры: $arr=array(var1=>"val1",var2=>"val2", ... ); $modx->placeholders=$arr; Тут надо осторожнее. Чтоб не затереть существующие. Естественно, если будете использовать стандартные плейсхолдеры (id, pagetitle, ...) - этот шаг не надо делать.
  • Парсим наш текст: $out=$modx->parseDocumentSource($tpl); .
  • Некоторые программеры советуют еще вызвать: $out = $modx->evalSnippets($out); Но я не заметил, что это что-то дает. Как-то обхожусь без этого. Сниппеты и на предыдущем шаге отлично обрабатываются.
Можно, очевидно, написать функцию. Но не советую. Иначе быстро забудете откуда ноги растут. А это чревато...

Есть функция parseText. Например:

$txt = $modx->parseText($text, array( 'name' => 'modx.im', 'type' => 'site', 'url' => 'http://modx.im' ), '[+', '+]' );
    
Которая делает 1 проход и тупо подставляет элементы массива вместо тэгов "[+.....+]". И толку от нее совершенно никакого.

Еще одна функции parseChank. Такая же тупая и бесполезная. Использует предыдущую ("parseText"), но для чанка.

Здесь, как правило, без проблем:

    $txt = $modx->runSnippet('MySnippet',   array( 'ID' => 34, 
                .....
                
                ));
    

В последнее время часто этим пользуюсь. Это так же способ подключения функций с обратным вызовом (колбэки). Очень полезная и крутая вещь. Техника такова:

  1. Запускаем сначала сниппет. В нем определяем все функции.
  2. Ниже, в чанке запускается сниппет с вызовами этих функций.
Вы спросите: ну и что тут особенного? А то, что "подсовывая" разные функции, мы можем влиять на вывод одного и того же сниппета. Очень популярный и удобный сниппет eForm использует этот метод для назначения колбэков.

[!Snippet1!]

< ?php
    function myCallBack(&$fields)
		{
			global $modx;
			$id = $fields['prod_id'];
			if (!is_numeric($id)) return;
			$url = $modx->makeUrl($id, '', '', 'full');
			$pagetitle = $modx->db->getValue('Select `pagetitle` from '.$modx->getFullTableName('site_content').' where `id`='.$id);	
....
....
....
Надо помнить, что в функциях modx не виден, поэтому надо не забывать добавить:global $modx;.

Далее идет сниппет с вызовами наших функций

[!Snippet2?
&callBack1=`myCallBack`
.....
.....
.....
!]    

В вызываемом PHP-коде все параметры доступны в массиве:

      $arrParam=$modx->event->params;
    
при вызове в чанке:
      [[inc_out?
          &outFile=`/assets/.../titleTovar.php`
          &parents=`1795,5298,3816,3110`
      ]]
    
В файле PHP имеем:
      $arrParam=Array
      (
        [outFile] => /assets/.../titleTovar.php
        [parents] => 1795,5298,3816,3110
      )
   

Получить ИД текущего документа: $curId = $modx->documentIdentifier;

Можно догадаться, что где-то должно храниться текущее состояние страницы. Так и есть. Это объект $modx->documentObject.

При этом свойства страницы - в массиве(ключи - поля таблицы "modx_content"):

Array
(
    [id] => 9481
    [type] => document
    [contentType] => text/html
    [pagetitle] => Резные дорожные нарды из массива мореного дуба
    [longtitle] => Резные дорожные нарды из массива мореного дуба
    [description] => Резные дорожные нарды из массива мореного дуба
    [alias] => duplicate-of-reznyie-dorozhnyie-nardyi-iz-massiva-morenogo-duba
    [link_attributes] => 
    [published] => 1
    [pub_date] => 0
    [unpub_date] => 0
    [parent] => 9294
    [isfolder] => 0
    [introtext] => Артикул: RTN-30.M
    .....
    
А TV-параметры в массиве, который - член предыдущего массива
     [price] => Array
        (
            [0] => price
            [1] => 5990
            [2] => 
            [3] => 
            [4] => number
        )       
        
    

Можно использовать так: $pageTitle=$modx->documentObject['pagetitle'], $priceValue=$modx->documentObject['price'][4]. Т.е. нет необходимости вызывать функции, делать запросы к базе. И тот же id можно получить так: $curId = $modx->documentObject['id'];


$modx->documentListing - массив всех страниц alias=>id :

Array
(
    [index] => 1
    [ajax] => 2
    [lichnyj-kabinet] => 4
    [403] => 8
    [delete] => 13
    [album] => 16
    [kak-izmenit-razmer-foto] => 24
    [razdely-kategorij] => 25
    [for-test] => 645
    [kontakty] => 66
    [albomy-polzovatelya] => 243
    [nastrojki] => 245
    [rezultaty-poiska] => 267
    [sitemap.xml] => 277
    [404] => 278
    [kvartiry] => 42
    .......................


$modx->documentMap - массив всех страниц Array(parent=>child)

Array (
      [0] => Array ( [0] => 1 ) 
      [1] => Array ( [0] => 2 )  
      [2] => Array ( [0] => 4 )  
      [3] => Array ( [0] => 8 ) 
      [4] => Array ( [0] => 13 ) 
      .........................



Работа в режиме API сильно упрощает жизнь программисту в MODX. Взять хотя бы извращения со снипетом if и всевозможными фильтрами и модификаторами. При чуть более сложной обработке все быстро вырождается в хаос и безисходность. Режим же API MODX дает кучу возможностей для прозрачного и легкого решения любых задач. Жаль, что не все документировано и пришлось долго рыться в исходниках, чтобы более-менее уверенно себя чувствовать.


Комментарии 0






Разрешённые теги: <b><i><br>Добавить новый комментарий: