powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / [php] Фильтрация переменных в классе-обертке для БД
25 сообщений из 90, страница 1 из 4
[php] Фильтрация переменных в классе-обертке для БД
    #37789934
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: 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
[php] Фильтрация переменных в классе-обертке для БД
    #37789979
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: 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
[php] Фильтрация переменных в классе-обертке для БД
    #37789994
Фотография Hett
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В mysqli и PDO это уже давно сделали
...
Рейтинг: 0 / 0
[php] Фильтрация переменных в классе-обертке для БД
    #37789999
Фотография Hett
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А если надо будет сделать запрос
Код: php
1.
'SELECT * FROM user WHERE id IN (' . inplode(',', $ids) . ')'


?
...
Рейтинг: 0 / 0
[php] Фильтрация переменных в классе-обертке для БД
    #37790004
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Hett, нет там неудобно все сделано
...
Рейтинг: 0 / 0
[php] Фильтрация переменных в классе-обертке для БД
    #37790005
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Hett, можно добавить модификатор ?v он будет джойнить по запятой эл-ты
...
Рейтинг: 0 / 0
[php] Фильтрация переменных в классе-обертке для БД
    #37790017
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
[php] Фильтрация переменных в классе-обертке для БД
    #37790062
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: 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
[php] Фильтрация переменных в классе-обертке для БД
    #37790066
vkle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Модератор: Няша ррр , опять нарушаете. Внимательно читаем правила форума. Особенно вот это место http://www.sql.ru/forum/rules.aspx Не рекомендуется:
Публиковать сообщения с бессмысленными темами. Например: <Люди помогите>, <Проблема!!>, <Срочно нужна помощь!>, <может знаете?> и т.д. Жду сообщения с новым названием темы. В противном случае топик будет удален, а Вам - бан за неоднократные нарушения. Как Вам такая идея?
...
Рейтинг: 0 / 0
[php] Фильтрация переменных в классе-обертке для БД
    #37790076
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
vkle, Автоматическое экранирование переменных при их передаче в функцию с применением модификаторов
...
Рейтинг: 0 / 0
[php] Фильтрация переменных в классе-обертке для БД
    #37790085
vkle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Няша ррр, Вы действительно считаете что можно заэкранировать переменную ? Если это высказывание вообще имеет смысл...
И, да, Ваш вариант не лезет в поле - перебор по количеству знаков. Попытка два.
...
Рейтинг: 0 / 0
[php] Фильтрация переменных в классе-обертке для БД
    #37790107
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
vkleНяша ррр, Вы действительно считаете что можно заэкранировать переменную ? Если это высказывание вообще имеет смысл...
И, да, Ваш вариант не лезет в поле - перебор по количеству знаков. Попытка два.

Фильтрация переменных в классе-обертке для БД
...
Рейтинг: 0 / 0
[php] Фильтрация переменных в классе-обертке для БД
    #37790108
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: 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
[php] Фильтрация переменных в классе-обертке для БД
    #37790326
Фотография r u
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Няша ррр,

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

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



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

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

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

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

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

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

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

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

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

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

ага
Код: php
1.
UPDATE maths SET formula = "2^3=8" WHERE id=1
...
Рейтинг: 0 / 0
[php] Фильтрация переменных в классе-обертке для БД
    #37790653
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
РенатНяша рррА можно так сделать '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
[php] Фильтрация переменных в классе-обертке для БД
    #37790743
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Так код менее понятен:

Код: 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
[php] Фильтрация переменных в классе-обертке для БД
    #37790773
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хотя и такая регулярка сойдёт
Код: sql
1.
/\^([a-z]+)|\?([a-z]*)/is



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

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



Кстати двоеточие тож можно использовать, с '^' некрасиво
...
Рейтинг: 0 / 0
[php] Фильтрация переменных в классе-обертке для БД
    #37790883
Фотография Hett
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
аргументы можно сделать именованные. Но тогда получится тоже самое что и в PDO
...
Рейтинг: 0 / 0
[php] Фильтрация переменных в классе-обертке для БД
    #37790955
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
[php] Фильтрация переменных в классе-обертке для БД
    #37790973
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ai -> Indexed Array
as -> Associative Array

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


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