[EVO] Ajax. Финальный правильный метод №4
Предлагаемые ранее методы черезжопные изначально.
Запуск сниппетов через index-ajax.php бред бредовый, т.к. это
а) не совсем безопасно, т.к. это без доп. проверок можно вызвать абсолютно любой сниппет в системе
б) Не удобно, т.к. вместо того, чтобы разруливать логикой на уровне контроллера (файла в который приходит запрос), приходится делать дополнительный сниппет на плечи которого перекладывается эта обязанность.
Использование jQuery.load это костлявый ajax, т.к. реально грузится вся страница целиком и уже только потом из этой страницы выбирается нужный HTML блок. При этом нет возможности получать ответ в JSON без дополнительных плагинов и модификаций сниппетов.
Разруливание роутингом на уровне плагина под событием OnPageNotFound — это конечно решение, но если вдруг кто-то создаст документ с алиасом указаным в switch, то весь ajax полетит к чертям, а программист будет искать ошибку пока не поседеет.
Создание документа в дереве ресурсов — хороший выход. Но опять таки, приходится плодить одноразовые сущности в виде сниппетов используемых только 1 раз только в конкретном ресурсе. Помимо этого необходимо еще и настраивать права доступа, чтобы спрятать системный ресурс от рядового менеджера.
Использование index.php как отправная точка — единственное верное решение. Тем более, там уже заложена возможность запуска в режиме API. Итак, создаем в корне сайта (рядом с index.php) какой-нибудь файлик (допустим ajax.php)
Как итог, в созданном файле автоматически задаются все те же параметры как и во всем движке. Вызывается событие OnWebPageInit (на случай если на это событие подвешены какие-то плагины типа LoadElement или автозагрузчики классов типа Composer).
Более того, сниппеты занимаются своими делами, а внутри файла мы уже задаем непосредственно логику для запуска этих сниппетов и обработку данных без внедрения дополнительных сущностей (сниппетов).
Банальный пример. Необходимо вернуть или в HTML или в json. Для этого последние 3 строки файла перепишем так:
Запуск сниппетов через index-ajax.php бред бредовый, т.к. это
а) не совсем безопасно, т.к. это без доп. проверок можно вызвать абсолютно любой сниппет в системе
б) Не удобно, т.к. вместо того, чтобы разруливать логикой на уровне контроллера (файла в который приходит запрос), приходится делать дополнительный сниппет на плечи которого перекладывается эта обязанность.
Использование jQuery.load это костлявый ajax, т.к. реально грузится вся страница целиком и уже только потом из этой страницы выбирается нужный HTML блок. При этом нет возможности получать ответ в JSON без дополнительных плагинов и модификаций сниппетов.
Разруливание роутингом на уровне плагина под событием OnPageNotFound — это конечно решение, но если вдруг кто-то создаст документ с алиасом указаным в switch, то весь ajax полетит к чертям, а программист будет искать ошибку пока не поседеет.
Создание документа в дереве ресурсов — хороший выход. Но опять таки, приходится плодить одноразовые сущности в виде сниппетов используемых только 1 раз только в конкретном ресурсе. Помимо этого необходимо еще и настраивать права доступа, чтобы спрятать системный ресурс от рядового менеджера.
Использование index.php как отправная точка — единственное верное решение. Тем более, там уже заложена возможность запуска в режиме API. Итак, создаем в корне сайта (рядом с index.php) какой-нибудь файлик (допустим ajax.php)
define('MODX_API_MODE', true);
include_once(dirname(__FILE__)."/index.php");
$modx->db->connect();
if (empty ($modx->config)) {
$modx->getSettings();
}
$modx->invokeEvent("OnWebPageInit");
if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest')){
$modx->sendRedirect($modx->config['site_url']);
}
$out = $modx->runSnippet('test');
$return = array('message' => $out);
echo json_encode($return);
Как итог, в созданном файле автоматически задаются все те же параметры как и во всем движке. Вызывается событие OnWebPageInit (на случай если на это событие подвешены какие-то плагины типа LoadElement или автозагрузчики классов типа Composer).
Более того, сниппеты занимаются своими делами, а внутри файла мы уже задаем непосредственно логику для запуска этих сниппетов и обработку данных без внедрения дополнительных сущностей (сниппетов).
Банальный пример. Необходимо вернуть или в HTML или в json. Для этого последние 3 строки файла перепишем так:
$out = $modx->runSnippet('test');
if(isset($_REQUEST['json'])){
$out = json_encode(array('message' => $out));
}
echo $out;
59 комментариев
и что это нам даст? :)
Пофиксил…
Ваш метод можно стандартизировать, добавив вместо вызова сниппета проверку$_REQUEST['action'] (к примеру) и далее switch($action)… Но сам я приверженец документного AJAX в MODx. Скрыть папку API от клиента и роботов не трудно, а сниппет можно сделать один универсальный и вызывать его с нужными параметрами.
— Инициализируется ядро MODX
— Получается documentObject страницы
— Получается сниппет
— Разбираются параметры
— Выполняется код
— Препарируется результат шаблонизатором MODX
Цикл жизни AJAX запроса в моем случае:
— Инициализируется ядро
— Выполняется код
Ну и наконец в вашем случае нужно еще проделать 1 совсем несложный этап:
Да и вызов сниппета это лишь пример — можно и сразу код фигачить. В документах увы так нельзя.
github.com/ghettovoice/AsyncDocs-EVO
github.com/Husband/AjaxifyEvo
но не изменяются мета-теги при переходе по страницам
Но мне кажется, что этот способ хорошо подойдет для одностраничного сайта. А если нужно, чтобы работало и без ajax, то я бы выбрал метод с прерыванием парсера. Описано здесь modx.pro/development/3139-foundations-of-ajax/ — только я делал с помощью плагина.
код сниппета
код страницы
Сегодня юзал этот код для аякса, всё работает, как часики.
Сделал запрос по методу, приведенному тут.
Если в файле ajax.php пишу
$out = $modx->runSnippet('models');
то он возвращает строку Array
Если в файле пишу сразу код сниппета, который просто выводит строку из базы, то все нормально работает.
В чем может быть проблема?
В браузере нормально открывается, выводит что должен.
Вот сниппет на страничке выводится
www.test1.sitefarm.ru/models.html?mark=360
www.test1.sitefarm.ru/models.html?mark=340
а если через аякс запрашивать ajax.php с запуском этого сниппета, выводит пустую строку.
Вот страничка с таким вот кодом:
www.test1.sitefarm.ru/test4.html
Как видите в ней сначала отрабатывает сниппет.
Код сниппета:
Вот код файла ajax1.php
Закомментировал проверку на xmlhttprequest
<?php
define('MODX_API_MODE', true);
include_once(dirname(__FILE__)."/index.php");
$modx->db->connect();
if (empty ($modx->config)) {
$modx->getSettings();
}
$modx->invokeEvent(«OnWebPageInit»);
/*if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest')){
$modx->sendRedirect($modx->config['site_url']);
} */
$out = $modx->runSnippet('test1');
echo $out;
?>
Если вызвать напрямую, работает
www.test1.sitefarm.ru/ajax1.php
Запрос через аякс упрямо возвращает строку Array
www.test1.sitefarm.ru/ajax1.php
Что я делаю не так?
prntscr.com/io1buh
аяксом также Array возвращает.
это не нужно
Потому что еще есть проблема со входом пользователя
prntscr.com/io1du6
что в логах «просмотр событий» показывает?
В логах ничего не выводится.
Если напрямую вызвать, выводится два раза:http://prntscr.com/io1lq7
Нашел вредный плагин!
Вторую ошибку с weblogin также вызывал плагин userHelper
Закомментировал, стало работать как надо:)
На сайте делаем вызов
В директории с конфигурацией FormLister создаём файл с настойками, например callback.json, в котором все настройки и указываем.
А как оправить форму через ajax на нужный файл, надеюсь, вы знаете.
Но чутье мне подсказывает, что не так надо делать.
Объясню ситуацию. Лейдинг. Начальство просит множество форм на странице, практически в каждом блоке свой лид. В итоге куча модальных окон с формами и просто формы без модальных окон… куча кода, куча вызовов Формлистера. Везде нужен аякс. Кошмар, который я хочу причесать.
В зависимости от того, чем отличаются формы, вы уже решите, обрабатывать их одним конфигом Формлистера или под каждую форму делать свой конфиг. Соответственно и в аякс-файле можете обрабатывать все формы через один action и вызов Формлистера или несколько.
Не ясно в чем ещё трудность.