наши рабочие классы для работы с бд

Тема в разделе ".:: Готовые решения", создана пользователем zaartix, 16 июл 2008.

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

    Simpson

    Регистр.:
    22 июл 2007
    Сообщения:
    373
    Симпатии:
    36
    Мда... Книжек обчитался или где? С какого перепугу бизнес-логика попала в прослойку субд? Типа умными словами забросать решил. Ну-ну. Не рассказывай об этом никому - засмеют.

    Если фильтрация ввода не защищает от инъекции, то что по-твоему защищает? Бойцы невидимого фронта? А ну да, это ж нужен еще отдельный класс для фильтрации ввода. Ну так и выложил бы его вместе с классом логгера. А то выложил кусок и удивляется что кому-то что-то не понравилось.

    P.S. htmlspecialchars из своего поста оставляю. А то тебе цепляться некчему будет.
     
  2. Jeurey

    Jeurey

    Регистр.:
    13 сен 2006
    Сообщения:
    419
    Симпатии:
    575
    Давайте определимся с понятием фильтрация и будем спорить дальше.

    В "стандартных", описанных методах SQL-инъекций, используются как-раз таки кавычки, для обрыва серии строк и вставки своего кода. Помочь-то помогает, только вот насколько оптимален данный подход - большой вопрос.

    Стоит, однако, заметить, что функциями удаления/экранирования нежелательных данных изначально являются mysql_escape_string, mysql_real_escape_string, addslashes :)
     
  3. Simpson

    Simpson

    Регистр.:
    22 июл 2007
    Сообщения:
    373
    Симпатии:
    36
    А я и не спорил. Просто некоторые цепляются к словам. Для чего мы пользуем htmlspecialchars? Для фильтрации ввода. А для чего mysql_escape_string и иже с ним? Тоже для фильтрации ввода. Я (когда надо) еще пользую регексп для проверки языка (например пропускаем только украинский). Указав htmlspecialchars я имел ввиду фильтрацию вообще и, как мне казалось (и кажется) из контекста это было ясно всем (как выяснилось не всем). Почему господину Slayter-у захотелось выпендрится мне не понять. Вот такие дела...
     
  4. venetu

    venetu

    Регистр.:
    28 мар 2007
    Сообщения:
    745
    Симпатии:
    264
    Люди, а объясните мне глупому, зачем вообще эти классы нужны? Ну то есть почему бы нам не писать прямо в коде
    mysql_query() вместо $moysuperclass->query(); Чем это хуже?

    А, да, знаю. Тяжело будет мигрировать на другую СУБД.
    Вы много вообще использовали субд, кроме мускула?
    Как правило если субд - не мускул, то об этом известно еще задолго до начала проекта. И шанс, что так будет, а особенно среди nulled тусовки, - он вообще-то говоря ничтожен.
    Так зачем городить огород?
     
  5. Slayter

    Slayter

    Регистр.:
    8 апр 2006
    Сообщения:
    231
    Симпатии:
    51
    Simpson, чё за бред ты несёшь? "бизнес-логика попала в прослойку субд" -- сам-то понял чо сказал? Любая работа с данными (а прослойка для субд именно с ними и работает) есть бизнес-логика приложения. По GoF она относится к модели в паттерне MVC, адептом которого я и являюсь :)

    К фильтрации содержимого посредством htmlspecialchars прибегают только начинающие разработчики (ню-ню, пожалуйста, применяй его в админке, например:D, чтобы пресечь использование html'я некой группой пользователей), а те, у которых есть опыт разрешают пользователю вводить определённые html теги (или предоставляют для этого визуальный редактор).

    Ну а фильтрацией занимаются отдельные валидаторы (POSIX, PCRE -- дело вкуса + для некоторых типов данных они и не нужны, хватает стандартных проверок) :) Ну а если php > 5.2.0 и стоит PECL filter, то прекрасное решение всех этих танцов с бубнами есть filter_var();, что вообще и не является проблемой, т.к. я думаю тут мало кто пользуется шаред-хостингами. VPS сейчас за копейки можно приобрести в пользование и настроить всё как надо. Сам пользуюсь регулярными выражениями, т.к. некоторые клиенты предпочитают размещать свои сайты таки на каком-нибудь уёбищном хостинге. С этим ничего не поделаешь, а жаль, конечно :(

    Защитой от SQL-инъекций должна заниматься сама прослойка для работы с базой данных (простого mysql_escape_string для этого вполне хватает). Нет, ну если не так, то какой идиот будет ручками всё обрабатывать перед передачей классу? :(
     
  6. Simpson

    Simpson

    Регистр.:
    22 июл 2007
    Сообщения:
    373
    Симпатии:
    36
    Я несу бред?... Мда. Твое заблуждение насчет бизнес-логики лечится вдумчивым чтением википедии.

    http://ru.wikipedia.org/wiki/Бизнес-логика
    ну и конечно же http://ru.wikipedia.org/wiki/Model-view-controller

    Насчет GoF - тут загадочная ситуация. В их книге описывается 23 паттерна, но ничего такого что ты тут пишешь, увы, нет. Собственно интересно узнать кто-куда-чего-относит. Можешь пару цитат привести для примера (желательно с номером страницы)?

    Насчет остального - где-то согласен, где-то нет. Но поскольку тема ушла в сторону смысла в дальнейшем обсуждении не вижу.
     
  7. dumber

    dumber

    Регистр.:
    23 апр 2007
    Сообщения:
    272
    Симпатии:
    123
    Во блин демагогию со спорами развели :D

    Моя класса для работы с БД использующая PDO

    PHP:
    class Datasource_gopher extends PDO {
        
        const
                    
    _QUOTE_TABLE    1,
                    
    _QUOTE_COL        2,
                    
    _QUOTE_BOTH        3,
                    
    _QUOTE_NONE        0;
                    
        protected 
    $db_prefix null;
        
        protected 
    $invalid_format 'provided %1$s name "%1$2" is not a valid name. Must contain "A-Z", "a-z", "0-9", "_", "-" only, and begin with an Alpha char';
        
    // constructor function
        
    public function __construct() {
            global 
    $cfg_database$cfg_host$cfg_user$cfg_pass$cfg_port$cfg_type;
            
            if ( empty( 
    $cfg_database ) && empty( $cfg_host ) ) {
                    
    $dns $cfg_type;
                    
    // Get the driver that is to be used
                    
    $split_dns explode':'$dns );
                    
    $driver $split_dns[0];
                } else {
                    
    // Build the DNS string needed
                    
    if ( $cfg_type == 'mysqli' ) {
                        
    $cfg_type 'mysql';
                    }
                    
    $driver $cfg_type;
                    
    $dns sprintf'%1$s:host=%2$s;dbname=%3$s'$cfg_type$cfg_host$cfg_database );
                    if ( !empty( 
    $cfg_port ) ) {
                        
    $dns .= ';port='.$cfg_port;
                    }                
                }
                
    /**
                 * Check the needed PDO driver is there
                 */
                
    if ( !in_array$driver$this->getAvailableDrivers() ) ) {
                    throw new 
    SQL_InvalidDriver'PDO driver "'.$driver.'" is not available, ensure it is installed'20 );
                }
                try {
                    if ( empty( 
    $driver_options ) || !is_array$driver_options ) ) {
                        
    $driver_options = array(
                                                
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ,
                                                );
                    }
                    if ( 
    $driver == 'mysql' ) {
                        
    $driver_optionsPDO::MYSQL_ATTR_USE_BUFFERED_QUERY ] = true;
                    }
                    
    parent::__construct$dns$cfg_user$cfg_pass$driver_options );
                } catch ( 
    PDOexception $e ) {
                    throw new 
    SQL_UnableToConnect$e->getMessage(), 21 );
                }
        }
        
    // empty destructor function
        
    public function __destruct() {
            
        }
        
        public function 
    get_db_prefix() 
        {
            global 
    $cfg_prefix;
            if ( 
    is_null$this->db_prefix ) ) 
            {
                
    // Get prefix from config
                
    $this->set_prefix($cfg_prefix);
            }
            return 
    $this->db_prefix;
        }
        public function 
    set_prefix$prefix 
        {
            
    $this->db_prefix $prefix;
        }
        
        public function 
    check_name$name 
        {
                if ( 
    preg_match'#[A-Z][A-Z0-9_\-]+#i'$name ) && trim$name ) == $name ) {
                    return 
    true;
                } else {
                    return 
    false;
                }
        }
        
        public function 
    query$statement$arg2=''$arg3=''$arg4='' 
        {    
                
    // Replace {SQL_PREFIX} with the table prefix
                
    $statement str_replace'{SQL_PREFIX}'$this->get_db_prefix(), $statement );
                try {
                    
    $result parent::query$statement$arg2$arg3$arg4 );
                    return 
    $result;
                } catch ( 
    PDOException $e ) {
                    throw new 
    SQL_QueryFailed$e->getMessage(), 22 );
                }
        }
        public function 
    prepare$statement$driver_opts=array() ) 
        {
                
    $statement str_replace'{SQL_PREFIX}'$this->get_db_prefix(), $statement );
                return 
    parent::prepare$statement$driver_opts );
        }
        public function 
    num_rows$result 
        {
                return 
    $result->rowCount();
        }
        public function 
    insert_id() 
        {
                return 
    $this->lastInsertID();
        }
        public function 
    insert$table$entries$quote_ident=self::_QUOTE_BOTH 
        {
                
    $table $this->get_db_prefix().$table;
                if ( 
    $this->check_name$table ) ) {
                    if ( 
    $quote_ident self::_QUOTE_TABLE ) {
                        
    $table '`'.$table.'`';
                    }
                    
    $query_parts = array();        
                    foreach( 
    $entries as $col=>$val ) {
                        if ( !
    $this->check_name$col ) ) {
                            
    // Column has invalid name
                            
    throw new SQL_InvalidNamesprintf$this->invalid_format'column'$col ), 22 );
                        } else if ( 
    $quote_ident self::_QUOTE_COL ) {
                            
    $query_parts['col'][] = '`'.$col.'`, ';
                        } else {
                            
    $query_parts['col'][] = $col.', ';
                        }
                        
    $query_parts['val'][] = '?, ';
                    }                
                    
    // Create the column and value strings
                    
    $query_parts['col'] = trimimplode''$query_parts['col'] ), ', ' );
                    
    $query_parts['val'] = trimimplode''$query_parts['val'] ), ', ' );                
                    
    $statement 'INSERT INTO '.$table.' ( '.$query_parts['col'].' ) VALUES ( '.$query_parts['val'].' )';                
                    
    // Prepare and execute query
                    
    try {
                        
    $pdo_st parent::prepare$statement );
                        
    $pdo_st->executearray_values$entries ) );
                        return 
    $pdo_st;
                    } catch ( 
    PDOException $e ) {
                        
    //throw new SQL_QueryFailed( $e->getMessage(), 22 );
                    
    }
                } else {
                
    //    throw new SQL_InvalidName( sprintf( $this->invalid_format, 'table', $table ), 23 );
                
    }
        }
        
        public function 
    update$table$entries$where=array(), $quote_ident=self::_QUOTE_BOTH ) {
                
    $table $this->get_db_prefix().$table;
                if ( 
    $this->check_name$table ) ) {
                    if ( 
    $quote_ident self::_QUOTE_TABLE ) {
                        
    $table '`'.$table.'`';
                    }
                    
    $sql 'UPDATE '.$table.' SET ';
                    
    // Create the middle section of the query
                    
    $middle_sql '';
                    foreach( 
    $entries as $key=>$val ) {
                        if ( !
    $this->check_name$key ) ) {
                            
    // Column has invalid name
                            
    throw new SQL_InvalidNamesprintf$this->invalid_format'column'$key ), 23 );
                        } else if ( 
    $quote_ident self::_QUOTE_COL ) {
                            
    $key '`'.$key.'`';
                        }
                        
    $middle_sql .= $key.' = ?, ';
                    }
                    
    $sql .= trim$middle_sql', ' );
                    if ( 
    is_array$where ) && !empty( $where ) ) {
                        
    // Add where onto the query (Only allows for equals so far)
                        
    $where_sql '';
                        foreach( 
    $where as $key=>$val ) {
                            if ( !
    $this->check_name$key ) ) {
                                
    // Column has invalid name
                                
    throw new SQL_InvalidNamesprintf$this->invalid_format'column'$key ), 23 );
                            } else if ( 
    $quote_ident self::_QUOTE_COL ) {
                                
    $key '`'.$key.'`';
                            }
                            
    $where_sql .= ' AND '.$key.' = ? ';
                        }
                        
    $sql .= ' WHERE '.trim$where_sql'AND ' );
                    }
                    
    // Prepare and execute query
                    
    try {
                        
    $pdo_st parent::prepare$sql );
                        
    $pdo_st->executearray_mergearray_values($entries), array_values($where) ) );
                        return 
    $pdo_st;
                    } catch ( 
    PDOException $e ) {
                    
    //    throw new SQL_QueryFailed( $e->getMessage(), 22 );
                    
    }
                } else {
                
    //    throw new SQL_InvalidName( sprintf( $this->invalid_format, 'table', $table ), 23 );
                
    }
        }
        public function 
    select$table$where=array(), $cols=array(), $quote_ident=self::_QUOTE_BOTH ) {
                if ( !
    is_array$where ) ) {
                    
    $where = array();
                }
                if ( !
    is_array$cols ) ) {
                    
    $cols = array();
                }
                
    $table $this->get_db_prefix().$table;
                if ( 
    $this->check_name$table ) ) {
                    if ( 
    $quote_ident self::_QUOTE_TABLE ) {
                        
    $table '`'.$table.'`';
                    }
                    if ( (empty( 
    $cols ) || !is_array$cols )) && (empty( $where ) || !is_array$where )) ) {
                        
    // Run a straight select all on the provided table
                        
    try {
                            
    $pdo_st parent::prepare'SELECT * FROM '.$table );
                            
    $pdo_st->execute();
                            return 
    $pdo_st;
                        } catch ( 
    PDOException $e ) {
                        
    //    throw new SQL_QueryFailed( $e->getMessage(), 22 );
                        
    }
                    } else {
                        
    /**
                         * Construct the correct query string needed for use with prepared
                         * queries. Depending on the $quote_ident, the column names may be
                         * quoted correctly.
                         */
                        
    $sql 'SELECT ';
                        if ( 
    is_array$cols ) && !empty( $cols ) ) {
                            
    // Add the columns onto the query
                            
    foreach( $cols as $key=>$column ) {
                                if ( 
    is_array$column ) ) {
                                    
    trigger_error'Sql::select() invalid column value type (array)'E_USER_WARNING );
                                    unset( 
    $cols$key ] );
                                } else if ( !
    $this->check_name$column ) ) {
                                    
    // Column has invalid name
                                //    throw new SQL_InvalidName( sprintf( $this->invalid_format, 'column', $column ), 23 );                            
                                
    } else if ( $quote_ident self::_QUOTE_COL ) {
                                    
    $cols$key ] = '`'.$column.'`';
                                }
                            }
                            
    $sql .= trimimplode','$cols ), ', ' );
                        } else {
                            
    $sql .= '*';
                        }
                        
    $sql .= ' FROM '.$table# Add the table on
                        
    if ( is_array$where ) && !empty( $where ) ) {
                            
    // Add Where on
                            
    $where_sql '';
                            foreach( 
    $where as $key=>$val ) {
                                if ( 
    is_array$val ) ) {
                                    
    trigger_error'Sql::select() invalid where value type (array) for key "'.$key.'"'E_USER_WARNING );
                                    continue;
                                } else if ( !
    $this->check_name$key ) ) {
                                    
    // Column has invalid name
                                    
    throw new SQL_InvalidNamesprintf$this->invalid_format'column'$key ), 23 );
                                } else if ( 
    $quote_ident self::_QUOTE_COL ) {
                                    
    $key '`'.$key.'`';
                                }                            
                                
    $where_sql .= ' AND '.$key.' = ?';
                            }
                            
    $sql .= ' WHERE '.trim$where_sql'AND ' );
                        }
                        
    // Prepare and execute query
                        
    try {
                            
    $pdo_st parent::prepare$sql );
                            
    $pdo_st->executearray_values$where ) );
                            return 
    $pdo_st;
                        } catch ( 
    PDOException $e ) {
                        
    //    throw new SQL_QueryFailed( $e->getMessage(), 22 );
                        
    }
                    }    
                } else {
                
    //    throw new SQL_InvalidName( sprintf( $this->invalid_format, 'table', $table ), 23 );
                
    }                
        }    
        public function 
    delete$table$where$quote_ident=self::_QUOTE_BOTH ) {
                
    $table $this->get_db_prefix().$table;
                if ( !
    is_array$where ) || empty( $where ) ) {
                    throw new 
    SQL_QueryFailed'second argument must be an array' );
                } else if ( 
    $this->check_name$table ) ) {
                    if ( 
    $quote_ident self::_QUOTE_TABLE ) {
                        
    $table '`'.$table.'`';
                    }
                    
    $sql 'DELETE FROM '.$table;
                    
    $where_sql '';
                    foreach( 
    $where as $key=>$val ) {
                        if ( 
    is_array$val ) ) {
                            
    trigger_error'Sql::delete() invalid where value type (array) for key "'.$key.'"'E_USER_WARNING );
                            continue;
                        } else if ( !
    $this->check_name$key ) ) {
                            
    // Column has invalid name
                            
    throw new SQL_InvalidNamesprintf$this->invalid_format'column'$key ), 23 );
                        } else if ( 
    $quote_ident self::_QUOTE_COL ) {
                            
    $key '`'.$key.'`';
                        }                            
                        
    $where_sql .= ' AND '.$key.' = ?';
                    }
                    
    $sql .= ' WHERE '.trim$where_sql'AND ' );
                    
    // Prepare and execute query
                    
    try {
                        
    $pdo_st parent::prepare$sql );
                        
    $pdo_st->executearray_values$where ) );
                        return 
    $pdo_st;
                    } catch ( 
    PDOException $e ) {
                    
    //    throw new SQL_QueryFailed( $e->getMessage(), 22 );
                    
    }
                } else {
                
    //    throw new SQL_InvalidName( sprintf( $this->invalid_format, 'table', $table ), 23 );
                
    }
        }
        public function 
    split_sql_file$file$delimiter=';'$run_queries=true ) {
                if ( !
    is_file$file ) || !is_readable$file ) ) {
                    throw new 
    Sql_InvalidFile$file.' does not exist or is not readable' );
                }
                
    // Remove comments from file
                
    $file_contents file_get_contents$file );
                
    $this->remove_remarks$file_contents );
                
    /**
                 * Get string into one big line, splitting on the delimiter
                 * and then trimming off any white space
                 */
                
    $sql str_replace"\r" ''$file_contents );
                
    $data preg_split'/' preg_quote$delimiter'/' ) . '$/m'$file_contents );
                
    $data array_map'trim' $data) ;
                
    // The empty case
                
    $end_data end$data );
                if ( empty( 
    $end_data ) ) {
                    unset( 
    $datakey$data ) ] );
                }
                if ( 
    $run_queries == true ) {
                    foreach( 
    $data as $key=>$query ) {
                        if ( !
    trim$query ) ) {
                            unset( 
    $data$key ] );
                        } else {
                            
    $this->query$query );
                        }
                    }
                }
                return 
    $data;
        }
    }
    Может еще ко мне кто придирется, давненько уже ни с кем не ссорился :D
     
  8. Jeurey

    Jeurey

    Регистр.:
    13 сен 2006
    Сообщения:
    419
    Симпатии:
    575
    dumber, ты, конечно, не обижайся... Но чего-то ты намудрил :)

    PHP:
    public function __construct() {
            global 
    $cfg_database$cfg_host$cfg_user$cfg_pass$cfg_port$cfg_type;
    Ничего не смущает, не? Как-то globals не смотрятся :)

    PHP:
    public function set_prefix$prefix 
        {
            
    $this->db_prefix $prefix;
        }
    Что мешает magic-функции использовать (если так хочется извне переопределять)?
    PHP:
     $db -> __set('db_prefix'$prefix);
    Мягко говоря, непонятно введение в условия констант, которые заведомо возвратят true
    PHP:
    if ( $quote_ident self::_QUOTE_TABLE ) {
    Мутновато, все-таки...
     
  9. dumber

    dumber

    Регистр.:
    23 апр 2007
    Сообщения:
    272
    Симпатии:
    123
    PHP:
    public function __construct() {
            global 
    $cfg_database$cfg_host$cfg_user$cfg_pass$cfg_port$cfg_type;
    Ничего не смущает, не? Как-то globals не смотрятся :)

    ГЫ, класс то взял с проекта, доп функции я убрал а глобалки не заметил, оставил :) Они там не нужны, в оригинале в качестве параметров construct все передавалось :)

    PHP:
    public function set_prefix$prefix 
        {
            
    $this->db_prefix $prefix;
        }
    Что мешает magic-функции использовать (если так хочется извне переопределять)?
    PHP:
     $db -> __set('db_prefix'$prefix);
    Ну мне так больше нравица :)

    Мягко говоря, непонятно введение в условия констант, которые заведомо возвратят true
    PHP:
    if ( $quote_ident self::_QUOTE_TABLE ) {
    а тут quote_ident может быть и константой QUOTE_NONE которая равна нулю, тобишь false а значит не нужно нам кавычки ставить :)

    а если все четко и ясно то неинтересно ;)
    ну и я никогда не пишу коды для других, цели мои использование тоже мое, а делюсь так просто от нечего делать :)
     
  10. Slayter

    Slayter

    Регистр.:
    8 апр 2006
    Сообщения:
    231
    Симпатии:
    51
    Simpson, на той же википедии ясно написано "Модель (Model). Модель предоставляет данные (обычно для View), а также реагирует на запросы (обычно от контролера ), изменяя свое состояние." так что не надо :smmne:

    А если говорить про GoF, то открой 19ю (это ещё введение, кстати :D) страницу (ну в той версии книги, что у меня)
    последний абзац специально выделил :confused:

    http://s50.radikal.ru/i130/0807/fd/1092ae8a41de.jpg

    ну и себя процитирую:
    Работа с любыми данными возлагается на модель. И это в понимании широких кругов разработчиков есть именно бизнес-логика приложений. Не важно откуда данные берутся (база, файловая система или что ещё), важно отделить работу с ними от всей остальной части приложения.

    dumber, зачётно, молодец. Сам всё никак не соберусь написать апдейт, делит и селект методы для своего класса. Было бы полезно, но лень :) у меня в моделях хранятся в константах шаблоны запросов к базе :ah:
     
Статус темы:
Закрыта.