modxAccount - личный кабинет веб пользователя
Сниппет для регистрации, входа, напоминания пароля и личного кабинета пользователя.
Долго разбирался с параметрами аналогичных сниппетов для регистрации, все они в чём то, да не устраивали, чтобы расширить возможности кабинета, приходилось читать простыни кода и запоминать всю логику. Но намучавшись, решил, что своё решение будет намного быстрее сделать, нежели переделать чужое.
Dmi3yy порекомендовал обратить внимание на класс modUsers от Agel_Nash. Из этого класса и позаимствовал некоторые методы, для упрощения работы.
Что может modxAccount.
Регистрация пользователя, с использованием всех доступных полей юзера, плюс, можно создавать свои настройки юзера в таблице web_user_settings, добавление аватарки, капча.
Восстановление пароля.
Личный кабинет.
Форма входа.
Регистрация
Например поле Адрес, вместо того чтобы предложить юзеру записать весь адрес одной строчкой, можно поставить поля для каждого значения.
далее эти данные запишутся в базу в видесериализованного массива json строки.
Уровень вложенности можно использовать любой, но разумнее дальше 3-4 ого не залезать.
Все новые данные будут перезаписываться в уже существующие поля, либо добавляться новые, как с адресом.
Название address, стоит в исключениях, для того чтобы юзер мог добавить несколько адресов для последующего использования, как например адреса доставки в интернет магазине.
Добавление и ресайз фотографии (аватарки).
Как динамически так и при отправке данных пользователя.
Так же есть возможность подключения капчи
Восстановление пароля
Пользователю высылается новый сгенерированный пароль, если он не менял его, то можно авторизоваться по старому паролю, а новый удалится.
Личный кабинет
Достаточно гибкий для добавления своих возможностей.
Форма входа
Стандартные два поля.
Шаблоны
Шаблоны для формы в html со вставками php кода, можно использовать php сразу в шаблоне, либо все теги modx.
либо использовать чанки, подключив их в &tpl=`ваш чанк`
Личный кабинет с псевдонимом account
в нём создаёте дочерние
Регистрация — register
Профиль — profile
Восстановление пароля — forgot
псевдонимы страниц, будут определять выбор контроллера для каждой страницы.
Далее ставим вызов сниппета на каждой странице.
Личный кабинет — account
Регистрация — register
Профиль — profile
Восстановление пароля — forgot
Вместо псевдонимов контроллеров &controller..., можно поставить id страниц на которых расположен тот или иной вызов сниппета.
&success — перенаправление после удачного действия сниппета.
&userGroupId — id групп, через запятую для нового зарегистрированного пользователя.
вызов сниппета можно сократить до одной строчки
Так же можно использовать свои шаблоны в чанках либо в файлах
и копируете папку со сниппетом (ссылка ниже)
Капча для форм использована своя, поскольку стандартная капча перестаёт работать, если закрывать папку manager через .htaccess (ссылка на гит), либо использовать другую которая пишет значение в сессию $_SESSION['veriword']
В создании сниппета использованы функции из класса modUsers, за последнее исправление в SessionHandler, большое спасибо Pathologic
Свежим взглядом посмотрел DrMorro, после статьи об уязвимостях WebloginPE.
Спасибо Agel_Nash за AJAX финальный метод №4 и подсказки в работе контроллера через ajax и вопросах его безопасности и так же методы из MODxApi и modUsers.
И спасибо Dmi3yy за направления, где и что посмотреть да почитать на данную тему.
Жду ваших комментариев и вопросов по работе сниппета.
UPD: добавлен вывод многомерных массивов в плейсхолдерах чанка шаблона. [+custom_field.address.street+]
UPD: добавлена возможность использования своих шаблонов в чанках или файлах
UPD: замена serialize на json
Долго разбирался с параметрами аналогичных сниппетов для регистрации, все они в чём то, да не устраивали, чтобы расширить возможности кабинета, приходилось читать простыни кода и запоминать всю логику. Но намучавшись, решил, что своё решение будет намного быстрее сделать, нежели переделать чужое.
Dmi3yy порекомендовал обратить внимание на класс modUsers от Agel_Nash. Из этого класса и позаимствовал некоторые методы, для упрощения работы.
Что может modxAccount.
Регистрация пользователя, с использованием всех доступных полей юзера, плюс, можно создавать свои настройки юзера в таблице web_user_settings, добавление аватарки, капча.
Восстановление пароля.
Личный кабинет.
Форма входа.
Регистрация
Например поле Адрес, вместо того чтобы предложить юзеру записать весь адрес одной строчкой, можно поставить поля для каждого значения.
<label>Город</label>
<input type="text" name="custom_field[address][city]" />
<label>Улица</label>
<input type="text" name="custom_field[address][street]" />
<label>Дом</label>
<input type="text" name="custom_field[address][house]" />
<label>Квартира</label>
<input type="text" name="custom_field[address][flat]" />
далее эти данные запишутся в базу в виде
Уровень вложенности можно использовать любой, но разумнее дальше 3-4 ого не залезать.
<input type="text" name="custom_field[1][2][3][4]" />
Все новые данные будут перезаписываться в уже существующие поля, либо добавляться новые, как с адресом.
Название address, стоит в исключениях, для того чтобы юзер мог добавить несколько адресов для последующего использования, как например адреса доставки в интернет магазине.
Добавление и ресайз фотографии (аватарки).
Как динамически так и при отправке данных пользователя.
Так же есть возможность подключения капчи
Восстановление пароля
Пользователю высылается новый сгенерированный пароль, если он не менял его, то можно авторизоваться по старому паролю, а новый удалится.
Личный кабинет
Достаточно гибкий для добавления своих возможностей.
Форма входа
Стандартные два поля.
Шаблоны
Шаблоны для формы в html со вставками php кода, можно использовать php сразу в шаблоне, либо все теги modx.
<input type="text" name="email" value="<?= $email ?>" placeholder="mail@mail.ru">
<? if($error_email) { ?>
<div class="text-danger">
<?= $error_email ?>
</div>
<? } ?>
либо использовать чанки, подключив их в &tpl=`ваш чанк`
<input type="text" name="email" value="[+email+]" placeholder="mail@mail.ru">
<@IF:[+error_email+]>
<div class="text-danger">
[+error_email+]
</div>
<@ENDIF>
<input class="form-control" type="text" id="address" name="custom_field[address][street]" value="[+custom_field.address.street+]">
<@IF:[+error_custom_field.address.street+]>
<div class="text-danger">
[+error_custom_field.address.street+]
</div>
<@ENDIF>
Установка
Создаёте документЛичный кабинет с псевдонимом account
в нём создаёте дочерние
Регистрация — register
Профиль — profile
Восстановление пароля — forgot
псевдонимы страниц, будут определять выбор контроллера для каждой страницы.
Далее ставим вызов сниппета на каждой странице.
Личный кабинет — account
[!account?
&controller=`account`
&controllerRegister=`account/register`
&controllerLogin=`account`
&controllerForgot=`account/forgot`
&controllerProfile=`account/profile`
&success=``
&userGroupId=``
!]
Регистрация — register
[!account?
&controller=`account/register`
&controllerRegister=`account/register`
&controllerLogin=`account`
&controllerForgot=`account/forgot`
&controllerProfile=`account/profile`
&success=``
&userGroupId=``
!]
Профиль — profile
[!account?
&controller=`account/profile`
&controllerRegister=`account/register`
&controllerLogin=`account`
&controllerForgot=`account/forgot`
&controllerProfile=`account/profile`
&success=``
&userGroupId=``
!]
Восстановление пароля — forgot
[!account?
&controller=`account/forgot`
&controllerRegister=`account/register`
&controllerLogin=`account`
&controllerForgot=`account/forgot`
&controllerProfile=`account/profile`
&success=``
&userGroupId=``
!]
Вместо псевдонимов контроллеров &controller..., можно поставить id страниц на которых расположен тот или иной вызов сниппета.
&success — перенаправление после удачного действия сниппета.
&userGroupId — id групп, через запятую для нового зарегистрированного пользователя.
В одну строку
При создании вложенности документов, как указанно выше и используя вложенные URL,вызов сниппета можно сократить до одной строчки
[!account?&userGroupId=``!]
Так же можно использовать свои шаблоны в чанках либо в файлах
[!account?
&tpl=`@FILE:assets/snippets/account/view/register.tpl.txt`
&userGroupId=``
!]
Сниппет
Затем создаёте сниппет account с кодом<?php
require MODX_BASE_PATH.'assets/snippets/account/snippet.account.php';
?>
и копируете папку со сниппетом (ссылка ниже)
Капча для форм использована своя, поскольку стандартная капча перестаёт работать, если закрывать папку manager через .htaccess (ссылка на гит), либо использовать другую которая пишет значение в сессию $_SESSION['veriword']
Ajax
Для работы через ajax используется modxLoader, статья на modx.im и код гитеСкачать
Скачать сниппет на гите — modxAccountВ создании сниппета использованы функции из класса modUsers, за последнее исправление в SessionHandler, большое спасибо Pathologic
Свежим взглядом посмотрел DrMorro, после статьи об уязвимостях WebloginPE.
Спасибо Agel_Nash за AJAX финальный метод №4 и подсказки в работе контроллера через ajax и вопросах его безопасности и так же методы из MODxApi и modUsers.
И спасибо Dmi3yy за направления, где и что посмотреть да почитать на данную тему.
Жду ваших комментариев и вопросов по работе сниппета.
UPD: добавлен вывод многомерных массивов в плейсхолдерах чанка шаблона. [+custom_field.address.street+]
UPD: добавлена возможность использования своих шаблонов в чанках или файлах
UPD: замена serialize на json
97 комментариев
2. Зачем было избретать велосипед в виде Account.abstract.php почти на полном копипасте, если можно было взять modUsers? modUsers входит в стандартный комплект MODxAPI, который поставляется в комплекте с DocLister.
3. Разработчики modUsers. Спасибо Pathologic за помощь.
Вот еще что. Я понимаю, что нативная шаблонизация это круто. Но несколько не по канонам MODX. Нельзя просто так взять и назначить чанк. При учете, что имя шаблона жестко зашито в коде, мы получаем дикий гемор при обновлениях. Вроде как и шаблоны нужно включить в комплект. И в то же время обновление перезапишет наши изменения. Таким образом подходим к необходимости еще и в поддержке штатной шаблонизации MODX. Либо лезем в DocumentParser, либо идем за расширенной поддержкой в DLTemplate из того же комплекта DocLister.
Вопрос. Как правильнее сделать?
Изолировать имена плейсхолдеров от совпадения или можно оставить свои имена?
[+email+] или [+post.email+] [+user.email+] [+ma.email+]
[+error_email+] или [+error.email+] [+ma.error_email+]
custom_field[address][street] => [+custom_field.address.street+]
А проблемы не вижу используем getTpl + ParseText 2 метода из АПи и все, просто и лаконично и в стиле MODX. Выигрыша в вашем решении на нативном шаблонизаторе тут нет. А вот минусы в понимании больше.
А по поводу разработчиков, извини Жень, поторопился.
Точно так же начинался мой FormLister (: Но я все же пошел путем использования уже существующих решений, т.е. modUsers и DLTemplate, а часть кода оформил так, чтобы можно было не велосипедить в будущем: валидация, работа с параметрами, отправка почты, лексиконы.
Простое заимствование методов, я считаю плохой идеей. Вот после статьи DrMorro отправилось исправление в modUsers (на очереди еще одно по той же статье) — соответственно все сниппеты на modUsers будут правильно выставлять куку. В DLTemplate запланировано добавить поддержку Twig — опять же она появится всюду, где используется DLTemplate. Или, возвращаясь к пользователям, у меня был вариант делать поддержку плагинов в своем коде, как сделал Женя в DLUsers, но я вместо этого добавил вызов событий в modUsers, чтобы в будущем не приходилось возвращаться к этому вопросу. Еще более наглядный пример — SimpleGallery; если бы я не использовал DocLister, то пришлось бы городить велозавод, а через пару месяцев я бы запутался и бросил это все (:
Да, и еще, мне кажется что у вас при регистрации не проверяется никак уникальность пользователя?
Я правда сам пока пилю EvoShop простыми запросами но потом когда буду рефакторить думаю перевесить на DocLister все выборки
Это добавит однотипности кода а соответственно более быстрого его понимания другими;) ведь проще разобраться в одном решени. Чем с 10тком разных
Велосипед тут не получился, а получился самокат) поскольку не используется modxApi.
И при регистрации проверяется имя пользователя. Так же если нет в форме поля username, то используется email.
И всё таки modUsers — это класс для работы с пользователями, а не готовое решение для использования, скопировал код, скачал файлы и всё работает.
FormLister ещё тоже надо настраивать, почитать, правила создать… для новичков это не так просто.
В modxAccount можно добавить свои функции в каждый контроллер, например при входе, записывать в сессию содержимое корзины или товаров в закладках, которые ранее зарегистрированный юзер добавлял к себе. А при выходе очищать корзину и закладки.
Читабельный код — render — validate — действие. И плюс аякс с готовым кодом.
В будущем если modxAccount начнёт расползаться функционально, то исправить на использование modUsers будет проще простого.
В SimpleGallery тоже можно (1, 2, 3)
А никто и не говорит, что это готовое решение. Вам говорят, что это более или менее полноценный класс для работы с пользователями. В котором есть даже то, что на данном этапе вам и не нужно, но может пригодиться в будущем.
В рамках MODX это делается плагинами, а не контроллерами. Я понимаю, что вы хотите придерживаться общепринятых норм разработки, но давайте условимся, что в MODX это не работает. По крайней мере для этого тут придумали абсолютно другие средства.
За рендер и шаблонизацию мы уже выше разговаривали. Валидация тоже есть, но вы пока не научились ей пользоваться;-)
Желаю удачи в завоевании мира.
У меня все, поэтому больше не буду тратить ни свое, ни ваше время.
Все мы знаем о существующих сниппетах для регистрации, и все нужно запускать с бубном и танцами.
Это личный кабинет, а не главное достояние сайта, поэтому и решения должны быть простыми и доступными. А то получается, чтобы создать регистрацию пользователя, человек тратит большую часть времени.
Все говорят, это есть, то есть, всё уже готово, зачем велосипеды… покажите, где готово? где взять?, чтобы поставил и забыл.
Так и пришлось что то своё пилить.
Хотя от обновленного решения из коробки по авторизации/регистрации/редактированию личных данных я бы не отказался, особенно в свете проблем безопасности :)
Точно так же и шаблонизация DLTemplate. Вас же не смущает использование $modx->parseText() и $modx->getTpl(), которые обладают меньшим функцоиналом.
Я бы еще понял, что вы хотите упростить людям задачу, поэтому понадергали методов из разных источников собрав воедино свое. И ладно если бы нужно было что-то дополнительно устанавливать. Но ведь нет. С недавних пор эти классы идут в базовой комплектации MODX Evo. Бери, да пользуй…
Надеюсь теперь вы правильно поймете мой посыл, а не будете уповать на то, что аналогов вашему решению нет. Да, их нет. Но наша песня совсем не о том.
А то, что в моём сниппете «чистятся» все отправляемые на сервер данные, обуславливается скорее всего тем, что кроме текстовых данных записывать в базу ничего не планировалось.
Не обижайтесь, но вот вам пример: если вдруг, мы добавим глобально twig в DLTemplate. То только ваше решение будет работать по старинке и только затормозит весь процесс. Либо пользователи и дальше продолжать верстать плейсхолдерами. Либо будут изобретать новый modxAccount.
Пример 2 — более реальный. Помните историю с переходом на mysqli? Проблема была в том, что не во всех решениях использовался $modx->db. Многие решения работали с mysql_query напрямую.
Пример 3 — еще реальней. Помните как долго мы отлавливали ошибки в сниппетах, где был жестко зашит путь к папке manager? Казалось бы — я добавил лишь одну новую константу. И невозможное (переименовывание папки админки) стало возможным.
Еще раз! Я не говорю, что вы сделали ненужную работу. Я не говорю, что вы написали сниппет который уже есть. Я говорю лишь о том, что вы копипастом берете код из ядра за основу и немного правите.
Вот вы говорите, что нет документации. При этом пишете код. Делаете копипаст кода из одного места в другое. метод genPass
Не думаю, что тут нужна какая-то документация, чтобы не копипастить.
Идем дальше.
Да, возможно это не так просто. Но ведь документация есть!
Поэтому ну не верю я во все эти отговорки: там класс большой, тут документации нет, а это вообще отдельно качать нужно. Я скорее поверю в отсутствие желания разбираться.
полагаю в этой папке 'assets/templates' должны сохранятся все шаблоны?
И почему по старинке?, методы parseText и getTpl, это же встроенные в Modx методы. Немного не понял, чем в данном случае DLTemplate может быть полезен.
genPass зачем ради строчки кода, подключать ещё один класс?
и ссылочка, на документацию битая((
Действительно. Думаю
всегда можно обойтись штатным DocumentParser, который регулярно улучшают.И зачем было всю ветку городить, когда можно было изначально ничего не откуда не брать и при этом получать
такой же функционал.И опять же в процессе спора, данное решение получило дополнительные возможности.
Да и критикуем по сути подход к реализации, в силу своего видения положения дел в Evo, а не потому что метод откуда-то скопирован. Так-то у вас идеи хорошие, но по мне так отказ от готовых наработок — это лишняя трата времени и путь в никуда. Если бы над решениями работали вместе, то и время бы сэкономили и для сообщества больше пользы, как мне кажется.
А простым пользователям может и будет компонент интересен, значит уже не зря старались; опять же сами им пользуетесь. Плюс в результате появились какие-то улучшения, что тоже хорошо. Да и похоронить веблогины это сама по себе неплохая затея.
Ну и раз такое дело, то продолжу критику (: С точки зрения простого пользователя мне уже тяжело критиковать, разве что предположу еще, что валидация телефона не будет работать в моей стране, где номера начинаются с +375 или (0xx).
С точки зрения среднего программиста, слишком много хард-кода и мало свободы в доработках. FormLister в этом смысле можно допиливать, не только расширяя классы, но и традиционно сниппетами и плагинами. А что у меня не коробочное решение — так я просто не хотел навязывать свою верстку и js. Так, в minishop2 я прилично перелопатил клиентскую часть, чтобы было так, как хочу я — но не факт, что я сделал лучше. Если я добавлю в FormLister готовые формы и конфиги, то вызов сниппета будет тоже в 5-6 строчек и типа коробочное решение, поставил и все проблемы решены. Однако проблемы простых пользователей, которые берутся делать личные кабинеты, не понимая, что к чему, меня не особо и тревожат.
Пару лет назад я бы поставил и попробовал и может даже успешно, все ж проще, чем WebLoginPE. Но на сегодняшний день мне важнее удобство допила, чем готовые формы и ajax.
Так же хотел порядка в коде и папках.
account — отвечает за манипуляции юзера связанные с личными данными, корзина, вишлист, сравнение, адреса доставки, оплаты, заказы, возвраты.
catalog — вывод каталога товаров и всё что по товарам (акции, скидки, производители, свойства товаров и так далее)
blog — всё что связанно со статьями, новостями и блогами
Именно своего сниппета я сделал несколько версий, и сниппетами с простынёй кода, и классы и подклассы и через загрузчики и так далее… и смотрел что быстрее и что проще понимается. Так же расширяемость, подключил расширение класса и новые возможности в кабинете и так же управление через аякс, что мне не маловажно. И вот только после того как всё будет работать, можно будет и подумать и подключении полного modxApi со всеми плюшками.
А что до лоадеров, то приятнее в коде писать
поэтому даже представил своё видение работы с modx, причём в самом modx всё это можно реализовать и переписать ядро, без того, что что-то не будет работать из старого, как пример поставить выбор в настройках modx — использовать поддержку старого API.
Простите, что не ответил как это сделать, поскольку не сталкивался с тем, что ресурсы создаёт веб-пользователь.
Ответы с uLogin от сервера, причесать ещё надо, но вообще возможно.
Вопрос:
Почему не обрабатываются <@IF:><@ENDIF>?
При подключении без шаблона такой проблемы нет
Те что с расширением txt — их содержимое копируется в чанки и дальше меняется под себя.
с расширением tpl — подключаются и отрабатываются как php
а вызов
тоже с ошибками показывается?
При удалении @file и изменении базового tpl шаблона все заработало, записалось и вынулось из базы нормально
При подключении нестандартного файла tpl работать отказалось выдало ошибки вида <?=$переменная>
При подкючении через tpl из админки отказалось писать все в базу, не подхватывало ошибки.
Сломать много ума не надо и талант тестера не пропьешь, видимо))))
1. Добавляем дополнительные поля в таблицу web_user_attributes
2. Добавляем дополнительные поля в массив в файле Account.abstract.php
3. Добавляем обработчик ошибок в profile.php и register.php?
Можно ли подключить дополнительную таблицу, например, web_user_attributes_extended и писать дополнительные поля туда?
достаточно добавить в форму поле с именем custom_field[название_поля]
и они запишутся в таблицу web_user_settings
Execution of a query to the database failed — You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE id=9' at line 4"
ошибка web_custom_field.
в базе русские символы вот так выглядят {«street»:«u0443u043bu0438u0446u0430»,«house»:«4»,«city»:«u0433u043eu0440u043eu0434»}
версия 1.2-d8.1.5. php 5.6
почему ошибка появляется и редирект не происходит, хотя данные пишутся?
в файле github.com/64j/ModxAccount/blob/master/account/controller/register.php#L290
заменить на
в файле
github.com/64j/ModxAccount/blob/master/account/controller/profile.php#L288
github.com/64j/ModxAccount/blob/master/account/controller/profile.php#L293
заменить на
позже обновлю на гите
jquery.min.js подключен выше, плагин modxloader не активен. Аякс подключен через Файл
Uncaught TypeError: $ is not a function
строка $(document).ready(function() {
При этом кнопка сохранить работает, но не работает загрузка фото
Активируем modxloader кнопка сохранить ломается, пропадают ошибки, но появляется загрузка фотографий.
При замене шаблона даты в DOB надо ли что-нибудь менять в базе данных в графе DOB?
Уведомление от сайта…
Not Found
Not Found
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" «www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd»>
и далее исходный код страницы
и ничего не происходит.
modx.im/blog/addons/4747.html
Или без ID параметра?
либо
либо в самом шаблоне через if/else
редирект на страницу с id=1
По умолчанию перекидывает на /account.html
modx 1.2.1
php-5.3
по указанному адресу файл есть?
что не так делаю?
ModxLoader установили?
ModxCaptcha установили?
ajax.php создали?
шаблоны свои используете или те что по умолчанию идут?
Устанавливали с гита по документации?
jQuery есть на странице?
2. Устанавливали с гита по документации — да
3. шаблоны свои используете или те что по умолчанию идут? — свои
4. ModxLoader и ModxCaptcha — файлы залил
5. ajax.php — тут можно поподробние?
что нужно ещё подключить?
нужно на основном делать?
на тестовому всё тестую сначала
Если ajax.php лежит не в корне сайта и рядом с ним нет файла index.php, исправляйте в файле пути, чтобы он мог получить доступ к index.php.
github.com/64j/ModxLoader#modxloader
ещё б с капчей розобраться… а то что-то не работает(
вот такое
я залил папку captcha в папку assets/
что еще нужно сделать?
site.com/assets/captcha/ — покажет картинку
подскажите, пожалуйства
Обнаружилась следующая проблема на iOS не возможно зарегистрироваться/войти в ЛК, кнопка вход не доступна.
Проблема связана с обработкой события click (конкретно тут не обрабатывается $('#loginform :submit').click(function(e) )
Описание проблемы stackoverflow.com
Там же есть варианты решений. Тестирую на самое простое.
Вопрос простой: как сделать поля в профиле необязательными?
Из коробки в tpl профиля имя, мыло и телефон идут со звездочками, остальные поля личной информации — нет. Однако, при отправке формы возвращаются ошибки на все поля.
Может быть, я что-то не правильно сделал? Вызов сниппета:
[!account?
&controllerProfile=`auth/profile`
&tpl=`@FILE:assets/snippets/account/view/profile.tpl.txt`
!]