Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / [php] Фильтрация переменных в классе-обертке для БД / 25 сообщений из 90, страница 1 из 4
11.05.2012, 18:26:28
    #37789934
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
    /**
     * Возвращает подготовленную строку для безопасного использования в запросе.
     * 
     * ? => начало спецификации<br>
     * i => число<br>
     * s => проэскейпленная строка в кавычках<br>
     * t => имя таблицы с преффиксом
     * 
     * <code>
     * echo $db->prepare('SELECT * FROM ?t WHERE age > ?i AND age < ?i AND city = ?s;', 'users', 'foo', '24', 'Moscow');
     * </code>
     * 
     * Выведет:
     * <pre>
     * SELECT * FROM prefix_users WHERE age > 0 AND age < 18 AND city = 'Moscow';
     * </pre>
     *
     * @param type $args
     * @return string 
     */
    public function prepare() {
        $args = func_get_args();
        return $this->_prepare($args);
    }
    
    private function _prepare($args) {        
        $count = count($args);
        $length = strlen($args[0]);     
        $query = '';
        $start = 0;
        $i = 1;
        
        while ($offset = strpos($args[0], '?', $start)) {
            if ($offset == $length - 1) {
                throw new Exception('Unexpected end.');
            }  
                       
            $modifier = $args[0][$offset + 1];
            
            switch ($modifier) {
                case 'i':
                    $value = intval($args[$i]);
                    break;

                case 's':
                    $value = $this->quote($args[$i]);
                    break;

                case 't':
                    $value = $this->getTablename($args[$i]);
                    break;
                
                default:
                    throw new Exception("Unknown modifier '{$modifier}'.");
            }
                      
            $query .= substr($args[0], $start, $offset - $start) . $value;
            $start = $offset + 2;
            ++$i;
        }
        
        $query .= substr($args[0], $start, $length);      
        return $query;
    }
...
Рейтинг: 0 / 0
11.05.2012, 19:02:52
    #37789979
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Код: php
1.
$db->query('SELECT * FROM ?t WHERE name = ?s AND pass = ?s', 'users', 'tester', "\x00"); // SELECT * FROM t_users WHERE name = 'tester' AND pass = '\0'
...
Рейтинг: 0 / 0
11.05.2012, 19:13:11
    #37789994
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
В mysqli и PDO это уже давно сделали
...
Рейтинг: 0 / 0
11.05.2012, 19:15:44
    #37789999
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
А если надо будет сделать запрос
Код: php
1.
'SELECT * FROM user WHERE id IN (' . inplode(',', $ids) . ')'


?
...
Рейтинг: 0 / 0
11.05.2012, 19:18:01
    #37790004
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Hett, нет там неудобно все сделано
...
Рейтинг: 0 / 0
11.05.2012, 19:19:32
    #37790005
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Hett, можно добавить модификатор ?v он будет джойнить по запятой эл-ты
...
Рейтинг: 0 / 0
11.05.2012, 19:27:26
    #37790017
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
HettА если надо будет сделать запрос
Код: php
1.
'SELECT * FROM user WHERE id IN (' . inplode(',', $ids) . ')'


?

Код: php
1.
2.
$ids = array(1, 3, 5, 7, 9);
$db->query('SELECT * FROM ?t WHERE id IN (?v);', 'example', $ids);



Код: sql
1.
SELECT * FROM t_example WHERE id IN (1, 3, 5, 7, 9);



?v в IN и VALUES можно использовать, хотя ему бы придумать более осмысленный модификатор, а то s -> string, i -> integer, t -> table
...
Рейтинг: 0 / 0
11.05.2012, 20:13:52
    #37790062
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Код: php
1.
2.
3.
$set = array('name' => "\x00'\"", 'password' => 'qwerty');
$set = $db->filterArray($set);
$db->query('UPDATE ?t SET ?H WHERE id = ?i;', 'users', $set, '1');



Код: sql
1.
UPDATE t_users SET name = '\0\'\"', password = 'qwerty' WHERE id = 1;



Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
    /**
     * Возвращает подготовленную sql-строку для безопасного использования в запросах.
     * 
     * ? => начальный символ c которого начинается модификатор<br>
     * i => значение будет приведено к типу INT<br>
     * s => строка будет экранирована и заключена в кавычки<br>
     * t => имя таблицы с преффиксом<br>
     * L => элементы списка через запятую<br>
     * H => ассоциативный массив key = value, key1 = value1, ... 
     * 
     * <code>
     * echo $db->prepare('SELECT * FROM ?t WHERE age > ?i AND age < ?i AND city = ?s;', 'users', 'foo', '24', 'Moscow');
     * </code>
     * 
     * Выведет:
     * <pre>
     * SELECT * FROM prefix_users WHERE age > 0 AND age < 24 AND city = 'Moscow';
     * </pre>
     *
     * @param array $args
     * @return string 
     */



Но вот задумалсястоит ли фильтровать автоматически хэши и списки? Вот например массив айдишников которые используются в WHERE IN мы получаем из базы, т.е. фильтровать не имеет смысла, в INSERT да и в UPDATE? Как лучше сделать?
...
Рейтинг: 0 / 0
11.05.2012, 20:19:16
    #37790066
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Модератор: Няша ррр , опять нарушаете. Внимательно читаем правила форума. Особенно вот это место http://www.sql.ru/forum/rules.aspx Не рекомендуется:
Публиковать сообщения с бессмысленными темами. Например: <Люди помогите>, <Проблема!!>, <Срочно нужна помощь!>, <может знаете?> и т.д. Жду сообщения с новым названием темы. В противном случае топик будет удален, а Вам - бан за неоднократные нарушения. Как Вам такая идея?
...
Рейтинг: 0 / 0
11.05.2012, 20:25:02
    #37790076
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
vkle, Автоматическое экранирование переменных при их передаче в функцию с применением модификаторов
...
Рейтинг: 0 / 0
11.05.2012, 20:35:43
    #37790085
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Няша ррр, Вы действительно считаете что можно заэкранировать переменную ? Если это высказывание вообще имеет смысл...
И, да, Ваш вариант не лезет в поле - перебор по количеству знаков. Попытка два.
...
Рейтинг: 0 / 0
11.05.2012, 20:52:11
    #37790107
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
vkleНяша ррр, Вы действительно считаете что можно заэкранировать переменную ? Если это высказывание вообще имеет смысл...
И, да, Ваш вариант не лезет в поле - перебор по количеству знаков. Попытка два.

Фильтрация переменных в классе-обертке для БД
...
Рейтинг: 0 / 0
11.05.2012, 20:54:46
    #37790108
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
    private function _set($data) {
        $data = $this->_filterArray($data);
        
        $sql = '';
        
        foreach ($data as $key => $value) {
            $sql .= $key . ' = ' . $value . ', ';
        }
        
        return substr($sql, 0, -2);
    }
    
    private function _applyModifier($modifier, $value) {
        switch ($modifier) {
            case 'i':
                return intval($value);

            case 's':
                return $this->quote($value);

            case 't':
                return $this->getTablename($value);
 
            case 'v': 
                return implode(', ', $value);

            case 'a':
                return implode(', ', $this->_filterArray($value));

            case 'h':
                return $this->_set($value);

            default:
                throw new Exception("Unknown modifier '{$modifier}'.");
        }
    }
    
    private function _prepare($args) {
        $sql = '';
        $length = strlen($args[0]);
        $start = 0;
        $i = 1;
        
        while ($offset = strpos($args[0], '?', $start)) {
            if ($offset == $length - 1) {
                throw new Exception('Unexpected end.');
            }  
                       
            $value = $this->_applyModifier($args[0][$offset + 1], $args[$i]);
            $sql .= substr($args[0], $start, $offset - $start) . $value;
            $start = $offset + 2;
            ++$i;
        }
        
        $sql .= substr($args[0], $start, $length);      
        return $sql;
    }
    
    /**
     * Возвращает подготовленную sql-строку для безопасного использования в запросах.
     * 
     * ? => начальный символ c которого начинается модификатор<br>
     * i => значение будет приведено к типу INT<br>
     * s => строка будет экранирована и заключена в кавычки<br>
     * t => имя таблицы с преффиксом<br>
     * v => значения через запятую(без фильтрации)<br>
     * a => значения через запятую(данные будут отфильтрованы)<br>
     * h => будет заменен на строку вида вида key = value[, key1 = value1[, ...]](данные будут отфильтрованы)
     * 
     * <code>
     * echo $db->prepare('SELECT * FROM ?t WHERE age > ?i AND age < ?i AND city = ?s;', 'users', 'foo', '24', 'Moscow');
     * </code>
     * 
     * Выведет:
     * <pre>
     * SELECT * FROM prefix_users WHERE age > 0 AND age < 24 AND city = 'Moscow';
     * </pre>
     *
     * @param array $args
     * @return string 
     */
    public function prepare() {
        $args = func_get_args();
        return $this->_prepare($args);
    }
...
Рейтинг: 0 / 0
12.05.2012, 05:57:20
    #37790326
r u
r u
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Няша ррр,

а имя таблицы зачем 'фильтровать'? вы сами себе недоверяете?
а если запрос сразу к нескольким таблицам? их имена будут размазаны по массиву параметров...
запоминать кучу модификаторов со странными именами - сомнительный прогресс.
и главный вопрос.
в чем конкретные преимущества вашего велосипеда перед тем же pdo?
...
Рейтинг: 0 / 0
12.05.2012, 09:31:42
    #37790427
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
автора имя таблицы зачем 'фильтровать'? вы сами себе недоверяете?
скорее это уже не фильтрация, а прикрепление префикса. Лучше это сделать как-то по другому, например неявно.

Код: sql
1.
INSERT INTO {{user}} VALUES(?, ?, ?)



Далее автозаменой

Код: php
1.
preg_replace('#{{(\w+)}}#', $this->prefix . '$1');
...
Рейтинг: 0 / 0
12.05.2012, 10:54:52
    #37790575
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
r u,

> а имя таблицы зачем 'фильтровать'? вы сами себе недоверяете?

преффиксы добавляются

> а если запрос сразу к нескольким таблицам? их имена будут размазаны по массиву параметров...

А можно так сделать 'SELECT * from ^users' => 'SELECT * FROM prefix_users'

> запоминать кучу модификаторов со странными именами - сомнительный прогресс.

Никого не заставляю

> и главный вопрос.
> в чем конкретные преимущества вашего велосипеда перед тем же pdo?

PDO такого не умеет
...
Рейтинг: 0 / 0
12.05.2012, 11:10:49
    #37790611
r u
r u
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Няша рррPDO такого не умеет
префиксы да. остальное умеет даже лучше
...
Рейтинг: 0 / 0
12.05.2012, 11:12:27
    #37790614
Ренат
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Няша рррА можно так сделать 'SELECT * from ^users' => 'SELECT * FROM prefix_users'

ага
Код: php
1.
UPDATE maths SET formula = "2^3=8" WHERE id=1
...
Рейтинг: 0 / 0
12.05.2012, 11:35:05
    #37790653
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
РенатНяша рррА можно так сделать 'SELECT * from ^users' => 'SELECT * FROM prefix_users'

ага
Код: php
1.
UPDATE maths SET formula = "2^3=8" WHERE id=1



Такое только дураку в голову придет, тем более знаки вопроса могут быть тоже в строке, как и любой другой символ. Есть какие предложения?

И вопрос. Можно ли сделать красивее?

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
    private function _replacePlaceholders($matches) {
        if ($matches[0] == '^') {
            return $this->tablesPrefix;
        }
        else {
            $value = next($this->_args);
            
            switch ($matches[1]) {
                case '':
                case 's':
                    return $this->quote($value);
                    
                default:
                    throw new Exception("Unknown placeholder ?{$matches[1]}.");
            }
        }
    }
    
    private function _prepare($args) {
        $sql = '';
        
        if (count($args) > 1) {
            $this->_args = $args; // вроде как хак, не нравится
            $sql = preg_replace_callback('/\^|\?(\w?)/s', array($this, '_replacePlaceholders'), $args[0]);
        }
        else {
            $sql = $args[0];
        }
        
        return $sql;
    }
...
Рейтинг: 0 / 0
12.05.2012, 12:09:12
    #37790743
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Так код менее понятен:

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
   private function _replacePlaceholders($matches) {
        if ($matches[0][0] == '^') {
            return $this->tablesPrefix . $matches[1];
        }
        else {
            $value = next($this->_args);
            
            switch ($matches[1]) {
                case '':
                case 's':
                    return $this->quote($value);
                    
                default:
                    throw new Exception("Unknown placeholder ?{$matches[1]}.");
            }
        }
    }
    
    private function _prepare() {
        if (count($this->_args) > 1) {
            return preg_replace_callback('/\^([a-z]+[_a-z0-9]*)|\?([a-z]*)/is', array($this, '_replacePlaceholders'), $this->_args[0]);
        }
        else {
            return $this->_args[0];
        }
    }
 
   public function prepare() {
        $this->_args = func_get_args();
        return $this->_prepare();
    }



Но зато массивы не передаются по значению, вроде как экономия на спичках.
...
Рейтинг: 0 / 0
12.05.2012, 12:17:25
    #37790773
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Хотя и такая регулярка сойдёт
Код: sql
1.
/\^([a-z]+)|\?([a-z]*)/is



Можно ещё добавить, указание номера аргумента

3?s 1?d 2?d
...
Рейтинг: 0 / 0
12.05.2012, 12:51:43
    #37790850
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Код: sql
1.
2.
3.
4.
SELECT * 
        FROM :pages 
        WHERE 
            alias = 1?



Кстати двоеточие тож можно использовать, с '^' некрасиво
...
Рейтинг: 0 / 0
12.05.2012, 13:04:01
    #37790883
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
аргументы можно сделать именованные. Но тогда получится тоже самое что и в PDO
...
Рейтинг: 0 / 0
12.05.2012, 13:30:33
    #37790955
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
Hett, это не очень удобно, там много лишних телодвижений, подготовить строку, подставить значения, выполнить, как и в mysqli

Код: html
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
lib/classes/DB.php
prepare  Возвращает подготовленную sql-строку для безопасного использования в запросах.  
: -> преффикс таблицы
? -> значение будет:
... s    -> экранировано и заключено в кавычки(если опущен сам флаг, то подразумевается применение 's')
... i, d -> приведено к целому
... a    ->  выведено через запятую(без фильтрации)
... ai   -> выведено через запятую(с фильтрацией)
... as   -> представлено в виде строки key = value[, key1 = value1[, ...]](с фильтрацией)
Пример: Перед '?' можно указывать порядковый номер аргумента.
echo $db->prepare('SELECT * FROM :users WHERE age > ?i AND age < ?i AND city = ?s;', 'foo', '24', 'Moscow');
Output: SELECT * FROM prefix_users WHERE age > 0 AND age < 24 AND city = 'Moscow';
...
Рейтинг: 0 / 0
12.05.2012, 13:40:51
    #37790973
Няша ррр
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[php] Фильтрация переменных в классе-обертке для БД
ai -> Indexed Array
as -> Associative Array

Надо записать
...
Рейтинг: 0 / 0
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / [php] Фильтрация переменных в классе-обертке для БД / 25 сообщений из 90, страница 1 из 4
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]