Ajax. Метод №3

Вкратце о раннее рассказанных методах.
1) Отправляем ajax запрос на туже страницу где мы находимся, а с ответа в нужном html теге вырезаем результат
+ простота
— скорость
— необходимость вырезать из ответа нужное
2) Через index-ajax.php Урок или на прямую на php файл
+ скорость
— необходимость подготовки скриптов их прописыванию
— правка кода через фтп
— необходимо иметь заготовку
3) Тут подробнее. Данный метод у некоторых людей поменяет стиль программирования в МОДх ))))

— создайте плагин AJAX с кодом

switch($_GET['q']){	
	case 'liked':
	    echo $_POST['value'].'-OK';  //вот тут код отработки вашего кода
            // выведим просто значение $_POST['value'] 
	break;
}
die();


— выставите его на событие OnPageNotFound

Все. Заготовка готова. Такой код запоминается на раз-два-три.
Самое интересное как этим пользоваться. Еще не догадались???? ))))

в консоли firebug давайте потестим как оно работает


$.ajax({
    url:'liked',
    type:'post',
    data:{
        value:1
    }
})


Ответом сервера будет «1-ОК» )) Все работает…

Для тех кому интересен принцип:
— идёт запрос на сервер по URL: liked
— так как его не существует (здесь вся соль) выполняется событие OnPageNotFound
— наш плагин как раз на данном событии
— .htaccess MODx преобразует frienly url в переменную которую отсылает GET параметром на index.php — потому используем $_GET['q'] для определения action

И что мы емеем. Для разных action мы просто прописуем их в case '':. на эти url шлем запросы.

+ скорость
+ простота (может и не с первого раза, но гарантирую что вы подсядите)

51 комментарий

avatar
Я немного не допетрил, а куда фтыкать сниппет обработки аякс запроса?
avatar
switch($_GET['q']){
case 'liked':
echo $_POST['value'].'-OK'; //вот тут код отработки
break;
}
die();
avatar
Кажется я начал понимать!!! Это же круто)) а я делал отдельную страницу с пустым шаблоном и нужным сниппетом. Нигде не читал, как допетрил так и сделал)))
Комментарий отредактирован 2014-04-03 12:10:40 пользователем Grinyaha
avatar
Очень интерестный способ, надо попробывать на досуге ))
avatar
Ещё можно создать документ и в нём вызвать некэшируемый сниппет (пример).
avatar
можно. это почти тоже самое что и п.1 что расписал. Но вот отличия:
— url и есть action. А в твоём его надо переменной передавать.
— не надо засорять дерево непонятными для клиента ресурсами
— парсер MODx даже пукнуть не успел а мы его в die, тоесть и скорость выше
avatar
— парсер MODx даже пукнуть не успел а мы его в die, тоесть и скорость выше
Стало быть чанк тут не пропишешь?
avatar
чанк пропишет. Я про то что парсер не отрабатывает текущий документ
avatar
— url и есть action. А в твоём его надо переменной передавать.
+ одно слово, ничего страшного.
— не надо засорять дерево непонятными для клиента ресурсами
Я бы сказал: надо настраивать права пользователей.
— парсер MODx даже пукнуть не успел а мы его в die, тоесть и скорость выше
Всё это выглядит в конечном счёте «грязновато» или, простите, «через жопу». Событие «OnPageNotFound» (страница не найдена) как-то логически не подходит для этих вещей. Это какой-то стиль Netcat, где по человечески сделать просто не возможно. Да и какой смысл? Вместо привычного использования сниппетов каждый раз писать код?

P.S.: ↑ это риторические вопросы.
P.P.S.: без обид только ;-)
Комментарий отредактирован 2014-04-03 17:16:39 пользователем Ronef
avatar
На каждый товар свой покупатель. А вставлять сниппет в ресурс, выставлять права — уж простите это через жопу
— когда есть стандартный механизм. То что предложил я альтернатива стандартному, без левых телодвижений с правами и тд.
P.S.: без обид только ;-)
avatar
Просто в сборке есть один ресурс сразу с нужными правами, создаёшь для него дочерний и всё. И вы не правы, это не через жопу, это всё стандартные механизмы: что создание документа, что вызов в нём сниппета, да и выставление прав, — всё это через правильное стандартное место ;-)
avatar
Тут суть в том что:
по сравнению с вариантом через создание документа — работае быстрее.
по сравнению с index-ajax — настраивается легче

Да это похоже на черезжопу, но если все хорошо за документировать то не успеешь подумать как этот вариант станет стандартным :)

Понимаю что все должно быть по правилам но жизнь идет все меняется и правила тоже нужно менять: )
avatar
Я вас умоляю, прямо-таки сильно быстрее? Да ладно.

А если параметры принимаются через $_GET, а вызов сниппета в таком случае вообще кэшируемый (в конфиге настроено кэширование с учётом $_GET), что будет быстрее?

Или в одном случае надо делать так, а в другом — по-другому?

А как же вызовы сниппетов VS код руками? Или что, надо в событии «OnPageNotFound» вызывать сниппеты через «$modx->runSnippet»?

Ещё есть множество подобных вопросов и тонких моментов, ибо это не через ту дырку, через какую надо. Если есть нам предназначено ртом, давайте этого правила и будем придерживаться.
Комментарий отредактирован 2014-04-04 07:34:30 пользователем Ronef
avatar
Кста вот это $modx->runSnippet
быстрее чем [!!]
а кешировать можно и не только стандатрным кешем :)

Вообщем как вариант использования Ajax по новому вам показали а использовать или нет дело ваше:)

но игнорировать такие плюшки и заведомо считать их ошибочными считаю не правильным. Опять же потому что нет фактов что это плохо потому этот метод пускай не совсем по правилам но имеет право на жизнь :)
avatar
Начинающие программисты читают такие посты и начинают делать в таком стиле не особо разбираясь в деталях. А потом другие люди смотрят и говорят, что MODX — по сути тот же Netcat.

Да просто если мне придётся копаться в сайте, на котором аякс сделан вот таким вот методом, то сначала я буду копаться продолжительное время, чтобы понять, как это работает, а потом такое же время выражаться нецензурной бранью и переделывать на что-то более стандартное.
avatar
Тогда еще вот это почитайте :)
blog.agel-nash.ru/2014/2/ide-and-modx-evolution.html

p.s. Не вижу не тандартным использование плагина на pageNotFound тудой к примеру все ЧПУ для своих страниц делается:) и нет в этом проблемы
avatar
Тогда еще вот это почитайте :)
blog.agel-nash.ru/2014/2/ide-and-modx-evolution.html
LoadElement имеет явное преимущество по сравнению со всеми другими стандартными подходами. Как минимум нет необходимости сидеть в админке. Как максимум — есть возможность комфортно пользоваться гитом. Ну и да, не стоит забывать, что LoadElement отлично подходит для разработки, но не для продакшинов! Так что не не нужно путать божий дар с яичницей.

Теперь о способе предложенном в данном топике. Он хоть и вписывается в так называемые «стандартные средства MODX», но он выбивается из общей идеологии программирования, т.к. код который по логике должны быть в одном месте, по факту находится абсолютно в другом. Если пытаться привести пример, то я бы сравнил это с кодом в стиле:

include_once("image.gif");


Ну а че… какая разница gif это или php файл. Стандартные же средства php задействованы.

В общем кому нравится обманываться — пожалуйста, первые 3 способа для вас. Лично я использую метод №4:
— Код ajax методов находится на своем месте и любой кодер без явных познаний modx разберется куда уходят запросы.
— Нет необходимости копипастить кучу символов из других файлов, чтобы корректно подключить ядро modx
— Не плодятся одноразовые сущности, что в конечном счете не приводит к разбуханию глобального кеша, что влияет на производительность (а учитывая, что явный плюс вашего метода это производительность, то получается что овчинка выделки не стоит)
— Есть возможность использовать автозагрузчики классов и элементов

Ну в общем как-то так. А теперь советую задуматься — действительно ли вы правильные методы разработки вы пропогандируете…
avatar
Agel-Nash — Ё, дай поспорить. Не видишь срач пытаемся мелкий развести. Пришёл надавал пендюлей… )))) ггг
Комментарий отредактирован 2014-04-04 11:14:18 пользователем bumkaka
avatar
Я видел множество примеров реализации стандартного функционала на MODX всякими изощрёнными методами (вспомни хотя бы тот же if ($content['template'] == 1500) в mm_rules). Зачем? Да, это будет работать сейчас, может быть будет работать и позже, а может и нет, кто знает. Зачем?
avatar
Текущее решение это все в рамках документированных возможностей MODX тут нет использования недокументированных фич потому работать будет всегда
avatar
ребят прекращайте спор. Каждому свое.
Ronef — возми листок бумаги, прорисуй блоксхемно этапы обработки твоего и данного метода через ядро. Ты все поймешь. Даже твоим через ресурс, onpagenotfound гораздо раньше вызывается парсером, как по моему незачем систему дергать если есть возможность сделать производительней. А рассказывать про учеников которые читают эту статью и что она наносит им вред — уж изволь полная чушь. Чем больше понимания работы ЦМС тем лучше специалист
avatar
Получается, что всё преимущество обработки аякса в «OnPageNotFound» сводится экономии ресурсов?

1. Экономия на спичках.
2. Что насчёт примера с кэшируемым вызовом?
Комментарий отредактирован 2014-04-04 10:04:53 пользователем Ronef
avatar
а вот для кешированного метод отстаиваемый тобой самое оно, так как там статика. Просто получается ресурс со своей инфой которую ты выводиш аяксом. А вот динамику так делать крайне не советую. На это использовать прямое обращение на файл похапе, использовать схему index-ajax.php или мной предложенный вариант. Кому как угодно. Всему есть свое применение. А отстаивать свой любимый привыкшийся годами метод для вся и все — ну прастыце… Каждый разраб должен быть в меру ленив. Именно лень заставляет делать разраба свои наработки проще, быстрее, качественнее
avatar
Предложение закончить спор было очень в тему)

А вообще, я не вижу смысла использовать оба метода, логичней остановиться на чём-то одном для однообразия, для понимания, для дебага, для командной работы, etc.

Опять же, я попытался акцентировать внимание на том, что экономия на производительности при помощи «OnPageNotFound» довольно низка и ей можно пренебречь в угоду удобства разработчиков, что есть правильный паттерн, на мой взгляд.
avatar
А рассказывать про учеников которые читают эту статью и что она наносит им вред — уж изволь полная чушь.
Ко мне обращаются за помощью сотни людей, я видел тонны решений, сделанных новичками. Я разговаривал со многими людьми, доказывающими мне, что MODX — тот же Netcat, только сбоку. Поверь, это не чушь.
avatar
Не могу одного понять — причем тут Netcat, он вам что-то плохое сделал? :))))
avatar
О, у меня к нему особые чувства)) Думаю, вы и сами понимаете, какие именно =)
avatar
Да ладно, то, что у них вся обработка идет через файл с говорящим названием e404.php — еще ни о чем не говорит :))))) Зато у них в 5-й версии наконец то «сложилось» с кавычками и теперь их можно не слэшировать везде :)
Вон в битриксе вообще напрямую сортировку разделов в инфоблоках задать нельзя, и ничего, живут же как-то и без этого :)
avatar
Там ещё много весёлого есть (чего таить, там почти всё — «просто обхохочешься») ;-)
avatar
где то мне попадалось, что официально именно так и рекомендуется делать AJAX, что я и практикую. Там ещё было предложение через процессоры, но его отмели, как раз по той причине что указана в первом предложении. К сожалению пруфлинк не предоставить уже.
avatar
Ну ты молодец! Ещё не всё понял и не проверил, добавил в избранное, почитаю обязательно в скорейшем времени! Спасибо!!!
avatar
Интересный способ, конечно немного «черезжопный», но в некоторых моментах может пригодиться, возьму на вооружение. Спасибо!
Комментарий отредактирован 2014-04-04 00:34:36 пользователем b0nn1e
avatar
Для разруливания экшенов я обычно использую класс обработчик, примерно такого плана, написал упрощенно gist.github.com/vanchelo/1c6b4ff6e79b05edf40d
Точно так же создаете плагин на событие OnPageNotFound, но это не обязательно
<?php
require MODX_BASE_PATH . 'ActionsHandler.php'; // Подключаем наш класс
$handler = new ActionsHandler($modx);
if ($response = $handler->handle()) {
    echo $response; // Отдаем наш ответ браузеру
    exit();
}

В классе ActionsHandler создаете новый метод, если вы отправляете запрос на адрес
site.com/hello, то метод должен называться helloAction, метод должен возвращать любой корректный массив:
protected function helloAction() {
    return $this->success('Hello message', ['hello' => 'Hello, World!']);
}
avatar
А еще этот метод прекрасно подходит для генерации динамических страниц-ответов, например для стороннего сервиса оплаты при условии передачи параметров и их проверки, ну и например страниц-сигнализаторов, аля payment?success или payment?fail.
avatar
пробую использовать для сортировки на Дитто (может кто знает проще?)
пишу код (JS):

			$("a.settings-list__sort-item").click(function(e){
				e.preventDefault();
				var href = $(this).attr("href");
				
				$.ajax({
				    url:'ajax',
				    type:'GET',
				    data: href,
				    success: function(data){ // при успехе
							$('.listing').html( data );
						},
						error: function(){ // при неудаче
							$('.listing').html('Ошибка! Попробуйте ещё раз!');
						}
				})
			}); 

код плагина:

switch($_GET['q']){     
        case 'ajax':
				/* START */
				
				$docid = 5;
				$p['extenders'] = 'request';
				$p['andFilterTv'] = "";

				$p['parents'] = $docid;
				$p['tpl'] = 'cat.tpl';
				$p['display'] = '12';
				$p['depth'] = 1;
				$p['sortDir'] = (isset($_GET['ditto_sortDir']))? $_SESSION['sortDir'] = $_GET['ditto_sortDir'] : (isset($_SESSION['sortDir']) )? $_SESSION['sortDir'] : 'DESC';
				$p['sortBy'] = (isset($_GET['ditto_sortBy']))? $_SESSION['sortBy'] = $_GET['ditto_sortBy'] : (isset($_SESSION['sortBy']) )? $_SESSION['sortBy'] : 'pub_date';
				$p['truncLen'] = 70;
				$p['paginate'] = 1;
				$p['hideFolders'] = 1;
				$p['showInMenuOnly'] = 0;
				$p['tplPaginatePrevious']='@CODE:<a href="[+url+]"><</a>';
				$p['tplPaginateNext']='@CODE:<a href="[+url+]">></a>';
				$p['tplPaginateCurrentPage']='@CODE:<span class="active">[+page+]</span>';
				$p['debug'] = 0;

				$html = $modx->runSnippet('Ditto', $p);
				echo $html;

				/* END */
        break;
}
die();


в консоле ошибка:
GET http://mag/ajax?/?ditto_sortBy=price&dateSource=price&ditto_sortDir=ASC 500 (Internal Server Error)

* код на PHP проверял отдельно, там окей…
avatar
ссылку поправил; вижу в логах системы:

« MODX Parse Error »
`` is not numeric and may not be passed to makeUrl()

DocumentParser->makeUrl('', '', string $var3)
assets/snippets/ditto/classes/ditto.class.inc.php on line 1038
avatar
а это потому что пустой id передаете надо ж что б был id
avatar
у меня вообще запрос идёт на стр. и там сниппет с параметром — видно нужно всё таки передавать доп. через JS

новый вопрос — пагинацию просто вынести за контейнер где обновляется контент (дописать обработку кликов) или её что надо?
avatar
попробовал код (JS), но что-то не помогает (для пагинации)
$('.pager a').on('click', function(e) {
				//var href = $(this).attr("href");
				var text = $(this).text(); 
		    $.ajax({
				    url:'/run.html',
				    type:'GET',
				    data: { start: text },
				    success: function(data){ // при успехе
							$('.listing').html( data );
						}
				});
		    e.preventDefault();
		  });
avatar
попробуйте для начала сделать несколько ссылок с сортировкой, но без Аякса…
ссылки будут иметь примерно такой вид
<a href="[~[*id*]~]?sortBy=pagetitle&sortDir=asc">от А до Я</a><a href="[~[*id*]~]?sortBy=pagetitle&sortDir=desc">от Я до А</a>

если это всё работает, далее ставить Аякс запрос на ваши ссылки, и при успехе заменяете блок с выводом ditto.

$('.pager a').on('click', function(e) {
    e.preventDefault();
    $('#ditto_block').load(this.href + ' #ditto_block')
});
avatar
э… тут надо вырезать лишнее (из шаблона..)
avatar
понял, тут надо писать таким образом:

$('#wrap_for_cut_box').load(this.href + ' #cut_box')
avatar
можно и так
$('#ditto_block').load(this.href + ' #ditto_block>*')
avatar
мы с ребятами словили интересные «грабли»
при листании пагинации на Аяксе Модкс пропускает один шаг
(обычно второй, при этом номера идут по-порядку)
* может это связанно с тем, что в сборке убрали дубли…
avatar
при пагинации вы скорее всего ловите событие ссылок, которые подгружаются через аякс, попробуйте делегированием
$('body').delegate('.pager a', 'click', function() {
// обработка клика
});
avatar
совет хороший; но я комментировал выше, что вынес её за контейнер modx.im/blog/triks/2096.html#comment43671

и гугл говорит: Начиная с jQuery 1.7, метод .delegate() можно заместить методом .on()
avatar
да да, можно заменить delegate методом on, но вот только таким образом)))
$('body').on('click', '.pager a', function() {
// обработка клика
});

а то, что вынесли за контейнер, значит надо опять обрабатывать, только зачем, если можно всё одним махом получить?

<wrapper>
    <ditto />
    <pager />
</wrapper>

получите содержимое wrapper, получите и дитто и пагинацию
avatar
в этом есть смысл; но разве замена плейсхолдеров делается не парсером Модкс? — т.е. будет ли оно работать на аякс
avatar
wrapper, ditto, pager
обозначил что в этих местах должно быть, чтобы сократить код

<div id="wrapper">
    <div id="ditto"></div>
    <div id="pager"></div>
</div>
avatar
не я говорю про то, будет ли обработан
[+previous+] [+pages+] [+next+] 
avatar
вы же получаете уже сгенерированную эту же страницу, но только с другими параметрами GET.
вам нужно всего лишь, три строчки кода на JS и больше ничего
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.