Вывод тикетов пользователя
Сегодня задали вопрос: -а как выводить тикеты определённого пользователя, типа как персональный блог?
Ну, тут минимум 2 варианта: 1. Создать отдельный раздел для юзера. 2. Выделять тикеты юзера из общей кучи.
Первый вариант отметаем сразу по ряду причин: - Нужно дать право юзеру на создание разделов. - Нужно проверять, сколько он их создал (должно же быть не больше одного). - Нужно назначать политики доступа так, чтобы туда мог написать только юзер. - Куча ненужных никому разделов в админке - Еще всякие непредвиденные сложности.
Если вы будуте создавать каждому юзеру блог самостоятельно в админке руками - еще куда ни шло. Но это не удобно + если юзеров много, то админка разрастётся до неприличных размеров.
Поэтому, мы пойдем вторым путём - выводом тикетов юзера по уникальному url. Я предлагаю site_name/section_name/user_name/.
Первым делом, нам нужно подготовить getPage к фильтрации по юзеру. Пиишем сниппет-обёртку getPageWrapper:
if (!empty($_REQUEST['username'])) {
$username = trim($_REQUEST['username']);
if ($user = $modx->getObject('modUser', array('username' => $username))) {
$uid = $user->get('id');
}
else {$uid = 0;}
$scriptProperties['where'] = '{"createdby":'.$uid.'}';
}
return $modx->runSnippet('getPage', $scriptProperties);
В разделе всех тикетов заменяем вызов getPage на getPageWrapper. Теперь, если в массиве $_REQUEST передать username существующего юзера - то выведутся только его тикеты.
Уже можно обращаться к странице site_name/section_name/?username=k07n. Обратите внимание, мы заодно нашли решение распространённого вопроса - а как передать через $_GET данные в getPage? Ничего сложного.
В принципе, всё. Можно делать ссылки на блог юзера и при переходе туда, будут выводиться только его статьи. Но это не красиво, мы ведь хотим дружественные url, да?
Эта задача также решается довольно просто. Пишем плагин redirectToUser:
if ($modx->event->name == 'OnPageNotFound') {
$request = $_REQUEST['q'].'/';
preg_match('/(.*?)\/(.*?)(?:\/|\.html)/', $request, $matches); // выбираем имя секции и юзера
//echo '<pre>';print_r($matches);die; // Можно активировать для отладке
if (!empty($matches[1]) && !empty($matches[2])) {
$q = array(
'alias' => $matches[1]
,'class_key' => 'TicketsSection'
,'deleted' => 0
,'published' => 1
);
// Ищем секцию тикетов и выводим её вместе с параметром фильтрации по юзеру
if ($section = $modx->getObject('TicketsSection', $q)) {
$section_id = $section->get('id');
$_REQUEST['username'] = $matches[2];
$modx->sendForward($section_id);
}
}
}
Плагин сработает, если не найдена страница по указанному адресу, затем попытается выделить из адреса запроса имя секции тикетов и юзера. Если секцию тикетов существует, то плагин загрузит ее, поместив в $_REQUEST имя юзера, чтобы обёртка getPage добавила его в условие выборки.
Если где-то в этом процессе произойдет сбой\несоответствие, то работа плагина остановится и вы получите стандартную страницу 404, которая и должна выводиться в таком случае. Конечно, вы можете добавить собственные дополнительные услоия\проверки и расширить мой пример как угодно.
Задача решена. С этого момента у меня в разделе вопросов можно кликать на имя юзера и получать все его тикеты. Например: http://bezumkin.ru/user/topics/bezumkin/.
Данный пример является класическим роутером дружественных url. Приблительно так же работают и friendly urls самого MODX.
0
👍
👎
❤️
🔥
😮
😢
😀
😡
5 463
18.12.2012, 13:31:56
49 комментариев
Andrei Kilin
18.12.2012, 19:22:29
Andrei Kilin
18.12.2012, 19:46:06
Дзен наступит, если еще сделать ссылки на сами тикеты в такой форме:
.
Василий Наумкин
18.12.2012, 21:09:01
Вы уже знаете всё нужное для этого.
Andrei Kilin
18.12.2012, 21:34:41
дада, это не вопрос был, а предложение по функционалу сюда.
Бохонов Андрей
26.10.2013, 04:30:23
Большое спасибо за статью! Появился вопрос, если добавить случайные символы в конец url то сервер отвечает кодом 200 вместо вывода 404 ошибки
Например ссылка на комментарии bezumkin-а - код 200
добавили к ссылке 123 - так же код 200 (почему не 404 ошибка?)
Может кто-нибудь сможет подсказать как это исправить?
Andrei Kilin
28.10.2013, 16:06:09
404 ошибка в том и том случае, просто она плагином обрабатывается. В обоих случаях урл подпадает под условие проверок первых 3-х секций. Если ты хочешь 404, когда в конце лишнее написано - проверяй 4-ую секцию на отсутсвие знаков. Если в 4-ой пусто тогда форвард, если нет то форвард надо пропустить и будет 404
Даниил
13.01.2014, 12:27:37
Что то не хотят у меня урлы работать(( Сниппет getPageWrapper создал, плагин redirectToUser тоже создал (именно плагин же должен быть, не сниппет, верно?), на странице, на которой предполагается вывод, вызываю так:
Ссылка с именем пользователя на эту страничку (ее id у меня 69) следующая
В чем может быть ошибка?
Даниил
13.01.2014, 12:28:53
Если пишу через обычный GET имя пользователя вручную в адресной строке - работает.
Василий Наумкин
13.01.2014, 12:55:52
У меня здесь старый код, в котором показан общий принцип.
Попробуй вот такой плагин:
Даниил
13.01.2014, 13:04:28
Увы и ах, не хочет даже так срабатывать... А в настройках плагина разве не нужно выставлять никаких системных событий?
Василий Наумкин
13.01.2014, 13:05:16
Естественно нужно, в первой строке же проверка OnPageNotFound.
Даниил
13.01.2014, 13:31:46
Все, заработало! Ура!))))) Спасибо большущее! На самом деле это я протупил и не посмотрел в код детально изначально, у меня адрес страницы с getPageWrapper был произвольный, а надо было чтоб он был адрес-сайта/user/topics (ну либо адрес-сайта/user/comments - во втором случае) в соответствие с условием
Василий Наумкин
13.01.2014, 14:34:44
На здоровье!
Николай
07.02.2014, 12:37:27
А как правильно должен выглядеть сниппет getPageWrapper,чтобы работал с этим плагином? У меня заработал только когда добавил в плагин
но это как-то странно по моему
Александр Наумов
13.01.2014, 19:04:18
Василий, объясни, пожалуйста, почему у тебя не срабатывает запрос?
Василий Наумкин
13.01.2014, 19:07:02
Сниппет реагирует на uid - bezumkin.ru/user/topics/?uid=2
А плагин переводит username в uid.
Александр Наумов
13.01.2014, 20:03:22
Получается у тебя в добавок по ссылке http://bezumkin.ru/user/topics/ работает какой-то сниппет, который выводит надпись: Подходящих записей не найдено.?
Василий Наумкин
13.01.2014, 20:39:58
Обычный фильтр вывода default, при вызове сниппета.
Александр Наумов
13.01.2014, 20:43:01
Спасибо, понял!
Чикин Артур
13.01.2014, 20:33:51
Василий, скрести ссылки, что бы получилось вот так:
Василий Наумкин
13.01.2014, 20:39:28
Один раздел доступен только для юзеров, а другой для всех.
Их нельзя скрещивать.
Чикин Артур
13.01.2014, 20:54:22
Блин было бы гораздо удобнее. Так сказать появилась бы иллюзия единого кабинета.
Даниил
14.01.2014, 16:02:32
Ну да, пусть все видят две вкладки, а юзеры четыре.
Василий Наумкин
14.01.2014, 17:06:00
Это разные разделы сайта: личный кабинет и публичный профиль. В личный кабинет без авторизации даже зайти нельзя, в профиль индексируют поисковики.
Вы если не понимаете - не нужно давать советов. Я вроде не дурной, осознаю, что делаю.
Даниил
14.01.2014, 17:13:42
После озвучивания конкретных названий разделов стал понимать логику твоих мыслей. Да, согласен - объединять нельзя.
Даниил
14.01.2014, 16:00:18
Что-то не пойму как должен использоваться TicketComments через getPageWrapper... Комментарии это же по сути не ресурсы. Можно пример такого вызова?
Александр Наумов
14.01.2014, 18:30:17
В чанке tpl.Tickets.comments можно выводить
Даниил
14.01.2014, 19:01:48
Спасибо, Александр! Я уже пробовал pdoResources подставлять, но что-то видимо все-таки не так делал, сейчас попробую этот вызов.
Александр Наумов
14.01.2014, 19:27:48
Я тоже кучу разных вариантов перепробовал и заработало, только тогда, когда поставил &sortby=``, так и не пойму почему без этого параметра не работает.
Василий Наумкин
14.01.2014, 20:55:25
Потому что иначе сортировка по первичному ключу, а он у комментов на два поля, то есть массив.
Через это ошибка в запросе pdo. Смотрите логи, это полезно.
Александр Наумов
14.01.2014, 21:34:11
Спасибо, буду знать!
Даниил
15.01.2014, 07:59:06
При таком выводе интересно несколько моментов, да [[+text]], [[+name]] и [[+createdon]] в чанке выводят все как положено. Фото пользователя из соцсети, через которую он залогинен также выводится без проблем, через конструкцию [[+createdby:userinfo=photo]]. А как вывести имя тикета, к которому относится комментарий и граватар пользователя в чанке tpl.Tickets.comments?
Даниил
15.01.2014, 11:55:58
И как еще можно вывести на одной странице общее число публикаций и комментариев? Для того раздела где находимся понятное дело [[+total]] выводит, а как для другого находясь в этом же разделе?? Я то конечно вывел, но по-моему это большущий костыль... На странице комментариев общее количество публикаций вот так:
И, соответственно, на странице публикаций общее количество комментариев тем же способом, только используя getTickets:
Как бы это правильнее сделать, чтоб не запускать целый "завод", ради производства одной "зубочистки"?
Василий Наумкин
15.01.2014, 12:11:51
Я написал свой сниппет:
Выставляет плейсхолдеры total.topics, total.comments, username, fullname и avatar.
Даниил
15.01.2014, 12:57:02
Огого как тут все круто оказывается) Спасибо, Василий, сейчас буду пробовать!
А аватар у меня кстать легко вот так вывелся:
Даниил
15.01.2014, 12:59:20
Твой сниппет кстати можно включить даже в стандартный набор Tickets, я думаю многим такой функционал был бы полез!
Даниил
15.01.2014, 11:15:08
Оказалось у меня getPageWrapper по какой-то причине не хотел воспринимать имя пользователя, использую теперь getPage без него. Для этого создаю в плагине redirectToUser еще один плейсхолдер, содержащий id юзера. Получается вот такой код:
А на страницах получаю все необходимые данные через:
Соответственно и в вызовы getPage потом подставляю.
Для тикетов:
И для комментариев:
Даниил
16.01.2014, 12:33:59
Не пойму, почему при моем вызове thread, parent, text и name попадают в выборку, а id не попадает (вроде в той же самой таблице находится)?
Василий Наумкин
16.01.2014, 12:53:41
Имя ТВ не должно совпадать с именем поля ресурса.
Даниил
16.01.2014, 13:00:43
А, да то я уже извращался, если вот так делаю тоже не выбирает:
Даниил
16.01.2014, 14:49:01
Добавил параметр select в котором перечислил все нужные мне поля, в том числе и id, так попадает в выборку
Странно, что без select никак его не получается вытащить. Это как то связано с тем что у поля id в таблице AUTO_INCREMENT стоит? По крайней мере больше я никаких отличий этого поля от других не нашел...
Даниил
16.01.2014, 16:16:28
А чем мы можем получить информацию о тикете находясь на произвольной странице, но зная id тикета?
Даниил
17.01.2014, 01:25:16
Может быть можно для этих целей как-то использовать pdoField? Единственное не могу понять как переключить его логику работы с ресурсов на комментарии((
Даниил
17.01.2014, 19:59:03
Маленький модификатор threadid который из id тикета получает resource, т.е. на выходе получаем id ресурса, являющегося тикетом
Применяем в чанке tpl.Tickets.comments (о котором выше говорили) так
Соответственно отсюда можем уже и pagetitle тикета узнать, к которому относится комментарий и pagetitle деда ну и т.д.
Даниил
17.01.2014, 22:13:49
Сам задал вопрос, сам нашел ответ, поразительно как действует отсутствие внешних подсказок :DDD Вот только времени очень много лишнего тратится на понимание...
Василий Наумкин
17.01.2014, 22:39:22
Зато потом экономится.
Иначе так и будешь постоянно ждать подсказок.
Даниил
17.01.2014, 22:53:14
Да я ж не против никогда учиться, у меня этот веб весь хоть и сидит в печенках уже за несколько лет, но узнавать что-то новое и осваивать всегда приятно и интересно... Тут просто ситуация другая, когда над тобой висит заказчик проекта и орет "быстрее-быстрее" и ты понимаешь, что да, надо бы действительно быстрее, т.к. обещал сайт за 3 недели сделать, а уже полтора месяца "пилишь" его и при этом тратишь 2 дня на то чтоб только понять как вытянуть этот самый pagetitle, вот это расстраивает... Но я не в коем случае никого не виню, тебе, Василий, вообще отдельная и пожизненная благодарность за то, чем мы пользуемся все, и со временем я представляю как проблематично у тебя, тут нас таких вопрошающих не одна сотня, а ты один. Эт я сам дурак что не могу чего-то быстро сообразить, матчасть учить мне больше надо
Василий Наумкин
17.01.2014, 23:18:18
Ну так нужно оценивать свои силы и не обещать за 3 недели =)
Даниил
17.01.2014, 23:22:31
А если не обещать, то никто и не закажет, кушать то хочется ;)
bezumkin.ru
Личный сайт Василия Наумкина
Прямой эфир
Василий Наумкин
01.07.2024, 11:56:41
Да, верно, именно так.
А в контроллере, скорее всего, ловить данные методом post.
Василий Наумкин
26.06.2024, 09:38:15
О, точно, вылезает если не залогинен.
Спасибо, исправил!
Василий Наумкин
09.04.2024, 04:45:01
> Ошибка 500
Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи.
...
russel gal
09.03.2024, 20:17:18
> А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал...
Александр Наумов
27.01.2024, 03:06:18
Василий, спасибо!
Извини, тупанул.