За последние 24 часа нас посетили 19203 программиста и 1670 роботов. Сейчас ищут 657 программистов ...

Написал класс роботы с MySQL проверте

Тема в разделе "Решения, алгоритмы", создана пользователем oligarx, 13 апр 2007.

Статус темы:
Закрыта.
  1. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Здравствуйте любители и профессионалы PHP. Вот решил на днях написать класс роботы с базой данных MySQL . Я не профессионал и хочу, чтобы вы посмотрели на него своим профессиональным взглядом, дали свою рецензию и может, посоветовали, как его улучшить. Очень интересует вопрос безопасности, не люблю когда кто-то портит мне настроение. Буду рад выслушать ваше мнение. Скажу сразу, что он написан не полностью мной, проверка данных перед вводом была скромно мною украдена :wink:
    PHP:
    1. <?php
    2. /**
    3.  * Ксасс для роботы с базой данных
    4.  */
    5. class Database {
    6.  
    7.   private $pconn;
    8.   private $host;
    9.   private $port;
    10.   private $user;
    11.   private $pass;
    12.   private $base;
    13.   private $char;
    14.   private $debug;
    15.   private $loging;
    16.   private $antihack;
    17.  
    18.   private $conn_id;
    19.   private $query_id;
    20.   private $counter = '0';
    21.   private $work_time;
    22.  
    23.   private $error;
    24.   private $error_exp;
    25.  
    26.   function Connect(){
    27.    
    28.         if($this->pconn){
    29.             $this->conn_id = @mysql_pconnect($this->host, $this->user, $this->pass);
    30.         } else {
    31.             $this->conn_id = @mysql_connect($this->host, $this->user, $this->pass);
    32.         }
    33.        
    34.         if($this->conn_id){
    35.             $dbselect = @mysql_select_db($this->base);
    36.             if(!$dbselect){
    37.                 @mysql_close($this->conn_id);
    38.                 $this->error = 'Невозможно выбрать базу данных';
    39.                 return false;
    40.             }
    41.         } else {
    42.           $this->error = 'Невозможно подключится к серверу базы данных';
    43.           return false;
    44.         }
    45.             return $this->conn_id;
    46.     }
    47.  
    48.     function Disconnect(){
    49.         if($this->conn_id){
    50.             if($this->query_id){
    51.                 @mysql_free_result($this->query_id);
    52.             }
    53.             $result = @mysql_close($this->conn_id);
    54.             return $result;
    55.         } else {
    56.             return false;
    57.         }
    58.     }
    59.  
    60.     function Query($query,$file,$line){
    61.      
    62.     if ($this->antihack) {
    63.         $clean = '';
    64.         $old_pos = '0';
    65.         $pos = '-1';
    66.         while (true) {
    67.             $pos = strpos($query, '\'', $pos++);
    68.             if ($pos === false) break;
    69.             $clean .= substr($query, $old_pos, $pos - $old_pos);
    70.             while (true) {
    71.                 $pos1 = strpos($query, '\'', $pos++);
    72.                 $pos2 = strpos($query, '\\', $pos++);
    73.                 if ($pos1 === false) break;
    74.                 elseif ($pos2 == false || $pos2 > $pos1) {
    75.                     $pos = $pos1;
    76.                     break;
    77.                 }
    78.                 $pos = $pos2++;
    79.             }
    80.             $clean .= '%s';
    81.             $old_pos = $pos++;
    82.         }
    83.         $clean .= substr($query, $old_pos);
    84.         $clean = trim(strtolower(preg_replace(array('~\s+~s', '~/\*!40001 SQL_NO_CACHE \*/~', '~/\*!40000 USE INDEX \([A-Za-z\_]+?\) \*/~'), array(' ', '', ''), $clean)));
    85.  
    86.         // Мы не используем UNION.  Зато они удобны для инекций.
    87.         if (strpos($clean, 'union') !== false && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0) $this->error = true;
    88.         // Комментарии?  Мы не используем комментарии в запросах!
    89.         elseif (strpos($clean, '/*') > 2 || strpos($clean, '--') !== false || strpos($clean, ';') !== false) $this->error = true;
    90.         // Попытка подмены паролей, замедления сервера или чего-то еще?
    91.         elseif (strpos($clean, 'set password') !== false && preg_match('~(^|[^a-z])set password($|[^[a-z])~s', $clean) != 0) $this->error = true;
    92.         elseif (strpos($clean, 'benchmark') !== false && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s', $clean) != 0) $this->error = true;
    93.         // Под выборы? Мы их не используем.
    94.         elseif (preg_match('~\([^)]*?select~s', $clean) != '0') $this->error = true;
    95.  
    96.         if (!empty($this->error)){
    97.           $this->Log($query,$file,$line);
    98.           die('Что хакер да?');
    99.         }
    100.     }
    101.    
    102.     if ($this->debug) {
    103.       $StartTimer = microtime(1);
    104.     }
    105.    
    106.     $this->query_id = mysql_query($query, $conn_id);
    107.     if (!$this->query_id){
    108.       $this->Log($query,$file,$line);
    109.       die('Ошибка выполнения запроса');
    110.     }
    111.    
    112.     if ($this->debug) {
    113.       $this->work_time = microtime(1) - $StartTimer;
    114.     }
    115.    
    116.     $this->counter++;
    117.    
    118.     return $this->query_id;
    119.     }
    120.    
    121.   function Fetch_Row($query_id = "") {
    122.     if ($query_id == "")
    123.     {
    124.         $query_id = $this->query_id;
    125.     }
    126.     return  mysql_fetch_array($query_id, MYSQL_ASSOC);
    127.   }
    128.    
    129.   function Get_Counter() {
    130.     return $this->counter;
    131.   }
    132.    
    133.   function Get_Result_Fields($query_id = "") {
    134.     if ($query_id == ""){
    135.       $query_id = $this->query_id;
    136.     }
    137.     while ($field = mysql_fetch_field($query_id)){
    138.       $Fields[] = $field;
    139.     }
    140.     return $Fields;
    141.     }
    142.    
    143.   function Free_Result($query_id = "") {
    144.         if ($query_id == "") {
    145.         $query_id = $this->query_id;
    146.     }
    147.     @mysql_free_result($query_id);
    148.   }    
    149.  
    150.     function Log($query,$file,$line){
    151.       if($this->loging){
    152.       if ($this->work_time > 0.1){
    153.       $time = "<span style='color:red'><b>$this->work_time</b></span>";
    154.       }  
    155.      
    156.       if (preg_match("/^select/i", $query)){
    157.         $explain = mysql_query("EXPLAIN $query", $this->conn_id);
    158.        
    159.         if ($explain !== true){
    160.           $this->error_exp .= "<table width='95%' border='1' cellpadding='6' cellspacing='0' bgcolor='#FEFEFE'  align='center'>";
    161.           $this->error_exp .= "<tr>";
    162.           $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'><b>Недопустимый запрос</b></td>";
    163.           $this->error_exp .= "</tr>";
    164.           $this->error_exp .= "<tr>";
    165.           $this->error_exp .= "<td style='font-family:courier, monaco, arial;font-size:14px'>".$query."</td>";
    166.           $this->error_exp .= "</tr>";
    167.           $this->error_exp .= "<tr>";
    168.           $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'>";
    169.           $this->error_exp .= "<b>Дата</b>: ".date("y.m.d H:i:s")."<br />";
    170.           $this->error_exp .= "<b>Файл</b>: ".$file."<br />";
    171.           $this->error_exp .= "<b>Строка</b>: ".$line."<br>";
    172.           $this->error_exp .= "</tr>";
    173.           $this->error_exp .= "</table><br />\n\n";
    174.  
    175.         } else {
    176.           $array = mysql_fetch_array($explain);
    177.           $type_col = '#FFFFFF';
    178.           if ($array['type'] == 'ref' or $array['type'] == 'eq_ref' or $array['type'] == 'const'){
    179.             $type_col = '#D8FFD4';
    180.           } else if ($array['type'] == 'ALL'){
    181.             $type_col = '#FFEEBA';
    182.           }
    183.           $this->error_exp .= "<table width='95%' border='1' cellpadding='6' cellspacing='0' bgcolor='#FFE8F3' align='center'>\n";
    184.           $this->error_exp .= "<tr>\n";
    185.           $this->error_exp .= "<td colspan='8' style='font-size:14px' bgcolor='#FFC5Cb'><b>Select Запрос</b></td>\n";
    186.           $this->error_exp .= "</tr>\n";
    187.           $this->error_exp .= "<tr>\n";
    188.           $this->error_exp .= "<td colspan='8' style='font-family:courier, monaco, arial;font-size:14px;color:black'>\n".$query."</td>";
    189.           $this->error_exp .= "</tr>\n";
    190.           $this->error_exp .= "<tr bgcolor='#FFC5Cb'>\n";
    191.           $this->error_exp .= "<td><b>table</b></td><td><b>type</b></td><td><b>possible_keys</b></td>\n";
    192.           $this->error_exp .= "<td><b>key</b></td><td><b>key_len</b></td><td><b>ref</b></td>\n";
    193.           $this->error_exp .= "<td><b>rows</b></td><td><b>Extra</b></td>\n";
    194.           $this->error_exp .= "</tr>\n";
    195.           $this->error_exp .= "<tr bgcolor='#FFFFFF'>\n";
    196.           $this->error_exp .= "<td>".$array[table]."&nbsp;</td>\n";
    197.           $this->error_exp .= "<td bgcolor='".$type_col."'>".$array[type]."&nbsp;</td>\n";
    198.           $this->error_exp .= "<td>".$array[possible_keys]."&nbsp;</td>\n";
    199.           $this->error_exp .= "<td>".$array[key]."&nbsp;</td>\n";
    200.           $this->error_exp .= "<td>".$array[key_len]."&nbsp;</td>\n";
    201.           $this->error_exp .= "<td>".$array[ref]."&nbsp;</td>\n";
    202.           $this->error_exp .= "<td>".$array[rows]."&nbsp;</td>\n";
    203.           $this->error_exp .= "<td>".$array[Extra]."&nbsp;</td>\n";
    204.           $this->error_exp .= "</tr>\n";
    205.           $this->error_exp .= "<tr>\n";
    206.           $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'>";
    207.           $this->error_exp .= "<b>Дата</b>: ".date("y.m.d H:i:s")."<br />";
    208.           $this->error_exp .= "<b>Файл</b>: ".$file."<br />";
    209.           $this->error_exp .= "<b>Строка</b>: ".$line."<br>";
    210.           $this->error_exp .= "<b>Время выполнения</b>: ".$time;
    211.           $this->error_exp .= "</tr>";
    212.           $this->error_exp .= "</table><br />\n\n";
    213.         }
    214.       } else {
    215.         $this->error_exp .= "<table width='95%' border='1' cellpadding='6' cellspacing='0' bgcolor='#FEFEFE'  align='center'>";
    216.         $this->error_exp .= "<tr>";
    217.         $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'><b>Не Select Запрс</b></td>";
    218.         $this->error_exp .= "</tr>";
    219.         $this->error_exp .= "<tr>";
    220.         $this->error_exp .= "<td style='font-family:courier, monaco, arial;font-size:14px'>".$query."</td>";
    221.         $this->error_exp .= "</tr>";
    222.         $this->error_exp .= "<tr>";
    223.         $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'>";
    224.         $this->error_exp .= "<b>Дата</b>: ".date("y.m.d H:i:s")."<br />";
    225.         $this->error_exp .= "<b>Файл</b>: ".$file."<br />";
    226.         $this->error_exp .= "<b>Строка</b>: ".$line."<br>";
    227.         $this->error_exp .= "<b>Время выполнения</b>: ".$time;
    228.         $this->error_exp .= "</tr>";
    229.         $this->error_exp .= "</table><br />\n\n";
    230.       }
    231.       return $this->error_exp; //Временно!
    232.       }
    233.     }
    234.    
    235.   function Config($array){
    236.     if(empty($array)){
    237.       $this->error = 'Конфигурация БД не задана';
    238.       return false;
    239.     }
    240.    
    241.     $class_vars = get_object_vars($this);
    242.     foreach ($class_vars as $key => $val){
    243.       if (array_key_exists($key, $array)) {
    244.         $this->$key = $array[$key];
    245.       }
    246.     }
    247.    
    248.     return true;
    249.   }
    250. }
    251. ?>
    Что будет из меня толк? :)
     
  2. Anonymous

    Anonymous Guest

    Понравилось. Хорошая идея. Расширяемая.
    абсолютно напрасно. Ибо г*вно. Не надо ничего проверять. Надо просто исключить возможность SQL-инъекции.
    Укради лучше отсюда — http://www.dklab.ru/lib/DbSimple/manual.html#cont7
     
  3. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Спасибо за оценку и за ссылку
     
  4. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Однако я заранее не знаю какие запросы буду передавать базе? а хочу реализовать проверку именно в этом классе чтобы потом даже не думать про это.
     
  5. Anonymous

    Anonymous Guest

    oligarx вот именно. Плейсхолдеры для этого и нужны. Но не странным отметанием UNION, которым я пользуюсь, а именно ЭКРАНИРОВАНИЕМ ВХОДЯЩИХ ДАННЫХ.
     
  6. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Ну, если кому приглянется класс, то используйте на здоровье! Думаю мою роботу ссылочкой не обидите. Если кто-то его будет усовершенствовать или дополнять сообщите, мне очень интересно.
     
  7. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Тогда получается мне надо проститать все возможные запросы к моей БД и для каждого создать метод? Другого рационального пути я не вижу т.к. я хочу, чтобы вся безопасность обрабатывалась именно в классе БД (мне кажется, это избавит от многих щелей в программе, а для меня это важно).
     
  8. Anonymous

    Anonymous Guest

    oligarx, ты прочитал ссылку?
    там вообще ничего просчитывать не надо. Там надо экранировать входящие данные. И все. Никаких SQL-иньекций.
     
  9. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Прочитал, понял – был не прав! Только правда надо следить за тем чтобы все запросы использовали именно placeholder’ы, а то напишет кто-то код без них и все минус зашита, точнее появится щель.
     
  10. Anonymous

    Anonymous Guest

    ну, это ж его проблемы. У него ж появится.
     
  11. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Нужно написать парсер но я не очень понимаю как работают регулярные выражения.
    Вот что надо заменить из строчки запроса ‘?’ на первый элемент массива $array.
    Что я уже сделал:
    PHP:
    1.   <?php
    2.     $i = '0';
    3.     foreach ($array as $key => $data){
    4.       $query = preg_replace('?', $array[$i], $query, '1');
    5.       $i++;
    6.     }
    7.   ?>
    Подскажите, а то у меня как раз мысль пошла.

    У нас нововведение? Что-то я раньше капатчи тут не видел.

    Проблема в другом сервер работать будет у меня, а програмеров несколько.
    Придется за всеми следить и проверять что они пишут.
     
  12. Hight

    Hight Старожил
    Команда форума Модератор

    С нами с:
    5 мар 2006
    Сообщения:
    7.153
    Симпатии:
    0
    Адрес:
    из злой параллельной вселенной
    оно самое.
     
  13. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Сделали бы, так что если человек оставил больше чем N сообщений она пропадает.
     
  14. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    надоели боты
     
  15. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    oligarx
    Регулярками бесполезно, я пробовал... только простейшие конструкции, сложные запросы они не в силах обработать, точнее я просто не смог такие сделать. Тут надо разбирать посимвольно код запросов и делать автомат, который занимаеться разбором и анализом. Короче, полноценный парсер SQL запросов.
     
  16. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Ну вот приблизительно то что говорил Горбунов Олег в моем классе.
    Можно еще много чего добавить. Но это уже по необходимости.
    Какие в методе классы, думаю понятно и без дополнительного описания.

    А вот составляем запрос мы вот так:
    $DB->Query($mask, $array_var, __FILE__, __LINE__);

    Пример:
    PHP:
    1. <?php
    2. // include mysql.php
    3. $DB = new Database;
    4. $DB-> Config($array);
    5. $DB-> Connect();
    6. $DB-> Query(“SELECT *  FROM `banner` WHERE `id` = ?”,2,__FILE__,__LINE__);
    7. ?>
    То есть сначала мы задаем маску $mask, по которой будет выполнен запрос:
    “SELECT * FROM `jos_banner` WHERE `bid` = ?”
    Как видно на этом примере в маске присутствует знак вопроса “?”.
    Вот он и задает маску. Вместо «?» автоматически будет подставлена значение массива $array_var. Знаков “?” может быть несколько в таком случае они просто будут по очереди замещаться на следующее значение массива $array_var.

    ВНИМАНИЕ! Маска не должна содержать “’”;
    $array_var это численный массив.

    Если произойдет ошибка при выполнении запроса то пользователь получит сообщение об ошибке и сработает команда die(). Стандартно пользователь увидит системную информацию о происхождении ошибки (метод предназначен для создания лога).
    Конфигурация класса. Для задания конфигурации вам надо передать значения классу через метод Config($array) где $array ассоциативный массив с ключами pconn, host, port, user, pass, base, char, debug, loging. Думаю всем понятно для чего они и что в них вносить.

    Ладно хватит болтовни вот собственно обновлена версия класса:

    PHP:
    1. <?php
    2. /**
    3.  * Ксасс для роботы с базой данных
    4.  */
    5. class Database {
    6.  
    7.   private $pconn;
    8.   private $host;
    9.   private $port;
    10.   private $user;
    11.   private $pass;
    12.   private $base;
    13.   private $char;
    14.   private $debug;
    15.   private $loging;
    16.  
    17.   private $conn_id;
    18.   private $query_id;
    19.   private $counter = '0';
    20.   private $work_time;
    21.  
    22.   private $error;
    23.   private $error_exp;
    24.  
    25.   function Connect(){
    26.    
    27.         if($this->pconn){
    28.             $this->conn_id = @mysql_pconnect($this->host, $this->user, $this->pass);
    29.         } else {
    30.             $this->conn_id = @mysql_connect($this->host, $this->user, $this->pass);
    31.         }
    32.        
    33.         if($this->conn_id){
    34.             $dbselect = @mysql_select_db($this->base);
    35.             if(!$dbselect){
    36.                 @mysql_close($this->conn_id);
    37.                 $this->error = 'Невозможно выбрать базу данных';
    38.                 return false;
    39.             }
    40.         } else {
    41.           $this->error = 'Невозможно подключится к серверу базы данных';
    42.           return false;
    43.         }
    44.             return $this->conn_id;
    45.     }
    46.  
    47.     function Disconnect(){
    48.         if($this->conn_id){
    49.             if($this->query_id){
    50.                 @mysql_free_result($this->query_id);
    51.             }
    52.             $result = @mysql_close($this->conn_id);
    53.             return $result;
    54.         } else {
    55.             return false;
    56.         }
    57.     }
    58.  
    59.     function Query($query,$var,$file,$line){
    60.       $holder_count = substr_count($query, '?');
    61.     $var_count = count($var);
    62.     if($holder_count != $var_count || substr_count($query,"'") > '0'){
    63.       $var_merge = '';
    64.       foreach ($var as $key => $data){
    65.         $var_merge .= $data;
    66.       }
    67.       $query = 'Маска: '.$query.' Ключи: '.$var_merge;
    68.       $this->Log($query,$file,$line);
    69.       die();
    70.     }
    71.     $i = '0';
    72.     foreach ($var as $key => $data){
    73.       $query = preg_replace('\?', "'".$var[$i]."'", $query, '1');
    74.       $i++;
    75.     }
    76.    
    77.     if ($this->debug) {
    78.       $StartTimer = microtime(1);
    79.     }
    80.    
    81.     $this->query_id = mysql_query($query, $this->conn_id);
    82.     if (!$this->query_id){
    83.       $this->Log($query,$file,$line);
    84.       die('Ошибка выполнения запроса');
    85.     }
    86.    
    87.     if ($this->debug) {
    88.       $this->work_time = microtime(1) - $StartTimer;
    89.     }
    90.    
    91.     $this->counter++;
    92.    
    93.     return $this->query_id;
    94.     }
    95.    
    96.   function Fetch_Row($query_id = "") {
    97.     if ($query_id == "")
    98.     {
    99.         $query_id = $this->query_id;
    100.     }
    101.     return  mysql_fetch_array($query_id, MYSQL_ASSOC);
    102.   }
    103.    
    104.   function Get_Counter() {
    105.     return $this->counter;
    106.   }
    107.    
    108.   function Get_Result_Fields($query_id = "") {
    109.     if ($query_id == ""){
    110.       $query_id = $this->query_id;
    111.     }
    112.     while ($field = mysql_fetch_field($query_id)){
    113.       $Fields[] = $field;
    114.     }
    115.     return $Fields;
    116.     }
    117.    
    118.   function Free_Result($query_id = "") {
    119.         if ($query_id == "") {
    120.         $query_id = $this->query_id;
    121.     }
    122.     @mysql_free_result($query_id);
    123.   }    
    124.  
    125.     function Log($query,$file,$line){
    126.       if($this->loging){
    127.       if ($this->work_time > 0.1){
    128.       $time = "<span style='color:red'><b>$this->work_time</b></span>";
    129.       }  
    130.      
    131.       if(preg_match("/^fatal error/i",$query)){
    132.        
    133.         $this->error_exp .= "<table width='95%' border='1' cellpadding='6' cellspacing='0' bgcolor='#FEFEFE'  align='center'>";
    134.         $this->error_exp .= "<tr>";
    135.         $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'><b>Критическая Ошибка</b></td>";
    136.         $this->error_exp .= "</tr>";
    137.         $this->error_exp .= "<tr>";
    138.         $this->error_exp .= "<td style='font-family:courier, monaco, arial;font-size:14px'>".$query."</td>";
    139.         $this->error_exp .= "</tr>";
    140.         $this->error_exp .= "<tr>";
    141.         $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'>";
    142.         $this->error_exp .= "<b>Дата</b>: ".date("y.m.d H:i:s")."<br />";
    143.         $this->error_exp .= "<b>Файл</b>: ".$file."<br />";
    144.         $this->error_exp .= "<b>Строка</b>: ".$line."<br>";
    145.         $this->error_exp .= "</tr>";
    146.         $this->error_exp .= "</table><br />";
    147.        
    148.         }elseif (preg_match("/^select/i", $query)){
    149.         $explain = mysql_query("EXPLAIN $query", $this->conn_id);
    150.        
    151.         if ($explain !== true){
    152.           $this->error_exp .= "<table width='95%' border='1' cellpadding='6' cellspacing='0' bgcolor='#FEFEFE'  align='center'>";
    153.           $this->error_exp .= "<tr>";
    154.           $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'><b>Недопустимый запрос</b></td>";
    155.           $this->error_exp .= "</tr>";
    156.           $this->error_exp .= "<tr>";
    157.           $this->error_exp .= "<td style='font-family:courier, monaco, arial;font-size:14px'>".$query."</td>";
    158.           $this->error_exp .= "</tr>";
    159.           $this->error_exp .= "<tr>";
    160.           $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'>";
    161.           $this->error_exp .= "<b>Дата</b>: ".date("y.m.d H:i:s")."<br />";
    162.           $this->error_exp .= "<b>Файл</b>: ".$file."<br />";
    163.           $this->error_exp .= "<b>Строка</b>: ".$line."<br>";
    164.           $this->error_exp .= "</tr>";
    165.           $this->error_exp .= "</table><br />\n\n";
    166.  
    167.         } else {
    168.           $array = mysql_fetch_array($explain);
    169.           $type_col = '#FFFFFF';
    170.           if ($array['type'] == 'ref' or $array['type'] == 'eq_ref' or $array['type'] == 'const'){
    171.             $type_col = '#D8FFD4';
    172.           } else if ($array['type'] == 'ALL'){
    173.             $type_col = '#FFEEBA';
    174.           }
    175.           $this->error_exp .= "<table width='95%' border='1' cellpadding='6' cellspacing='0' bgcolor='#FFE8F3' align='center'>\n";
    176.           $this->error_exp .= "<tr>\n";
    177.           $this->error_exp .= "<td colspan='8' style='font-size:14px' bgcolor='#FFC5Cb'><b>Select Запрос</b></td>\n";
    178.           $this->error_exp .= "</tr>\n";
    179.           $this->error_exp .= "<tr>\n";
    180.           $this->error_exp .= "<td colspan='8' style='font-family:courier, monaco, arial;font-size:14px;color:black'>\n".$query."</td>";
    181.           $this->error_exp .= "</tr>\n";
    182.           $this->error_exp .= "<tr bgcolor='#FFC5Cb'>\n";
    183.           $this->error_exp .= "<td><b>table</b></td><td><b>type</b></td><td><b>possible_keys</b></td>\n";
    184.           $this->error_exp .= "<td><b>key</b></td><td><b>key_len</b></td><td><b>ref</b></td>\n";
    185.           $this->error_exp .= "<td><b>rows</b></td><td><b>Extra</b></td>\n";
    186.           $this->error_exp .= "</tr>\n";
    187.           $this->error_exp .= "<tr bgcolor='#FFFFFF'>\n";
    188.           $this->error_exp .= "<td>".$array[table]."&nbsp;</td>\n";
    189.           $this->error_exp .= "<td bgcolor='".$type_col."'>".$array[type]."&nbsp;</td>\n";
    190.           $this->error_exp .= "<td>".$array[possible_keys]."&nbsp;</td>\n";
    191.           $this->error_exp .= "<td>".$array[key]."&nbsp;</td>\n";
    192.           $this->error_exp .= "<td>".$array[key_len]."&nbsp;</td>\n";
    193.           $this->error_exp .= "<td>".$array[ref]."&nbsp;</td>\n";
    194.           $this->error_exp .= "<td>".$array[rows]."&nbsp;</td>\n";
    195.           $this->error_exp .= "<td>".$array[Extra]."&nbsp;</td>\n";
    196.           $this->error_exp .= "</tr>\n";
    197.           $this->error_exp .= "<tr>\n";
    198.           $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'>";
    199.           $this->error_exp .= "<b>Дата</b>: ".date("y.m.d H:i:s")."<br />";
    200.           $this->error_exp .= "<b>Файл</b>: ".$file."<br />";
    201.           $this->error_exp .= "<b>Строка</b>: ".$line."<br>";
    202.           $this->error_exp .= "<b>Время выполнения</b>: ".$time;
    203.           $this->error_exp .= "</tr>";
    204.           $this->error_exp .= "</table><br />\n\n";
    205.         }
    206.       } else {
    207.         $this->error_exp .= "<table width='95%' border='1' cellpadding='6' cellspacing='0' bgcolor='#FEFEFE'  align='center'>";
    208.         $this->error_exp .= "<tr>";
    209.         $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'><b>Не Select Запрс</b></td>";
    210.         $this->error_exp .= "</tr>";
    211.         $this->error_exp .= "<tr>";
    212.         $this->error_exp .= "<td style='font-family:courier, monaco, arial;font-size:14px'>".$query."</td>";
    213.         $this->error_exp .= "</tr>";
    214.         $this->error_exp .= "<tr>";
    215.         $this->error_exp .= "<td style='font-size:14px' bgcolor='#EFEFEF'>";
    216.         $this->error_exp .= "<b>Дата</b>: ".date("y.m.d H:i:s")."<br />";
    217.         $this->error_exp .= "<b>Файл</b>: ".$file."<br />";
    218.         $this->error_exp .= "<b>Строка</b>: ".$line."<br>";
    219.         $this->error_exp .= "<b>Время выполнения</b>: ".$time;
    220.         $this->error_exp .= "</tr>";
    221.         $this->error_exp .= "</table><br />\n\n";
    222.       }
    223.       return $this->error_exp; //Временно!
    224.       }
    225.     }
    226.    
    227.   function Config($array){
    228.     if(empty($array)){
    229.       $this->error = 'Конфигурация БД не задана';
    230.       return false;
    231.     }
    232.    
    233.     $class_vars = get_object_vars($this);
    234.     foreach ($class_vars as $key => $val){
    235.       if (array_key_exists($key, $array)) {
    236.         $this->$key = $array[$key];
    237.       }
    238.     }
    239.    
    240.     return true;
    241.   }
    242. } // Конец класса
    243. ?>
    Предупреждаю! класс я полностью не тестировал. Завтра прогоню его и исправлю. Если найдете ошибки, подождите до завтра может я их сам исправлю. Пишите, обсуждайте, буду рад.
     
  17. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    На самом деле есть MySQLi где уже есть Prepared Statments. Так что лучше юзать их :)
    А вообще, я считаю, что в классе не надо заморачиваться с проверками. Это должно лежать на плечах самого программиста. Если он составил криво запрос - это его проблемы. А проверять, парсить, экранировать... бесполеная работа, пожирающая порой много процесорного времени.

    P.S. Я вообще работаю напрямую с mysql_* функциями.

    А если юзаю MySQLi и мне нужен какой-то дебагинг, я просто переопределяю метод query и всё. Большего там практически не надо.
     
  18. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Согласен, но только в том случае если параметры запроса задаются не пользовательским вводом.
    А если запрос составляется динамически? Что каждый раз делать довольно не малый код проверки данных? Или писать сложное регулярное выражение, которое будет проверять правильно указаны параметры или нет? Думаю, что такие способы будут не намного быстрее, чем этот класс. Зато объемы кода резко увеличатся, да и читаемость явно не возрастет. По крайней мере, мне будет неудобно разобраться у куче кода, который делает проверку каждой переменной (в запросе) которую передал пользователь.
     
  19. DarkElf

    DarkElf Активный пользователь

    С нами с:
    22 окт 2006
    Сообщения:
    1.632
    Симпатии:
    0
    а почему не сделать функцию проверки?

    почему не разделить входящие параметры на типы и важность, и проверять в зависимости от них?
     
  20. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Не всегда хорошая идея приходит сразу.
    Но все равно надо проверять ,так какая разница в классе или нет?
     
  21. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Обычно всё же данные часто бывают разнородные. Где то это может быть цифра, а пришлют строку - как функция поймёт что это должна быть цифра? :) Задавать конфиги - тоже нудно. А если надо проверить регулярками, или разбить данные на части и.т.д.?
    Тупая проверка не занимает много места и пишеться быстро. Удобно использовать Exceptions в этом случае. Если код написан правильно, такие коды будут минимальны и просты и писаться за минуты. У меня всё время уходит обычно на другие вещи, проверка данных пишеться в течении буквально от 2-3 до 30 (совсем запущенный случай) минут в зависимости от их кол-ва и сложности проверок.
    В текущем проэкте я писал форум, проверка данных заняла буквально 3-4 строки с выводом ошибки. Так что заморачиваться с их проверкой на самом деле глупо. Писать мега функции, которые только будут тормозить, когда решение на самом деле очень простое, не логично.

    Пример.
    У вас приходит из URL'a ID. Конечно надо защититься от SQL Injection. Тупо делаем так:

    PHP:
    1. <?php
    2. $result = mysql_query('SELECT * FROM table WHERE id = '.(int)$_GET['id'], $db);
    3. if (mysql_num_rows($result)){
    4.     // обрабатываем и выводим результат
    5. }else{
    6.    exit('Хакирь, да?');
    7. }
    8. ?>
    SQL Injection не случиться 100%. Введут левый ID? Ну и что, выведит просто другие данные. Если нужна проверка, а может ли пользователь иметь доступ к данным, то просто надо дополнительно проверить уровень доступа и в IF вписать через && условие, а может ли он иметь к данным доступ.

    Вставка данных? Да так-же. Если нужно число, вставляем (int)$_POST['chislo'], всё остальное вставляем пропустив через mysql_escape_string() и в " " кавычки в запросе. Если надо, проверили важные данные, а валидны ли они.

    Хотя конечно это просто надо на опыте понять. Мне намного проще работать напрямую. Это даёт максимальную гибкость, я не упираюсь в ограничения самописных функций по проверке данных. Делаю так, как удобнее в конкретном случае и могу проверить что угодно. От просто заквотить данные, до мега проверки по половине базы данных, а можно ли вставить такие данные этому юзеру вот в такое поле, проверить верны ли ID'ки которые он прислал. И.т.д.

    Стараюсь держаться принципа KISS, писать просто но удобно и без лишнего кода. PHP всё же скриптовый язык и кол-во и сложность кода на скорость влияют гораздо сильнее, чем на любой компилируемый язык. Зачем мучаться, писать мега универсальные функции проверок, с кучей конфигов и.т.д., если я могу просто сделать
    PHP:
    1. <?php
    2. if (is_numeric($param1) && is_array($param2)){
    3.    // do something
    4. }else{
    5.    // Error, invalid data. Print form again with filled fields
    6. }
    Быстро, просто, понятно!
     
  22. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    после этого можно было бы и не продолжать, ибо жудкая весч :)

    1. http://php.net/debug_backtrace
    2. что функция логирования забыла в классе работы с БД?
    3. почему чтобы начать работать с БД нужно написать преварительно 3 строчки кода?
    4. почему нельзя использовать апостроф в запросе?
    5. как выбрать всю таблицу ввиде одного массива?
     
  23. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Ребята я только учусь, и благодаря этому обсуждению обучение проходит гораздо быстрее. Спасибо вам за это!

    Psih по поводу проверок. Сам посмотрел на свой код и понял что слишком много лишнего и нагружающего. Просто учусь на разборе чих-то проектов типа форумов CMS и т.д. Смотрел как они делают проверку и подумал что такие опытные люди как они не могут так просто ошибиться (видно что могут). Для себя окончательно решил делать проверку до класса (причем сам), а ваши слова только подтверждают мою правоту.

    dark-demon полностью упрощать запрос я не хочу и не буду т.к. Я решил упростить его до такой формы:
    PHP:
    1. <?php
    2. $DB->Query($query,  __FILE__,  __LINE__);
    FILE и LINE я решил оставить по тому что потом будет легче находить откуда пошла ошибка, да и поставить __FILE__ __LINE__ не большая проблема.
     
  24. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
  25. oligarx

    oligarx Активный пользователь

    С нами с:
    23 янв 2007
    Сообщения:
    68
    Симпатии:
    0
    Адрес:
    Украина Львов
    Читал! Но мне такой принцип не очень. Мой способ просто мне нравится больше.
    Да и что проблема вставить два слова?

    440Hz что боты все-таки нравится начали? Где капача?
     
Статус темы:
Закрыта.