[СДЕЛАЙ САМ] Авторизация и регистрация по СМС
Всем привет. Я ни на что не претендую, прекрасно понимаю, что вариантов решения данной задачи много, и мой, наверное, не лучший, но меня попросили написать решение и эту инструкцию, поэтому поехали.
Нам понадобится:
Начнём с чанка корзины. Добавим туда ссылку на страницу оформления заказа для авторизованных пользователей и кнопку открытия формы авторизации/регистрации для неавторизованных пользователей.
Сюда же добавим модальное окно с формой авторизации/регистрации
Чанк с формой авторизации/регистрации checkcodeForm.html выглядит так
Чтобы закончить с клиентской частью, создаем файл с названием, например, sms-auth.js, с таким контентом
И внесём небольшую правку в исходники ajaxForm, а именно закомментируем в файле assets/components/ajaxform/js/default.js 66 строку, там должно быть это
Для отправки СМС будем использовать api SMSЦентр. Скачиваем файл smsc_api.php и в начале файла меняем
Теперь можно создать сниппет, который будет запускать отправку смс, назовём его codeSender
Теперь надо рассказать modx как с этой таблицей работать, для этого воспользуемся дополнением CMPGenerator. Открываем его интерфейс и нажимаем Create Package. Появившуюся форму заполняем как наследующем скрине
Потом жмём сохранить. Переходим в Console и выполняем вот такой код
Можем переходить к сниппету smsAuth, основные моменты я прокомментировал.
Тут вы вероятно заметили, что есть сниппет genPassword, изнутри он выглядит так
Регистрацию я сделал так (Registration)
Авторизацию вот так (Authorization)
Теперь нужно сделать так, чтобы minishop2 использовал уже зарегистрированного пользователя в качестве получателя заказа. Для этого немного расширим класс core/components/minishop2/model/minishop2/msorderhandler.class.php, а точнее метод submit. Для этого создаем файл core/elements/code/customOrderHandler.class.php с вот таким содержимым
На этом всё!
Нам понадобится:
- Console
- CMP Generator
- AjaxForm
- miniShop2
Начнём с чанка корзины. Добавим туда ссылку на страницу оформления заказа для авторизованных пользователей и кнопку открытия формы авторизации/регистрации для неавторизованных пользователей.
{if $_modx->user.id > 0}
<a href="{13 | url}"> <!-- 13 это id ресурса с формой оформления заказа -->
<button type="submit" class="knopka2">
Оформить заказ
</button>
</a>
{else}
<button type="button" data-toggle="modal" data-target="#modalSMSAuth" class="knopka2">
Оформить заказ
</button>
{/if}
Сюда же добавим модальное окно с формой авторизации/регистрации
<!-- MODAL -->
<div class="modal" id="modalSMSAuth" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="btn-close" data-dismiss="modal" aria-label="Close">X</button>
</div>
<div class="modal-body row">
{'!AjaxForm' | snippet:[
'snippet' =>'smsAuth',
'form' =>'@FILE chunks/forms/checkcodeForm.html',
'redirectTo' => 12
]}
</div>
</div>
</div>
</div>
<!-- /MODAL -->
Чанк с формой авторизации/регистрации checkcodeForm.html выглядит так
<form class="col-12">
<div class="row">
<label class="col-12">
<input type="tel" class="d-block input_sms_nam" name="phone" placeholder="+7(999)888-77-66">
<span class="error error_phone"></span>
</label>
<label class="col-12">
<small class="modal__text">Нет пароля или Вы его забыли?
Оставьте поле пустым, и мы отправим новый пароль в СМС</small>
<input type="text" class="d-block input_sms_cod" name="code" placeholder="Пароль">
<span class="error error_code"></span>
</label>
<div class="col-lg-6 offset-lg-3">
<button class="btn btn-primary">Войти</button>
</div>
</div>
</form>
Чтобы закончить с клиентской частью, создаем файл с названием, например, sms-auth.js, с таким контентом
// Маска ввода номера телефона
let phoneMask = document.querySelectorAll('input[type="tel"]');
for (let i = 0; i < phoneMask.length; i++) {
phoneMask[i].addEventListener('keydown', function (event) {
if (!(event.key == 'ArrowLeft' || event.key == 'ArrowRight' || event.key == 'Backspace' || event.key == 'Tab')) {
event.preventDefault()
}
let mask = '+7 (111) 111-11-11'; // Задаем маску
if (/[0-9\+\ \-\(\)]/.test(event.key)) {
let currentString = this.value;
let currentLength = currentString.length;
if (/[0-9]/.test(event.key)) {
for (let i = currentLength; i < mask.length; i++) {
let number = event.key;
if (mask[i] == '1') {
if (i == 4 && number != '9') {
number = '';
}
this.value = currentString + number;
break;
}
currentString += mask[i];
}
}
}
});
}
// Обработка ответа сервера
$(document).on('af_complete', function (e, response) {
if(response.data.redirectTo){
setTimeout(function(){
document.location.href = response.data.redirectTo; // просто делаем редирект на нужную страницу
},2000);
}
});
И внесём небольшую правку в исходники ajaxForm, а именно закомментируем в файле assets/components/ajaxform/js/default.js 66 строку, там должно быть это
form[0].reset();
Для отправки СМС будем использовать api SMSЦентр. Скачиваем файл smsc_api.php и в начале файла меняем
// SMSC.RU API (smsc.ru) версия 3.8 (03.07.2019)
define("SMSC_LOGIN", "login"); // логин клиента
define("SMSC_PASSWORD", "password"); // пароль
define("SMSC_POST", 0); // использовать метод POST
define("SMSC_HTTPS", 0); // использовать HTTPS протокол
define("SMSC_CHARSET", "windows-1251"); // кодировка сообщения: utf-8, koi8-r или windows-1251 (по умолчанию)
define("SMSC_DEBUG", 0); // флаг отладки
define("SMTP_FROM", "api@smsc.ru"); // e-mail адрес отправителя
на// Подключаем Modx API
define('MODX_API_MODE', true);
require_once $_SERVER['DOCUMENT_ROOT'] . '/index.php';
// SMSC.RU API (smsc.ru) версия 3.8 (03.07.2019)
define("SMSC_LOGIN", $modx->getOption('smsc_login')); // логин клиента
define("SMSC_PASSWORD", $modx->getOption('smsc_password')); // пароль
define("SMSC_POST", $modx->getOption('smsc_post')); // использовать метод POST
define("SMSC_HTTPS", $modx->getOption('smsc_https')); // использовать HTTPS протокол
define("SMSC_CHARSET", $modx->getOption('smsc_charset')); // кодировка сообщения: utf-8, koi8-r или windows-1251 (по умолчанию)
define("SMSC_DEBUG", $modx->getOption('smsc_debug')); // флаг отладки
define("SMTP_FROM", $modx->getOption('smsc_smtp_from')); // e-mail адрес отправителя
Все параметры указанные в методах $modx->getOption надо создать в системных настройках, думаю это понятно.Теперь можно создать сниппет, который будет запускать отправку смс, назовём его codeSender
<?php
$file = MODX_CORE_PATH . 'components/codesender/smsc_api.php';
if(!file_exists($file)){
$modx->log(1, 'FILE NOT FOUND');
}
include_once $file;
if(!isset($translit)){
$translit = 1; // по умолчанию отправляем транслит, там можно впихнуть больше текста
}
$send = send_sms($number, $message, $translit);
return $send;
Чтобы можно было проверять отправленные коды, нужно их куда-то сохранять. Для этого создадим в базе данных новую таблицу modx_codesender на 5 полей с настройками как на скриншоте нижеТеперь надо рассказать modx как с этой таблицей работать, для этого воспользуемся дополнением CMPGenerator. Открываем его интерфейс и нажимаем Create Package. Появившуюся форму заполняем как наследующем скрине
Потом жмём сохранить. Переходим в Console и выполняем вот такой код
$modx->addExtensionPackage('codesender', '[[++core_path]]components/codesender/model/');
Очищаем кэш и проверяем всё ли у нас получилось, выполнив следующий код$sms = $modx->newObject('Codesender', array('username' => '79998887766', 'code' => '0000', 'text' => 'Test'));
$sms->save();
Если ошибок нет, значит всё хорошо, если есть внимательно проверяем пути к файлам.Можем переходить к сниппету smsAuth, основные моменты я прокомментировал.
<?php
if(!($username = preg_replace('/[^0-9]/', '', trim($_POST['phone'])))){ // проверяем введен ли номер телефона
return $AjaxForm->error('Исправьте ошибки в форме', array('phone' => 'Введите номер телефона'));
}
$user = $modx->getObject('modUser', array('username'=> $username)); // получаем пользователя
$inputCode = (int)$_POST['code']; // получаем введенный код
$codesender = $modx->getObject('Codesender', array('username' => $username)); // получаем данные об отправленном коде из БД
if(!$inputCode){ // если код не ввели
if($codesender){ // и если мы его уже отправили
$timeOut = 120; // задаем задержку повторной отправки
$sendTime = strtotime($codesender->get('date')); // получаем дату предыдущей отправки кода
$now = time(); // получаем текущее время
if(($now - $sendTime) < $timeOut){ // не даем слишком часто запрашивать пароль
return $AjaxForm->error('Повторно запросить код Вы сможете через ' .($timeOut - ($now - $sendTime)) . ' cек.' , array());
}
}
$inputCode = $modx->runSnippet('genPassword', array('length' => 6, 'type' => 'code')); // генерируем код
$text = 'Пароль для сайта ' . $modx->getOption('http_host').': ' . $inputCode; // формируем сообщение
$send = $modx->runSnippet('codeSender', array('number' => $username, 'message' => $text)); //отправляем СМС с кодом
// если отправка не удалась
if(count($send) == 2){
switch ($send[1]){
case -7:
$message = 'Неверный формат номера телефона. Код подтверждения не отправлен.';
break;
case -8:
$message = 'Сообщение на указанный номер не может быть доставлено. Введите другой номер и повторите попытку';
break;
default:
$message = 'Код подтверждения не отправлен. Введите другой номер и повторите попытку';
break;
}
return $AjaxForm->error($message, array());
}
// записываем код в БД
$sms = $modx->newObject('Codesender', array('username' => $username, 'code' => $inputCode, 'text' => $text));
$sms->save();
if($user){
// обновляем пароль пользователя
$user->set('password', $inputCode);
$user->save();
}
return $AjaxForm->success('Пароль успешно отправлен', array());
}
$params = array('username' => $username, 'password' => $inputCode, 'group' => 2, 'active' => true, 'blocked' => false); // массив с данными для авторизации/регистрации
if(!$user){ // проверяем существует ли пользователь
$dbcode = (int)$codesender->get('code'); // получаем отправленный код
if($inputCode != $dbcode){ // проверяем совпадают ли коды
return $AjaxForm->error('Исправьте ошибки в форме', array('code'=> 'Введен неверный пароль'));
}
$codesender->remove(); // удаляем код из БД если проверка прошла успешно
// если нет - регистрируем
$user = $modx->runSnippet('Registration', array('params' => $params));
$user->set('password', $inputCode);
$user->save();
}
$response = $modx->runSnippet('Authorization', array('params' => $params));
if(!$response['success']){
return $AjaxForm->error($response['message'], array());
}
$redirectId = $scriptProperties['redirectTo'] ?: 1;
$redirectUrl = $modx->makeUrl($redirectId, 'web', '', 'full');
return $AjaxForm->success($response['message'], array('redirectTo' => $redirectUrl));
Тут вы вероятно заметили, что есть сниппет genPassword, изнутри он выглядит так
<?php
if(!$length){
$length = $modx->getOption('password_min_length');
}
if(!$type){
$type = 'pass';
}
//$modx->log(1, 'LENGTH ' . $length);
//$modx->log(1, 'TYPE ' . $type);
/* Более сложный генератор паролей с любыми символами */
$password = "";
/* Массив со всеми возможными символами в пароле */
switch ($type){
case 'pass':
$arr = array(
'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', '1', '2',
'3', '4', '5', '6', '7', '8',
'9', '0', '#', '!', "?", "&"
);
break;
case 'hash':
$arr = array(
'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', '1', '2',
'3', '4', '5', '6', '7', '8',
'9', '0'
);
break;
case 'code':
$arr = array('1', '2', '3', '4', '5', '6', '7', '8', '9', '0');
break;
}
for ($i = 0; $i < $length; $i++){
$password .= $arr[mt_rand(0, count($arr) - 1)]; // Берём случайный элемент из массива
}
return $password;
Регистрацию я сделал так (Registration)
<?php
$user = $modx->newObject('modUser'); // создаем пользователя
$user->set('username', $params['username']); // задаем имя пользователя
$user->set('password', $params['password']); // задаем пароль
$profile = $modx->newObject('modUserProfile'); // создаем профиль
if(!$params['email']){
$params['email'] = $params['username'] . '@' . $_SERVER['HTTP_HOST'];
}
if(!$params['phone']){
$params['phone'] = preg_replace('/(\d)(\d{3})(\d{3})(\d{2})(\d{2})$/', '+7(\2)\3-\4-\5', $params['username']);
}
$params['extended'] = $extended;
// инициализируем поля
$profile->fromArray($params);
$user->addOne($profile); // добавляем профиль к пользователю
$profile->save(); // сохраняем профиль
$user->save(); // сохраняем пользователя
$user->joinGroup($params['group'],1); // добавляем пользователя в группу только после сохранения объекта пользователя
setcookie('user_id', $user->get('id'));
if(!$user){
return false;
}
return $user;
Авторизацию вот так (Authorization)
<?php
$loginData = array(
'username' => $params['username'],
'password' => $params['password'],
'rememberme' => 1,
'login_context' => 'web'
);
$loginResponse = $modx->runProcessor('/security/login', $loginData);
if ($loginResponse->isError()) {
$modx->log(modX::LOG_LEVEL_ERROR, 'login error. Username: '.$params['username'].', Message: '.$loginResponse->getMessage());
return array('success' => false, 'message' => $loginResponse->getMessage());
}
return array('success' => true, 'message' => 'Вы успешно авторизованы');
Теперь нужно сделать так, чтобы minishop2 использовал уже зарегистрированного пользователя в качестве получателя заказа. Для этого немного расширим класс core/components/minishop2/model/minishop2/msorderhandler.class.php, а точнее метод submit. Для этого создаем файл core/elements/code/customOrderHandler.class.php с вот таким содержимым
<?php
if(!class_exists('msOrderInterface')) {
require_once dirname(dirname(dirname(__FILE__))) . '/components/minishop2/model/minishop2/msorderhandler.class.php';
}
class customOrderHandler extends msOrderHandler implements msOrderInterface{
/**
* @param array $data
*
* @return array|string
*/
public function submit($data = array())
{
$response = $this->ms2->invokeEvent('msOnSubmitOrder', array(
'data' => $data,
'order' => $this,
));
if (!$response['success']) {
return $this->error($response['message']);
}
if (!empty($response['data']['data'])) {
$this->set($response['data']['data']);
}
$response = $this->getDeliveryRequiresFields();
if ($this->ms2->config['json_response']) {
$response = json_decode($response, true);
}
if (!$response['success']) {
return $this->error($response['message']);
}
$requires = $response['data']['requires'];
$errors = array();
foreach ($requires as $v) {
if (!empty($v) && empty($this->order[$v])) {
$errors[] = $v;
}
}
if (!empty($errors)) {
return $this->error('ms2_order_err_requires', $errors);
}
// custom code
$user_id = $_COOKIE['user_id'] ?: $this->ms2->getCustomerId();
if (empty($user_id) || !is_int($user_id)) {
return $this->error(is_string($user_id) ? $user_id : 'ms2_err_user_nf');
}
$cart_status = $this->ms2->cart->status();
if (empty($cart_status['total_count'])) {
return $this->error('ms2_order_err_empty');
}
$delivery_cost = $this->getCost(false, true);
$cart_cost = $this->getCost(true, true) - $delivery_cost;
$createdon = date('Y-m-d H:i:s');
/** @var msOrder $order */
$order = $this->modx->newObject('msOrder');
$order->fromArray(array(
'user_id' => $user_id,
'createdon' => $createdon,
'num' => $this->getNum(),
'delivery' => $this->order['delivery'],
'payment' => $this->order['payment'],
'cart_cost' => $cart_cost,
'weight' => $cart_status['total_weight'],
'delivery_cost' => $delivery_cost,
'cost' => $cart_cost + $delivery_cost,
'status' => 0,
'context' => $this->ms2->config['ctx'],
));
// Adding address
/** @var msOrderAddress $address */
$address = $this->modx->newObject('msOrderAddress');
$address->fromArray(array_merge($this->order, array(
'user_id' => $user_id,
'createdon' => $createdon,
)));
$order->addOne($address);
// Adding products
$cart = $this->ms2->cart->get();
$products = array();
foreach ($cart as $v) {
if ($tmp = $this->modx->getObject('msProduct', array('id' => $v['id']))) {
$name = $tmp->get('pagetitle');
} else {
$name = '';
}
/** @var msOrderProduct $product */
$product = $this->modx->newObject('msOrderProduct');
$product->fromArray(array_merge($v, array(
'product_id' => $v['id'],
'name' => $name,
'cost' => $v['price'] * $v['count'],
)));
$products[] = $product;
}
$order->addMany($products);
$response = $this->ms2->invokeEvent('msOnBeforeCreateOrder', array(
'msOrder' => $order,
'order' => $this,
));
if (!$response['success']) {
return $this->error($response['message']);
}
if ($order->save()) {
$response = $this->ms2->invokeEvent('msOnCreateOrder', array(
'msOrder' => $order,
'order' => $this,
));
if (!$response['success']) {
return $this->error($response['message']);
}
$this->ms2->cart->clean();
$this->clean();
if (empty($_SESSION['minishop2']['orders'])) {
$_SESSION['minishop2']['orders'] = array();
}
$_SESSION['minishop2']['orders'][] = $order->get('id');
// Trying to set status "new"
$response = $this->ms2->changeOrderStatus($order->get('id'), 1);
if ($response !== true) {
return $this->error($response, array('msorder' => $order->get('id')));
}
// Reload order object after changes in changeOrderStatus method
$order = $this->modx->getObject('msOrder', array('id' => $order->get('id')));
/** @var msPayment $payment */
if ($payment = $this->modx->getObject('msPayment',
array('id' => $order->get('payment'), 'active' => 1))
) {
$response = $payment->send($order);
if ($this->config['json_response']) {
@session_write_close();
exit(is_array($response) ? json_encode($response) : $response);
} else {
if (!empty($response['data']['redirect'])) {
$this->modx->sendRedirect($response['data']['redirect']);
} elseif (!empty($response['data']['msorder'])) {
$this->modx->sendRedirect(
$this->modx->context->makeUrl(
$this->modx->resource->id,
array('msorder' => $response['data']['msorder'])
)
);
} else {
$this->modx->sendRedirect($this->modx->context->makeUrl($this->modx->resource->id));
}
return $this->success();
}
} else {
if ($this->ms2->config['json_response']) {
return $this->success('', array('msorder' => $order->get('id')));
} else {
$this->modx->sendRedirect(
$this->modx->context->makeUrl(
$this->modx->resource->id,
array('msorder' => $response['data']['msorder'])
)
);
return $this->success();
}
}
}
return $this->error();
}
}
В Console запускаем следующий кодif ($miniShop2 = $modx->getService('miniShop2')) {
$miniShop2->addService('order', 'CustomOrderHandler',
'{core_path}elements/code/customOrderHandler.class.php'
);
}
В системных настройках меняем значение ms2_order_handler_class на customOrderHandler.На этом всё!
Поблагодарить автора
Отправить деньги
Комментарии: 25
Хорошая статья.
От себя могу добавить, сниппет genPassword можно не писать. У класса modUser есть метод generatePassword. В который тоже можно передать длину пароля
От себя могу добавить, сниппет genPassword можно не писать. У класса modUser есть метод generatePassword. В который тоже можно передать длину пароля
Спасибо за комментарий, но причина появления сниппета genPassword не в длине пароля, а в его составе, в своём сниппите я могу генерировать числовой код, а если использовать стандартный механизм там будут разные символы, а не только числа. Людям удобнее вводить числа, как показала практика и надёжность пароля им не важна. Ещё я думаю, что наверное после авторизации надо менять пароль ещё раз на более сложный, чтоб никто другой войти не смог. Хотя возможно это излишняя предосторожность.
Простыня кода, три строчки текста, никаких объяснений, нулевая информативность.
Что именно тебе непонятно в коде?
Мне как раз все понятно.
Более того, ты же ниже создаешь пакет, какая проблема примутить к нему класс-контроллер?
Тут кстати гораздо логичнее была бы проверка на false.
Итого: куски сомнительного кода не несущие абсолютно никакой ценности.
Я бы ни слова ни сказал, даже плюсик бы залепил если бы тут было хоть какое-то объяснение происходящего.
Почему так, а не иначе, почему это лучше, а это хуже.
Итого ты не учишь, а даешь людям копировать плохие практики.
Абсолютно заслуженный минус
{if $_modx->user.id > 0}
<a href="[[~13]]"> <!-- 13 это id ресурса с формой оформления заказа -->
<button type="submit" class="knopka2">
Оформить заказ
</button>
</a>
{else}
<button type="button" data-toggle="modal" data-target="#modalSMSAuth" class="knopka2">
Оформить заказ
</button>
{/if}
Помесь стандартного и fenom синтаксиса это дурной тон.{'!AjaxForm' | snippet:[
'snippet' =>'custConfirm',
'form' =>'@FILE chunks/forms/confirmForm.html',
'validate'=>'phone:required'
]}
{'!AjaxForm' | snippet:[
'snippet' =>'custCheckCode',
'customValidators' => 'validateCode'
'form' =>'@FILE chunks/forms/checkcodeForm.html',
'validate'=>'phone:required,code:validateCode',
'redirectTo' => 13
]}
Два некешированных вызова AjaxForm. А че ж не 5? Эту задачу можно решить одним вызовом сниппета.<?php
$file = MODX_CORE_PATH . 'components/codesender/smsc_api.php';
if(!file_exists($file)){
$modx->log(1, 'FILE NOT FOUND');
}
include_once $file;
if(!isset($translit)){
$translit = 1; // по умолчанию отправляем транслит, там можно впихнуть больше текста
}
$send = send_sms($number, $message, $translit);
return $send;
Такого рода задачи решаются не сниппетами. Сниппеты это вообще про другое. Более того, ты же ниже создаешь пакет, какая проблема примутить к нему класс-контроллер?
Тут вы вероятно заметили, что есть сниппет genPassword, изнутри он выглядит такОпять же а) Не решаются такие задачи сниппетами б) mt_rand не является безопасным для задач уровня генерации паролей. Ты бы это знал, если бы писал это сам.
Итак, выходим на финишную прямую. Сниппет custCheckCode отвечает за проверку кода, авторизацию и регистрацию пользователейСнова, такие задачи не решаются сниппетами.
// если ошибок нет
if($_POST['phone']){
$username = preg_replace('/[^0-9]/', '', trim($_POST['phone']));
$params = array('username' => $username, 'password' => $_POST['code'], 'group' => 2, 'active' => true, 'blocked' => false);
$params = array_merge($_POST, $params);
$user = $modx->getObject('modUser', array('username' => $username));
if(!$user){
$modx->log(1, 'Регистрация');
$user = $modx->runSnippet('Registration', array('params' => $params));
}
$user->set('password', $_POST['code']);
$user->save();
$response = $modx->runSnippet('Authorization', array('params' => $params));
if(!$response['success']){
return $AjaxForm->error($response['message'], array());
}
$redirectId= $scriptProperties['redirectTo'] ?: 1; // при вызове сниппета мы передаём id ресурса, на который нужно сделать редирект, если не передаем, то редирект будет на главную.
$redirectUrl = $modx->makeUrl($redirectId , 'web', '', 'full');
return $AjaxForm->success($response['message'], array('redirectTo' => $redirectUrl));
}
}
Из поста данные не валидируются. Пахнет безопасностью! Либо впадлу, либо не знаешь что это такое. Тут кстати гораздо логичнее была бы проверка на false.
Кастомный валидатор validateCode содержит такой код:Опять никакой валидации. Еще и сырой запрос (вызов которого не оправдан ничем)
Регистрацию я сделал так (Registration)Ни единой проверки на то что модель не сохранилась. Неверное сохранение аггеративных моделей.
Итого: куски сомнительного кода не несущие абсолютно никакой ценности.
Я бы ни слова ни сказал, даже плюсик бы залепил если бы тут было хоть какое-то объяснение происходящего.
Почему так, а не иначе, почему это лучше, а это хуже.
Итого ты не учишь, а даешь людям копировать плохие практики.
Абсолютно заслуженный минус
Люди предупреждены. А за ревью спасибо.
Из поста данные не валидируются.Хочешь сказать FormIt их не проверяет?
Валидирует.
У тебя валидация уровня required, я туда могу тебе прислать все что угодно.
У тебя валидация уровня required, я туда могу тебе прислать все что угодно.
Согласен. Надо добавить к коду isNumber.
Раскритиковали…
Напишите и выложите свой подобный кейс, а то желающих поделиться разработкой не много
Напишите и выложите свой подобный кейс, а то желающих поделиться разработкой не много
Без проблем!
100$ и я готов написать решение многократно элегантнее этого с пояснением каждого шага для новичков. Готовы проспонсировать статью?
Дорого?
Можете использовать компонент Office который стоит половину стоимости и реализует задачу гораздо лучше
modstore.pro/packages/users/office
100$ и я готов написать решение многократно элегантнее этого с пояснением каждого шага для новичков. Готовы проспонсировать статью?
Дорого?
Можете использовать компонент Office который стоит половину стоимости и реализует задачу гораздо лучше
modstore.pro/packages/users/office
А в Office есть авторизация по СМС?
Погугли — узнаёшь
Понятно.
Да. Как то давно писал к провайдеру smsc
Итого ты не учишь, а даешь людям копировать плохие практики.1. Не тот у меня уровень, чтобы кого-то учить.
2. Я во вступлении написал, что это не лучший из возможных вариантов.
3. Есть ты и твои комментарии, кто-то проникнется и не станет это копировать, кто-то допилит, а кому-то и так сойдет.
1. Ну так назови цикл статьей «Скопируй сам». Почему «Сделай»?
2. Это не лучший, а прям наихудший способ. Кстати если так хотелось прикрутить авторизацию, то можно было доработать Login.
2. Это не лучший, а прям наихудший способ. Кстати если так хотелось прикрутить авторизацию, то можно было доработать Login.
Это твоё личное мнение, мне нравится моё решение, оно простое, понятное и работает. Да оно далеко от идеала, но это не отменяет всего вышесказанного.
Извиняюсь. Только что столкнулся с modx. Пытаюсь решить задачу авторизации через СМС.
Вполне логичный и читабельный проект, только хотелось поподробнее про пути к файлам.(где их создавать?).
Вполне логичный и читабельный проект, только хотелось поподробнее про пути к файлам.(где их создавать?).
Про какие пути?
Если ошибок нет, значит всё хорошо, если есть внимательно проверяем ПУТИ К ФАЙЛАМ. Про эти.
Я думал из контекста понятно, что речь идёт о пути к файла «компонента» codesender, вот про это [[++core_path]]components/codesender/model/
Как видно, не всем понятно из контекста.)))
При проверке выдает ошибку, о том что не может создать экземпляр класса.
Что я могу сказать, у меня тоже так было нужно проверять пути, название файлов и классов.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.