ФорумПрограммированиеПыхнуть хотите?Готовые решения → Обертка DBAL::Query - переменное число аргументов и экранирование строк

Обертка DBAL::Query - переменное число аргументов и экранирование строк

  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 3:48

    Прошу оценить плоды трудов. Я потратил некоторое время на борьбу с демонами классами и регулярными выражениями. Пусть теперь пользуются все.

    Классов-оберток для доступа к MySQL написано немеряно. Я хочу заострить внимание только на паре аспектов - автоматическом экранировании строк в запросе и методе Myclass::query с произвольным количеством аргументов. Тут же пример как правильно вызывать метод в качестве callback-функции.

    Посмотрим на такой пример из реального движка:

    $result = $db->query('SELECT u.*
    FROM '.$db->prefix.'users AS u
    LEFT JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id
    WHERE u.id>1
    ORDER BY '.$db->escape($order_by).' '.$db->escape($direction));

    Не правда ли за*бывает писать эти $db->prefix и $db->escape !!!

    Мой пример реально не работает с базой, это заглушка для тестирования указанных фич.
    В тексте запроса упоминаются шаблоны подстановки:
    "$p_" — префикс таблиц, задается в конструкторе
    "$#" — аргумент запроса, по номерам с 1 и до бесконечности. автоматически экранируются апострофы прочая гадость. Вам не придется каждый раз делать это перед вызовом query.

    Файл test.php:

    <?php

    class DBLayer
    {
    private $prefix;
    private $subst;

    public function DBLayer($db_host, $db_username, $db_password, $db_name, $db_prefix)
    {
    $this->prefix = $db_prefix;
    }

    // метод, который мы будем использовать как callback
    private function subst_callback($matches)
    {
    if ($matches[1] == '$p_')
    return $this->prefix;
    else
    return $this->subst[intval(substr($matches[1], 1))];
    }

    // метод с произвольным числом аргументов
    // первый считаем текстом запроса, все остальные - параметры для подстановки
    // вида $1, $2 и т.д.
    public function query()
    {

           $sql = func_get_arg(0);
    $this->subst = array();

           if (func_num_args() > 1)
           {
            for ($i=1; $i<func_num_args(); $i++)
            $this->subst[$i] = mysql_escape_string(func_get_arg($i));
    }

    $sql = preg_replace_callback('#(\$p_|\$\d+)#', array(&$this, 'subst_callback'), $sql);

    echo $sql."<br />\n";
    }

    }

    /* —————— */

    $db = new DBLayer('localhost', 'superuser', '123456', 'mydb', 'my_');

    $db->query('SELECT * FROM $p_table1');
    $db->query('SELECT * FROM $p_table2 WHERE id=$1', 205);
    $db->query('SELECT \'$2\' AS myname, x.parent_id FROM $p_table3 AS x WHERE x.id=$1 AND x.kind=\'$2\'',
    777, 'd\'Artagnan');


    Должен выдавать такой результат:

    SELECT * FROM my_table1
    SELECT * FROM my_table2 WHERE id=205
    SELECT 'd\'Artagnan' AS myname, x.parent_id FROM my_table3 AS x WHERE x.id=777 AND x.kind='d\'Artagnan'
    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 3:59, спустя 10 минут 15 секунд

    почти совершенство ))но у меня другого вида запросы поддерживаются

    $user = $db->scalar("SELECT `userdata` FROM #__users WHERE `id`='{0}'",$_SESSION['user']['id']);
    $old = $db->scalar("SELECT id FROM #__users WHERE `id`='{0}' AND `password`='{1}'",$_SESSION['user']['id'],md5($_POST['password']['old']));
    $items = $db->sql2arr("SELECT #__basket.*, #__shop_items.`id` FROM #__basket
    LEFT JOIN #__shop_items ON #__shop_items.id=#__basket.itemid
    WHERE #__basket.userid={0} AND #__basket.itemid IN ({1}) ORDER BY `time` DESC",
    $_SESSION['user']['id'],$items);
    вот примеры запросов.

    #__ = префикс
    {0} - подставляемый аргумент :)
    Сапожник без сапог
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 4:01, спустя 2 минуты 32 секунды

    тот же х, но вид сбоку :))) какие мы молодцы!
    ιιlllιlllι унц-унц
  • Trej Gun

    Сообщения: 5302 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 4:03, спустя 2 минуты 23 секунды

    это слив :(

    аргументы:
    1 функционал на уровне нуля
    2 удобность - сомнительная
    3 реализовано во всех DBAL несмотря на высосаный из пальца пример с $db->escape($order_by)
    4 order_by как раз плохой пример для отслешивания!
    5 микроскопом гвозди забиваем preg_replace_callback('#(\$p_|\$\d+)#', array(&$this, 'subst_callback'), $sql);
    6 я так и не понял это класс дял работы с бд или sql builder?
    7 тока заметил этот пиздец global $subst; это что ооп?!

    ЗЫ возможно следующая попытка будет лучше
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 4:05, спустя 1 минуту 16 секунд


    тот же х, но вид сбоку :))) какие мы молодцы!
    соглашусь что решения сильно похожи)) по сути это метод prepared statements. только чуток удобнее писать. зато 100% гарантия непробиваемости на скл инъекции :)
    Сапожник без сапог
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 4:11, спустя 6 минут 15 секунд

    CTAPbIu_MABP, твои аргументы мне кажутся надуманными.
    то что якобы "высосано из пальца" взято из популярного форумного движка, только сократил немного. order by там так и стоит.
    global убрал, сорри - это был мусор.
    чем предлагаешь заменить preg_replace_callback ? пример пожалуйста!

    меня и эта попытка приводит в экстаз - возьму другую тему в следующий раз
    ιιlllιlllι унц-унц
  • Timur

    Сообщения: 1068 Репутация: N Группа: Джедаи

    Spritz 15 декабря 2008 г. 5:09, спустя 57 минут 46 секунд

    Замечание: Метод объявления переменной через ключевое слово var, принятый в PHP 4, до сих пор поддерживается в целях совместимости (как синоним ключевого слова public). В версиях PHP 5 ниже 5.1.3 такое использование выводит предупреждение E_STRICT.

    да, придираюсь к пустякам )
  • adw0rd

    Сообщения: 22943 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 5:30, спустя 21 минуту 45 секунд

    artoodetoo, phpdude, http://pyha.ru/forum/topic/554.0
    а именно http://pyha.ru/go/godb/intro/
    https://smappi.org/ - платформа по созданию API на все случаи жизни
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 5:41, спустя 10 минут 58 секунд

    adw0rd, не, спасибо. люблю свои библиотечки)
    Сапожник без сапог
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 5:50, спустя 8 минут 29 секунд

    adw0rd, спасибо. вещь серьезная, но со своей идеалогией.
    ιιlllιlllι унц-унц
  • sap

    Сообщения: 2701 Репутация: N Группа: Кто попало

    Spritz 15 декабря 2008 г. 6:06, спустя 16 минут 22 секунды


    Замечание: Метод объявления переменной через ключевое слово var, принятый в PHP 4, до сих пор поддерживается в целях совместимости (как синоним ключевого слова public). В версиях PHP 5 ниже 5.1.3 такое использование выводит предупреждение E_STRICT.

    да, придираюсь к пустякам )

    +1, еще и у функций не указан public, там где нужно, это что, ООП?! (с)
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 7:20, спустя 1 час 13 минут 19 секунд

    > В версиях PHP 5 ниже 5.1.3 такое использование выводит предупреждение E_STRICT
    я тоже поумничаю: нам не рекомендуют PHP ниже 5.2, так что забей

    > еще и у функций не указан public, там где нужно
    а разве методы в PHP не являются public по-умолчанию?

    > это что, ООП?!
    вписывать public там где нет необходимости — это Онанизм с Особым Пристрастием

    я все ждал кто докопается до такой неизящной конструкции с тиле C:

    for ($i=1; $i<func_num_args(); $i++)
    $this->subst[$i] = mysql_escape_string(func_get_arg($i));

    все пропустили, а можно "пыхнуть" так:

    $this->subst = array_slice(func_get_args(), 1, 100, true);
    $this->subst = array_map('mysql_escape_string', $this->subst);

    ιιlllιlllι унц-унц
  • adw0rd

    Сообщения: 22943 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 7:34, спустя 14 минут 1 секунду


    > еще и у функций не указан public, там где нужно
    а разве методы в PHP не являются public по-умолчанию?


    да, так и есть, однако лучше указывать для общей наглядности и однозначности, так как, например, в других языках по умолчанию указан private…
    я всегда указываю.
    https://smappi.org/ - платформа по созданию API на все случаи жизни
  • sap

    Сообщения: 2701 Репутация: N Группа: Кто попало

    Spritz 15 декабря 2008 г. 7:53, спустя 18 минут 59 секунд

    > еще и у функций не указан public, там где нужно
    а разве методы в PHP не являются public по-умолчанию?

    Вот я еще должен помнить, что где по умолчанию. А если в следующей версии разработчики наконец проснутся и сделают по умолчанию прайвет? Все посыпется.
    Кроме того, есть такое понятие, как читабельный код. За код с претензией на ООП, где не указаны модификаторы доступа, я бы долго и больно бил по рукам, а потом уволил.

    > это что, ООП?!
    вписывать public там где нет необходимости — это Онанизм с Особым Пристрастием

    Не указывать public там, где это положено — это кодинг (именно кодинг, а не программирование) на отьебись.
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 15 декабря 2008 г. 8:00, спустя 7 минут 15 секунд


    > еще и у функций не указан public, там где нужно
    а разве методы в PHP не являются public по-умолчанию?

    Вот я еще должен помнить, что где по умолчанию. А если в следующей версии разработчики наконец проснутся и сделают по умолчанию прайвет? Все посыпется.
    Кроме того, есть такое понятие, как читабельный код. За код с претензией на ООП, где не указаны модификаторы доступа, я бы долго и больно бил по рукам, а потом уволил.

    > это что, ООП?!
    вписывать public там где нет необходимости — это Онанизм с Особым Пристрастием

    Не указывать public там, где это положено — это кодинг (именно кодинг, а не программирование) на отьебись.
    а если вдруг придется в срочном порядке под пхп4 переписать?))) я сталкивался с такими проблемами, потом пришлось по всему проекты вычищать public,private,protected'ы. так что я в этой ситуации даже и не знаю за кого, ибо пхп пишут хорошие люди, но их вечно разрывает от идей. то надо то ненадо, то надо то ненадо … вечно так. придерживаюсь политики лучше не использовать и юзать умолчание, чтобы не наткнуться.
    Сапожник без сапог

Пожалуйста, авторизуйтесь, чтобы написать комментарий!