Почему AjaxForm использует сессии?
Всем привет, давно не виделись!
Переодически почитываю новости на сайте и вот увидел ветку комментариев про хранение данных в сессии.
Казалось бы, совершенно заслуженный камень в мой огород, как автора дополнения. Зачем использовать сессии для ajax сниппетов, ведь сама по себе эта технология сессий не требует? Так-то оно так, но в мире MODX всё несколько сложнее.
Итак, у нас есть 2 основных варианта запустить какой-то сниппет через Ajax.
Вариант 1: отправить запрос на страницу с ним. Вполне рабочий, да, но не очень быстрый, потому что MODX выполнит все плагины и сниппеты, которые найдёт перед вашим сниппетом.
А если вы используете Fenom, то эти сниппеты еще и сразу выведут ответ через echo, потому что он не буферизирует результаты в переменную, а выводит сразу — что сломает ответ от вашего сниппета.
Не подходит.
Вариант 2 — отправлять запрос на отдельный PHP коннектор, который запустит нужный сниппет в облегчённом MODX_API режиме и получит от него ответ без дополнительных затрат.
Отличный, быстрый вариант. Но нам нужно запустить этот сниппет с какими-то параметрами, верно? А где их взять?
Доверить юзеру самому отправлять параметры для работы сниппета нельзя, иначе он вам через pdoResources вытащит все возможные данные из БД, а может еще и запишет чего через другой сниппет. Где хранить данные для запуска сниппета через коннектор?
Тут тоже 2 варианта: какой-то отдельный временный файл с настройками или сессия. При этом отдельный файл с настройками должен обновляться при изменении параметров вызова сниппета на странице, и не должен зависеть от id или группы юзера (иначе файлов будет несколько и особой разницы с сессией не получится) — это всё выглядит довольно сложно для реализации.
А вот сессии вполне рабочий вариант. Да, возможно не самый лучший, но другого я не придумал. По факту, из реально рабочих и универсальных вариантов, это единственный. Все же любят установить дополнение, и чтобы оно сразу работало без танцев с бубном, верно?
Поэтому — сессии.
Вот такая небольшая юбилейная (трёхсотая!!!) заметка с объяснениями, почему AjaxForm, mSearch2, minShop2 и другие мои сниппеты хранят свои параметры в сессиях, а не где-то ещё.
Если у кого есть идеи для более удобного вызова сниппетов через ajax с хранением их параметров не в сессии — буду рад прочитать.
Переодически почитываю новости на сайте и вот увидел ветку комментариев про хранение данных в сессии.
Казалось бы, совершенно заслуженный камень в мой огород, как автора дополнения. Зачем использовать сессии для ajax сниппетов, ведь сама по себе эта технология сессий не требует? Так-то оно так, но в мире MODX всё несколько сложнее.
Итак, у нас есть 2 основных варианта запустить какой-то сниппет через Ajax.
Вариант 1: отправить запрос на страницу с ним. Вполне рабочий, да, но не очень быстрый, потому что MODX выполнит все плагины и сниппеты, которые найдёт перед вашим сниппетом.
А если вы используете Fenom, то эти сниппеты еще и сразу выведут ответ через echo, потому что он не буферизирует результаты в переменную, а выводит сразу — что сломает ответ от вашего сниппета.
Не подходит.
Вариант 2 — отправлять запрос на отдельный PHP коннектор, который запустит нужный сниппет в облегчённом MODX_API режиме и получит от него ответ без дополнительных затрат.
Отличный, быстрый вариант. Но нам нужно запустить этот сниппет с какими-то параметрами, верно? А где их взять?
Доверить юзеру самому отправлять параметры для работы сниппета нельзя, иначе он вам через pdoResources вытащит все возможные данные из БД, а может еще и запишет чего через другой сниппет. Где хранить данные для запуска сниппета через коннектор?
Тут тоже 2 варианта: какой-то отдельный временный файл с настройками или сессия. При этом отдельный файл с настройками должен обновляться при изменении параметров вызова сниппета на странице, и не должен зависеть от id или группы юзера (иначе файлов будет несколько и особой разницы с сессией не получится) — это всё выглядит довольно сложно для реализации.
А вот сессии вполне рабочий вариант. Да, возможно не самый лучший, но другого я не придумал. По факту, из реально рабочих и универсальных вариантов, это единственный. Все же любят установить дополнение, и чтобы оно сразу работало без танцев с бубном, верно?
Поэтому — сессии.
Вот такая небольшая юбилейная (трёхсотая!!!) заметка с объяснениями, почему AjaxForm, mSearch2, minShop2 и другие мои сниппеты хранят свои параметры в сессиях, а не где-то ещё.
Если у кого есть идеи для более удобного вызова сниппетов через ajax с хранением их параметров не в сессии — буду рад прочитать.
Комментарии: 23
Приятно видеть тебя. Пиши еще :)
modRegistry не подойдёт? Свои особенности, но всё же. Я в своё время тоже написал костыль, но думаю, что на перечисленных дополнениях он будет не уместен.
Тот же вариант, что и настройки в файлах, только в БД.
Если работа сниппета зависит от каких-то динамических параметров (id юзера или группа), то точно так же замусорит базу данных. При этом, насколько я помню, возможностей по расширению логики работы там поменьше, чем у modSession.
Да и взять и разом почистить modRegistry из админки нельзя.
Если работа сниппета зависит от каких-то динамических параметров (id юзера или группа), то точно так же замусорит базу данных. При этом, насколько я помню, возможностей по расширению логики работы там поменьше, чем у modSession.
Да и взять и разом почистить modRegistry из админки нельзя.
Можно сохранять настройки вызова AjaxForm в таблицу такой структуры
CREATE TABLE `modx_ajax_form_properties` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`hash` varchar(32) NOT NULL,
`properties` json NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `hash` (`hash`)
)
В коде AjaxForm меняем логику генерации хеша:ksort($scriptProperties);
$hash = md5(http_build_query($scriptProperties));
и потом добавляем новую запись в базу если такого хеша еще нет. При обработке запроса AjaxForm берем данные по хешу из базы а не из сессии.
Сессии modx хранит в базе… поэтому тут всё равно будет БД и куча записей (как я понимаю).
Может так случится, что в параметрах будет уникальное значение для каждого юзера. А значит таблица будет разрастаться как в случае с сессиями, только механизма удаления и чистки этой таблицы нет. Но как алтернативный вариант сойдёт, если уникальных данных нет.
В случае с уникальными данными (что бывает не очень часто) будет добавляться по одной записи в этой таблице, в то время как в варианте с сессиями набор свойств будет дублироваться в сессии каждого пользователя который зашел на страницу. То есть вариант с сессиями увеличивает размер базы быстрее, но, конечно, как вы правильно упомянули, там есть механизмы очистки.
увидел ветку комментариев про хранение данных в сессии. Казалось бы, совершенно заслуженный камень в мой огород, как автора дополнения.А вот спроси этого человека как сделать без сессий проще, лучше и чтоб работало из коробки у всех, ответит что-нибудь в духе «не моё дело, я с MODX не работаю». Главное сказать, что сессии — зло. Почему и чем так они страшны? Думаю, объективного ответа не дождёмся.
Сессии — это просто инструмент. Всё зависит от того, как им пользоваться. Вот из коробки в сессии пишутся группы ресурсов и группы пользователей. В итоге возникает проблема консистентности данных после изменения этих настроек. Это плохое использование сессий. А в ajaxForm использование сессий вполне обосновано.
И это глобально никак не влияет на разрастание таблицы сессий.
По большей части проблема или в неправильной настройке сборщика мусора (не зависит от MODX) или в ботах (о чём писал Алексей в своей статье), ибо каждый запрос бота вызывает создание новой записи в таблице. С гостями особой проблемы нет — запись создаётся только один раз и будет использоваться в течение 7 дней, потом будет удалена и создана другая (разговор про один браузер и стандартные настройки). Пример как игнорировать ботов и не создавать для них сессии есть у меня на сайте.
В сессиях обычно хранится уникальная информация пользователя. А форма чаще всего используется не персонально для пользователя, а для групп пользователей (боты входят в анонимную группу). Можно было просто создавать записи в БД для группы пользователей, использование сессии здесь не нужно. Можно так же получать массив параметров сниппетов, но для сохранения написать свою одну функцию (+ свой коннектор). Это просто как вариант. Возможно, есть и другие. Я не критикую, а просто высказываю мнение. Никого не хотел обидеть) Возможно, если бы я писал такое дополнение, то тоже выбрал бы лёгкий путь, всё наперёд просчитать сложно, это я понимаю.
Кстати, использование механизма кэширования (в файлах) это тоже хорошее решение. Ключ к кэшу может создать сам пользователь (разработчик конкретного сайта), а по умолчанию использовать группу пользователя.
В сессиях обычно хранится уникальная информация пользователя.Вот у меня только один вопрос — у Вас большой опыт программирования? Вы можете гарантировать, что в форме не будет уникальной информации, как написал Василий? Ой, это второй вопрос.
Т.е. если для 98% пользователей решение отлично подходит, но для 2-х% нет, то его нужно выбросить в пропасть. Ибо это оскорбляет эти 2%. Это не они должны адаптировать решение, а остальные 98%.
Можно было просто создавать записи в БД для группы пользователей, использование сессии здесь не нужно.А ещё можно в догонку спросить? Сколько дополнений Вы создали?
П.С. Я спрашиваю абсолютно по-дружески. )
Василий, рад видеть!
Вопрос по AjaxForm. В описании сказано, используются jQuery.Form и jQuery.jGrowl.
То есть, ему нужен jQuery. Можно ли обойтись без него?
Вопрос по AjaxForm. В описании сказано, используются jQuery.Form и jQuery.jGrowl.
То есть, ему нужен jQuery. Можно ли обойтись без него?
Даже я отвечу: конечно можно, переписываете вот этот файл без сторонних библиотек и все будет работать
github.com/bezumkin/AjaxForm/blob/master/assets/components/ajaxform/js/default.js
github.com/bezumkin/AjaxForm/blob/master/assets/components/ajaxform/js/default.js
В описании сказано, используются jQuery.Form и jQuery.jGrowl.
То есть, ему нужен jQuery.
Можно ли обойтись без него?Я даже не буду ничего отвечать, и процитирую самого автора:
Самый клоунский комментарий, который вызывает улыбку :)))
Здравствуйте Василий.
Извините, что вопрос не по теме.
Github pdoTools github.com/bezumkin/pdoTools — архивирован вами, кто теперь будет им заниматься и будут ли? Или вы кому-то его передали уже?
Спасибо.
Извините, что вопрос не по теме.
Github pdoTools github.com/bezumkin/pdoTools — архивирован вами, кто теперь будет им заниматься и будут ли? Или вы кому-то его передали уже?
Спасибо.
Ничего передавать не нужно, это Open Source — любой человек может сделать форк и выпускать свои версии с любыми исправлениями.
Архивация репозитория означает, что лично я им заниматься не буду, только и всего.
Архивация репозитория означает, что лично я им заниматься не буду, только и всего.
А кто тогда выпускает новые версии и выкладывает их на modstore?
В modstore.pro/packages/utilities/pdotools ссылка на github ведет на вас, у вас последний релиз версии 2.12.3
А на modstore последняя версия pdoTools — 2.12.10
Можно ли тогда обновить ссылку в описании pdoTools на актуальный github?
В modstore.pro/packages/utilities/pdotools ссылка на github ведет на вас, у вас последний релиз версии 2.12.3
А на modstore последняя версия pdoTools — 2.12.10
Можно ли тогда обновить ссылку в описании pdoTools на актуальный github?
Наверное, я просто не так часто пользовался вкладкой releases.
В репозитории та же версия, что и на modstore.
В репозитории та же версия, что и на modstore.
Ясно, спасибо за объяснение.
Казалось бы, совершенно заслуженный камень в мой огородВасилий, я ни в коем случае не хотел кидать в ваш огород камень. Просто указал, что проблема существует и её нужно решать, а не делать костыли. Вы выбрали самый просто способ, но есть и другие. Как минимум можно не сохранять параметры в сессии для ботов, думаю можно найти библиотеку для фильтрации по юзер агенту и т.п. (или написать самому). Не хотел Вас задеть). Уважаю за проделанную работу и полезные дополнения.
Привет, Василий!
Где хранить данные для запуска сниппета через коннектор?А если хранить данные в отдельной таблице? А через ajax передать только id нужной нам формы. И сниппет уже не нужен будет.
Да, если брать за уникальный id хэш от параметров сниппета и получать его потом из запроса юзера — рабочий вариант. Даже, пожалуй, хороший.
Но тут сразу второй вопорос — каждое дополнение будет устанавливать собственную такую таблицу? Или они все должны использовать какую-то общую? Если общую — как дополнениям об этом договориться, требовать какую-то зависимость, типа нового дополнения AjaxSettingsDB?
И если у вызова сниппета будет какой-то уникальный параметр, типа id юзера, то количество записей в такой БД будет ровно тем же, что и у таблицы сессий. Еще встаёт вопрос еще об очистке этой таблицы — сколько дней хранить в ней настройки?
Но, повторюсь, этот вариант мне нравится и в былые времена я мог бы переписать свои дополнения на хранение настроек в одной общей таблице. Кто сейчас это будет делать — вопрос.
Но тут сразу второй вопорос — каждое дополнение будет устанавливать собственную такую таблицу? Или они все должны использовать какую-то общую? Если общую — как дополнениям об этом договориться, требовать какую-то зависимость, типа нового дополнения AjaxSettingsDB?
И если у вызова сниппета будет какой-то уникальный параметр, типа id юзера, то количество записей в такой БД будет ровно тем же, что и у таблицы сессий. Еще встаёт вопрос еще об очистке этой таблицы — сколько дней хранить в ней настройки?
Но, повторюсь, этот вариант мне нравится и в былые времена я мог бы переписать свои дополнения на хранение настроек в одной общей таблице. Кто сейчас это будет делать — вопрос.
И придётся придумывать всё то, что уже есть в сессии. Вообще, в чём проблема-то? В сессии эти данные занимают байты. Ну пусть для всех пользователей это будет килобайты. Ну если уж у тебя большой сайт, то десятки МБ. И то при условии, что все ломятся на страницу с формой. А у большинства это какая-нибудь страница с обратной связью.
Проблемы надо решать по мере их поступления. Вот Алексей споткнулся об гигабайтную таблицу и предложил решение. Но опять же, оно нужно не всем, а только тем, у кого аналогичная проблема. Остальным можно не париться.
Ну а отдельная таблица — это явный оверхед. Тогда уж лучше передавать в форму зашифрованные данные из параметров сниппета в скрытый инпут. В этом случае оверхеда будет гораздо меньше.
Проблемы надо решать по мере их поступления. Вот Алексей споткнулся об гигабайтную таблицу и предложил решение. Но опять же, оно нужно не всем, а только тем, у кого аналогичная проблема. Остальным можно не париться.
Ну а отдельная таблица — это явный оверхед. Тогда уж лучше передавать в форму зашифрованные данные из параметров сниппета в скрытый инпут. В этом случае оверхеда будет гораздо меньше.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.