Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> MySQL Driver, Проба 
V
    Опции темы
ShurikA
Дата 8.8.2007, 03:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Что не в порядке в этом  классе:
Код

<?php
/**
 * mysql_driver.php
 * Created on Thu Aug 02 17:44:08 GMT 2007
 * By Alex Agulyansky (ShurikAg), IIBS Ltd.
 * Email: [email protected]
 * 
 * Copyright © 2007 IIBS. All rights reserved
 * 
 * This program cannot be distributed by any authority but IIBS Ltd. 
 * If you have purchased of downloaded this file, please report this to our email above.
 */

/**
 * @package IIBCore
 * @subpackage classes
 * @abstract  The class provides a whole functionality of interacting with MySQL DB.
 * IibCoreApi MUST be loaded!
 */

class IibMySQLDriver{
    private static $instance;

    private $connection_link;
    private $error = "";
    private $error_no = "";
    private $quiry_count = 0;
    private $query_res = "";
    private $record_row = array ();
    private $last_query = "";

    private function __construct(){
        global $coreApi;

        $coreApi->requireOnce(CORE_PATH."/configs/IibMySQLDriver.conf.php");
    }

    public static function  getInstance(){
        if(!isset(self::$instance)){
            $c = __CLASS__;
            self::$instance = new $c;
        }
        self::$instance->connect();
        return self::$instance;
    }

    /**
     * Prevent the users to colne the object.
     *
     */
    public function __clone()
    {
        trigger_error('IibMySQLDriver - Clone is not allowed.', E_CORE_ERROR);
    }


    public function __destruct(){
        self::$instance->freeResult();
        self::$instance->close_db();
    }

    /**
     * @abstract Connect to DB and select the DB.
     * @return TRUE if the connection successful, othervise - prints error message and dies.
     */
    private function connect(){
        global $mysqlConf;

        self::$instance->connection_link = @mysql_pconnect($mysqlConf["host"], $mysqlConf["user"], $mysqlConf["pass"]);
        if (!self::$instance->connection_link) {
            trigger_error("IibMySQLDriver - Fatal error: " . mysql_error(), E_CORE_ERROR);
            die();
        }

        if (!mysql_select_db($mysqlConf["db"], self::$instance->connection_link)) {
            trigger_error("IibMySQLDriver - Fatal error: " . mysql_error(), E_CORE_ERROR);
            die();
        }

        return TRUE;
    }

    /**
     * Proccess a menual query request. The function executes the query without any additional checking of the
     * query syntax. If there is an error in syntax, a fatal error thrown.
     *
     * @param String $query A full query string. If $query is not set the last_query that was set is taken in to account.
     * In case that the last set query is also not set error triggered.
     * @return resource from the query processing.
     */
    public function query($query){
        if(isset($query) && $query != ""){
            self::$instance->last_query = $query;
        }

        if(self::$instance->last_query == ""){
            trigger_error("IibMySQLDriver - Query string is not set.", E_USER_ERROR);
        }

        self::$instance->query_res = @mysql_query(self::$instance->last_query, self::$instance->connection_link);

        if(self::$instance->query_res == false){
            trigger_error("IibMySQLDriver - Query execution failed; Error: ". mysql_error());
        }
    }


    /**
     * Retreaves number of rows in the last result set. if
     * @param resource [optional] $result_set - the result set to get the number of rows from 
     * @return integer Number of rows.
     *
     */
    public function getNumOfRows($result_set){
        if(isset($result_set) && $result_set != ""){
            $res = $result_set;
        } elseif (self::$instance->query_res != ""){
            $res = self::$instance->query_res;
        } else {
            return 0;
        }

        $rows = mysql_num_rows($res);

        return $rows;
    }

    /**
     * Returns the number of affected rows from the last update, insert or remove queries.
     * @param resource [optional] $result_set - the result set from the requerted request.
     * @return integer - Number of rows affected.
     *
     */
    public function getNumOfAffectedRows($result_set){
        if(isset($result_set) && $result_set != ""){
            $res = $result_set;
        } elseif (self::$instance->query_res != ""){
            $res = self::$instance->query_res;
        } else {
            return 0;
        }

        $rows = mysql_affected_rows($res);

        return $rows;
    }

    /**
     * Gets the line id from the last insert query.
     * @return integer Line id, 0 in last query did not generate any id or -1 on error.
     *
     */
    public function getLastInsertId(){
        if(!self::$instance->connection_link){
            return -1;
        }

        $id = mysql_insert_id(self::$instance->connection_link);

        return $id;
    }

    /**
     * Fetches a data of next row from the result set result; if none is given the last available result set is used.
     *
     * @param Array $res_set - Data of the row as an array.
     */
    public function fetchArray($res_set){
        if(isset($res_set) && $res_set != ""){
            $res = $res_set;
        } elseif (self::$instance->query_res != ""){
            $res = self::$instance->query_res;
        } else {
            return 0;
        }

        self::$instance->record_row = @mysql_fetch_array($res, MYSQL_ASSOC);

        return self::$instance->record_row;
    }

    /**
     * Gets count of queries made by now.
     * @return integer - Count of queries.
     *
     */
    public function getQueryCount(){
        return self::$instance->quiry_count;
    }

    /**
     * Frees the result from mysql memory.
     * @param resource [optional] $res_set - Result set.
     * @return boolean TRUE if successful, FALSE othervise.
     */
    public function freeResult($res_set){
        if(isset($res_set) && $res_set != ""){
            $res = $res_set;
        } else {
            $res = self::$instance->query_res;
        }

        return @mysql_free_result($res);
    }

    /**
     * Closes the connection to DB
     *
     * @return boolean TRUE if successful, FALSE othervise.
     */
    public function closeDb(){
        if(self::$instance->connection_link){
            return @mysql_close(self::$instance->connection_link);
        }

        return false;
    }

    /**
     * Compiles a query string from given data. During the compilation converts the data to desired data types.
     *
     * @param array $data {
     *        ['data_field'] => array( 'data_type' = "type", 'value' = "value" )
     * }
     * @return Array ( 'FIELD_NAMES'  => "f1,f2...", 'FIELD_VALUES' => "v1,v2...");
     */
    private function compileInsertQueryString($data = array()){
        $insert_fields = "";
        $insert_values = "";

        foreach($data as $k => $v){
            $insert_fields .= "`".$k."`,";

            switch($v["data_type"]){
                case "string" :
                    $insert_values .= "'".addslashes(strip_tags(trim($v["value"])))."',";
                    break;
                case "int" :
                    $insert_values .= intval($v["value"]).",";
                    break;
                case "float":
                    $insert_values .= floatval($v["value"]).",";
                    break;
            }
        }

        $insert_fields = substr($insert_fields, 0, -1);
        $insert_values = substr($insert_values, 0, -1);

        return array(    'FIELD_NAMES'  => $insert_fields,
        'FIELD_VALUES' => $insert_values );
    }

    /**
     * Copile update query string from given data.
     *
     * @param array $data {
     *        ['data_field'] => array( 'data_type' = "type", 'value' = "value" )
     * }
     * @return String - The SET part of query string.
     */
    private function compileUpdateQueryString($data = array()){
        $set_str = "";

        foreach($data as $k => $v){
            $set_str .= "`".$k."`=";

            switch($v["data_type"]){
                case "string" :
                    $set_str .= "'".addslashes(strip_tags(trim($v["value"])))."',";
                    break;
                case "int" :
                    $set_str .= intval($v["value"]).",";
                    break;
                case "float":
                    $set_str .= floatval($v["value"]).",";
                    break;
            }
        }

        $set_str = substr($set_str, 0, -1);

        return $set_str;
    }
    
    /**
     * Executes inseting data to DB to desired table
     *
     * @param String $table - Table name to insert the data to.
     * @param array $data {
     *        ['data_field'] => array( 'data_type' = "type", 'value' = "value" )
     * }
     * @return resource from the query processing.
     */
    public function doInsert($table, $data = array()){
        $insert_string = self::$instance->compile_insert_string($data);
        
        $s = self::$instance->query("INSERT INTO $table({$insert_string['FIELD_NAMES']}) VALUES({$insert_string['FIELD_VALUES']});");
        return $s;
    }
    
    /**
     * Executes updating data in given table in DB.
     *
     * @param String $table - table name to update the data in.
     * @param array $data {
     *        ['data_field'] => array( 'data_type' = "type", 'value' = "value" )
     * }
     * @param String [optional] $where - if set the compiler adds 'WHERE' condition to the query string.
     * @return resource from the query processing.
     */
    public function doUpdate($table, $data, $where){
        $set_str = self::$instance->compile_update_string($data);
        
        $sql = "UPDATE $table SET $set_str";
        if(isset($where) && $where != ""){
            $sql .= " WHERE ".$where;
        }
        
        $s = self::$instance->query($sql);
        return $s;
    }
}
?>



--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
Fally
Дата 8.8.2007, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 17.8.2006
Где: Dahla

Репутация: нет
Всего: 4



Вопрос конкретизируй пожалуйста. Для меня не в порядке лишь то, что он является Синглтоном.


--------------------
Прежде чем задать вопрос на форуме воспользуйтесь поиском.
user posted image
user posted image
PM MAIL   Вверх
ShurikA
Дата 8.8.2007, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Fally
Я имею в виду, главным образом, на тему обращений к переменным.


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
Fally
Дата 8.8.2007, 10:53 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 17.8.2006
Где: Dahla

Репутация: нет
Всего: 4



Общие замечнания таковы: зачем использовать trigger_error(), укогда можно использовать механизм исключений (везде используешь же возможности РНР5). Теперь замечания по коду (всё естественно ИМХО.)

Код

global $coreApi;

Зачем глобальные переменные? можно ведь через constructor injection передавать $coreApi, тем самым, ты сможешь незаметно для скрипта подменить (если понадобиться) объект $coreApi, главное чтобы он имел тот интерфейс который ты используешь в своём классе.

Код

self::$instance->connection_link = @mysql_pconnect($mysqlConf["host"], $mysqlConf["user"], $mysqlConf["pass"]);

Зачем постоянное соединение с мускулом? и собаку лучше убери (во всех вызовах), толку от неё 0, а проблемы могут появиться.
Код

if(isset($result_set) && $result_set != ""){
            $res = $result_set;
        } elseif (self::$instance->query_res != ""){
            $res = self::$instance->query_res;
        } else {
            return 0;
        }


Вот такое встречается несколько раз. Мне кажется проще бы вынести в отдельный метод.

К концу файла появился у меня вопрос... смысл самому моделировать SQL-запросы? Лучше внеси поддержку placeholder'ов в свой класс. А то защиты от SQL Injection я не встретил.

Вроде всё. Повторюсь, что это только ИМХО.

Это сообщение отредактировал(а) Fally - 8.8.2007, 11:16


--------------------
Прежде чем задать вопрос на форуме воспользуйтесь поиском.
user posted image
user posted image
PM MAIL   Вверх
ShurikA
Дата 8.8.2007, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Fally
Во первых огромное тебе спасибо, именно эта критика мне и была нужна.


Цитата(Fally @  8.8.2007,  09:53 Найти цитируемый пост)
Зачем постоянное соединение с мускулом?

Довольно таки данво, проверял как быдет быстрее отрабатывать, так получился самый быстрый вариант. Ну и кроме того, чем же оно мешает, на одну отработку скрипта (того или иного) одно подключение.



Цитата(Fally @  8.8.2007,  09:53 Найти цитируемый пост)
и собаку лучше убери (во всех вызовах), толку от неё 0, а проблемы могут появиться.

Извиняюсь за такой вопрос: что точьно даёт собака? (не спрашивай: зачем я её вообще тогда написал, это исторический так получилось)... smile


Цитата(Fally @  8.8.2007,  09:53 Найти цитируемый пост)
Лучше внеси поддержку placeholder'ов в свой класс. А то защиты от SQL Injection я не встретил.

А вот с этим сейчас и начну заниматься.


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
Fally
Дата 8.8.2007, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 17.8.2006
Где: Dahla

Репутация: нет
Всего: 4



Цитата(ShurikA @  8.8.2007,  13:48 Найти цитируемый пост)
Извиняюсь за такой вопрос: что точьно даёт собака? (не спрашивай: зачем я её вообще тогда написал, это исторический так получилось)... smile

Собака подавляет вывод ошибок в браузер. Т.е. в случае чего ты не увидишь даже E_NOTICE'а о том, что что-то нехорошее произошло....


Цитата(ShurikA @  8.8.2007,  13:48 Найти цитируемый пост)
Довольно таки данво, проверял как быдет быстрее отрабатывать, так получился самый быстрый вариант. Ну и кроме того, чем же оно мешает, на одну отработку скрипта (того или иного) одно подключение.

Самое интересное, что однажды может вывестись  вот такая гадость на экран: "Unable connect to server. Too many connections."

И ещё, не реализовывай этот класс при помощи Singleton. Получаешь статическую зависимость от имени класса. А это не хорошо. Подробнее на эту тему здесь

Это сообщение отредактировал(а) Fally - 8.8.2007, 14:15


--------------------
Прежде чем задать вопрос на форуме воспользуйтесь поиском.
user posted image
user posted image
PM MAIL   Вверх
ShurikA
Дата 8.8.2007, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Fally
А где можно почитать что то конкретное про placeholder? Нащёл я много чего, но путного мало.


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
Fally
Дата 8.8.2007, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 17.8.2006
Где: Dahla

Репутация: нет
Всего: 4



Здесь не только описание плейсхолдеров, но и библиотека написанная Дмитрием Котеровым, кстати просто отличная библиотека. Советую пробовать воспользоваться ей.


--------------------
Прежде чем задать вопрос на форуме воспользуйтесь поиском.
user posted image
user posted image
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса

Внимание: данный раздел предназначен для решения сложных, нестандартных задач.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Для профи | Следующая тема »


 




[ Время генерации скрипта: 0.0797 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.