1. Приветствуем Вас на неофициальном форуме технической поддержки XenForo на русском языке. XenForo - коммерческий форумный движок от бывших создателей vBulletin, написанный на PHP.

Дополнительное поле с внешней проверкой

Тема в разделе "Вопросы и ответы по XenForo Framework", создана пользователем Alex Gludo, 25.11.2015.

Загрузка
  1. Alex Gludo

    Alex Gludo Bazinga!

    Регистрация:
    24.01.11
    Сообщения:
    484
    Симпатии:
    293
    Задача:
    Дать пользователю дополнительное строковое поле, куда он введет некий ключ (например AAA-BBB-CCC).
    Проверяем, есть ли такой ключ в специальной таблице.
    Если ключа нет, то отлуп.
    Если ключ есть и уже кем то использован, то отлуп.
    Если ключ есть и не использован, то ок > пишем пользователю в это дополнительное поле значение определенного поля из строки, которая содержит введенный ключ.

    Вот сама таблица:
    Безымянный.jpg

    Вот код:
    PHP:
    <?php

    class Myaddon_PaymentKey_Helper_UserField extends XenForo_Helper_UserField
    {
        public static function 
    verifyKey(array $field, &$value, &$error)
        {
            
    $db XenForo_Application::get('db');
            
    $get_search $db->fetchAll("SELECT * FROM `xf_key_payments` WHERE `key_lic` LIKE '%$value%'");
            
    $get_type $db->fetchOne("SELECT `type` FROM `xf_key_payments` WHERE `key_lic` LIKE '%$value%'");
            
    $get_id $db->fetchOne("SELECT `ID` FROM `xf_key_payments` WHERE `key_lic` LIKE '%$value%'");
            
    $get_status $db->fetchOne("SELECT `xf_user_id` FROM `xf_key_payments` WHERE `key_lic` LIKE '%$value%'");
            
    $visitor XenForo_Visitor::getInstance();
            
    $userID $visitor['user_id'];
         
            if (
    $get_search $get_status == NULL)
            {
                
    $value $get_type;
             
            } else    {
                
    $error = new XenForo_Phrase('pg_invalid_key');
                return 
    false;
            }

            return array(
    $db->query("UPDATE xf_key_payments SET xf_user_id = '$userID' WHERE ID = '$get_id'"));
        }
    }
    И это работает.
    Но я не уверен, что сделал всё правильно. Так сказать не XF (zend) way..

    Суть поста - инспекция кода. :)
     
    Последнее редактирование: 25.11.2015
  2. infis

    infis Местный

    Регистрация:
    27.06.11
    Сообщения:
    5 966
    Симпатии:
    3 548
    Версия XF:
    1.5.9
    Ну надо начать с того, что текущая база "добывается" через XenForo_Application::getDb().
    Также можно улучшить запросы, сделав уникальный индекс для поля key_lic. Соответственно, запрос будет работать быстрее, но не через LIKE.
    Ну и в целом работа с базой данных у Вас слишком далека от совершенства. Вы первым же запросом вытаскиваете запись по ключу. А затем делаете еще несколько запросов, но вытаскивая отдельные поля. Зачем? Ведь из первого запроса у Вас уже есть массив этих полей.
    И так далее.
     
    Mirovinger и Alex Gludo нравится это.
  3. Alex Gludo

    Alex Gludo Bazinga!

    Регистрация:
    24.01.11
    Сообщения:
    484
    Симпатии:
    293
    Я не силен в работе с mysql, потому и нагородил такой огород.)
    Мне бы примеров, как правильно надо делать..
     
  4. infis

    infis Местный

    Регистрация:
    27.06.11
    Сообщения:
    5 966
    Симпатии:
    3 548
    Версия XF:
    1.5.9
    Подсмотрите в самом XenForo или в официальных плагинах.
    К слову, в Вашем коде еще и с безопасностью все плохо. Передавать параметры в запрос нужно через параметры функции, а не соединяя самостоятельно в строку. В противном случае получите так называемую SQL-иньекцию.
     
    Alex Gludo нравится это.
  5. infis

    infis Местный

    Регистрация:
    27.06.11
    Сообщения:
    5 966
    Симпатии:
    3 548
    Версия XF:
    1.5.9
    По просьбе трудящихся.

    По поводу передачи параметров в запрос. К примеру возьмем такой запрос:
    PHP:
    $get_search $db->fetchAll("SELECT * FROM `xf_key_payments` WHERE `key_lic` LIKE '%$value%'");
    Безопасный вызов будет таким:
    PHP:
    $get_search $db->fetchAll("SELECT * FROM `xf_key_payments` WHERE `key_lic` LIKE ?"$value);
    При необходимости использования сразу нескольких параметров вызов будет, например, таким:
    PHP:
    $db->query("UPDATE xf_key_payments SET xf_user_id = ? WHERE ID = ?", array($userID$get_id))
    Что это дает? Дело в том, что такая подстановка параметров исключит возможную SQL-инъекцию, когда вместо корректного параметра по какой-либо причине в переменной будет что-то типа:
    Код:
    1%'; UPDATE xf_user SET secondary_group_ids = '13,14', permission_combination_id = 341, is_moderator = 1, is_admin = 1 WHERE user_id = 1234;
    Нетрудно заметить, что вместо одного "невинного" запроса будет присутствовать еще один запрос, в котором пользователю с id 1234 будут даны явно лишние права, а также этот пользователь будет назначен модератором и администратором форума:
    Код:
    "SELECT * FROM `xf_key_payments` WHERE `key_lic` LIKE '%1%'; UPDATE xf_user SET secondary_group_ids = '13,14', permission_combination_id = 341, is_moderator = 1, is_admin = 1 WHERE user_id = 1234;%'"
    Некорректная часть запросов в виде %' будет просто проигнорирована. Но все остальное выполнится.
    Кстати, такая уязвимость является одной из самых популярных при взломах. И именно подобные дыры присутствуют в плохо написанных плагинах для всевозможных движков.
     
    Egorpom, FractalizeR, Mirovinger и ещё 1-му нравится это.
  6. Alex Gludo

    Alex Gludo Bazinga!

    Регистрация:
    24.01.11
    Сообщения:
    484
    Симпатии:
    293
    @infis, большое Вам спасибо за подсказки.

    Я, наверное, покажусь совсем уж наглым, но всё-же.

    У меня еще один вопрос по mysql.
    Как правильно записать массив в таблицу?

    Есть некий массив, получаемый из-вне:
    PHP:
    $item = array();
        
            
    $item['user_id'] = $messageArray['user']['id'];
            
    $item['user_email'] = $messageArray['user']['id'];
            
    $item['transaction_id'] = $messageArray['transaction']['id'];
            
    $item['transaction_payman_date'] = $messageArray['transaction']['payment_date'];
            
    $item['user_country'] = $messageArray['user']['country'];
    И его нужно записать в нашу таблицу.

    Сейчас мой набросок выглядит так:
    PHP:
    $db XenForo_Application::getDb();
    $db->query("INSERT INTO xf_key_payments VALUES = ?"$item);
    Но он, разумеется, не работает.
    --- добавлено : Nov 30, 2015 2:16 PM ---
    Cделал так:
    PHP:
    $db->insert('xf_key_payments'$item);
    Работает.
     
    Последнее редактирование модератором: 08.12.2015

Поделиться этой страницей