Класс для работы с БД

*** скрытое содержание ***
Поддержка транзакций в первую очередь зависит от типа БД. Основной минус Mysqli перед PDO - поддержка только mysql. PDO в свою очередь абстрагирует работу с РСУБД и тем самым поддерживает работу с множеством популярных РСУБД. В случае миграции БД это существенное преимущество.
 
Возьми за основу клас от ДЛЕ. Там реализованы все нужные функции. Удобный, надежный и шустрый. Есть как mqsql так mysqli
 
saen, переносимость это +
MySQLi
хорош для меня мульти запросы, нормальная реализация работы с результатами процедур, есть недочет неудобство очистки результатов процедур, которые создают множественные результаты, ряды записей, но это решенный вопрос (ниже пример ф-я free), СуБД естественно InnoDB (друге типы уже юзаю)
там есть хранимые процедуры, транзакции и некоторые другие фичи.
вот старый класс мой, ноый еще не оттестирован поэтому его не выкладываю...


конструкции инсерт и тп не стоит смотреть, тут они не оптимизированы это конструктор запросов которые автоматически генерируется из данных модуля, те самым я отдаляюсь от человеческого фактора и так же миную sql инъекции...
PHP:
<?php

/**
 * $Revision: 175 $
 * $Author: CrashX $
 * $Date: 2010-02-02 14:27:01 +0600 (Вт, 02 фев 2010)$
 * $LastChangedDate: 2010-10-22 07:54:23 +0700 (Пт, 22 окт 2010) $
 * $Id: mysqli.php 175 2010-10-22 00:54:23Z CrashX $
 * Copyright © CrashX <XSiteCMS@gmail.com>
 * Всі права захищено © CrashX
 */
if (!defined('_SHELL'))
  die();

/**
 * Драйвер MySQLi
 */
class DriverDB {

// версия класса
  var $version = 0.01;
  var $driver = 'MySQLi';
// статус и id соединения
  var $connected = false;
// настройки сервера
  var $server = 'localhost';
  var $user = 'root';
  var $password = null;
  var $database = null;
  var $port = '3306';
  var $persistent = false;
// кодовая страница
  var $collate = 'utf8';
// текст запроса
  var $query = null;
// описание запроса
  var $info = null;
// время запроса
  var $timer = null;
// id запроса для освобождения памяти по указателю
  var $id = null;
// id последнего insert
  var $last = null;
// версионность
  var $mysql = null;
  var $compatibility = '4.0';
// статистика
// ведение журнала
  var $logging = true;
// освобожднеие памяти после выполнения запроса
  var $free = true;
  var $log = array(array('info' => '', 'query' => '', 'error' => '', 'time' => ''));
// кол-во запросов
  var $counter = 0;

  function __construct() {
    $this->db();
  }

  /**
   * Конфигурация соединения
   *
   */
  function db() {
    if (!defined('DB_SERVER'))
      $this->server = 'localhost'; else
      $this->server = DB_SERVER;
    if (!defined('DB_USER'))
      $this->user = 'root'; else
      $this->user = DB_USER;
    if (!defined('DB_PASSWORD'))
      $this->password = null; else
      $this->password = DB_PASSWORD;
    if (!defined('DB_DATABASE'))
      $this->database = null; else
      $this->database = DB_DATABASE;
    if (!defined('DB_PORT'))
      $this->port = 3306; else
      $this->port = DB_PORT;
  }

  /**
   * Подключение к указанной СуБД
   */
  function connect() {
    global $engine;
    $this->timer = $engine->debug->dbtime('on');
    if (!$this->connected):
      //$this->connected = mysqli_init();
      $this->connected = @mysqli_connect($this->server, $this->user, $this->password, $this->database, $this->port);
    endif;
    if ($this->connected):
      $this->mysql = mysqli_get_server_info($this->connected);
      $this->info = "db->connect(" . $this->database . ")";
      $this->query = "SET NAMES '" . $this->collate . "';";
      $this->query();
    /*      $this->info = "db->connect(" . $this->database . ")";
      $this->query = "SET CHARACTER SET '" . $this->collate . "';";
      $this->query();
      $this->info = "db->connect(" . $this->database . ")";
      $this->query = "SET CHARACTER SET '" . $this->collate . "';";
      $this->query();
      $this->info = "db->connect(" . $this->database . ")";
      $this->query = "SET CHARACTER SET '" . $this->collate . "';";
      $this->query();
     *
     */
    else:
      die("Not connect server ! Нет соединения с базой данных: <b>" . $this->database . "</b> !");
    endif;
  }

  function __destruct() {
    //Disconnect
    $this->disconnect();
  }

  /**
   * Enter description here...
   *
   */
  function disconnect() {
    global $engine;
    $this->timer = $engine->debug->dbtime('off');
    if ($this->connected):
      $this->free();
      @mysqli_close($this->connected);
      $this->connected = null;
      $this->database = '';
      $this->log = array();
      $this->log = null;
    endif;
    @mysqli_close();
  }

  function table(&$fields, $key, $prefix) {
    $fields = $prefix . '.' . $fields;
  }

  function fields($fields=array(), $table=null) {

    //$fields = implode(", ", array_keys( $fields));
    foreach ($fields as $field => $value):
      $fields[$field] = $table . "." . $field;
    endforeach;
    return implode(", ", array_values($fields));
  }

  /**
   * Возвращает ID, сгенерированный при последнем INSERT-запросе
   */
  function last() {
    $this->last = mysqli_insert_id($this->connected);
  }

  /**
   * Выполняет запросы и возвращает указатель на данные
   */
  function query() {
    global $engine;
    $this->free ? $this->free() : $this->id = null;
    $this->timer = '';
    if ($this->query != ""):
      $this->id = mysqli_query($this->connected, $this->query);
      //$this->id=mysqli_multi_query($this->connected,$this->query);
      $this->last();
      $this->counter++;
    else:
      return false;
    endif;
    if ($this->logging):
      $this->log();
    endif;
    $this->info = null;
    $this->query = null;
    if (!$this->id):
      $engine->debug->error = 'DEFAULT';
      $engine->debug->dump();
      return false;
    endif;
    return true;
  }

  /**
   * Enter description here...
   */
  function free() {
    while (mysqli_more_results($this->connected)):
      if (mysqli_next_result($this->connected)) :
        $this->id = mysqli_use_result($this->connected);
        @mysqli_free_result($this->id);
      endif;
    endwhile;
    $this->id = null;
  }

  /**
   * Ведение журнала запросов текущего пользователя
   */
  function log() {
    $this->log[$this->counter - 1]['info'] = $this->info;
    $this->log[$this->counter - 1]['query'] = $this->query;
    @$this->log[$this->counter - 1]['error'] = mysqli_errno($this->connected) . ':' . mysqli_error($this->connected);
    @$this->log[$this->counter - 1]['time'] = date('d.m.Y H:i');
  }

  /**
   * Возвращение результата в виде массива
   * @param  MYSQL_ASSOC, MYSQL_NUM, MYSQL_BOTH
   * @return  mixed результат
   */
  function result($type=MYSQL_ASSOC) {
    return @mysqli_fetch_array($this->id, $type);
  }

  /**
   * Возвращает количество рядов результата запроса
   * @return  mixed результат
   */
  function rows() {
    return @mysqli_num_rows($this->id);
  }

  /**
   * Создание текста запроса для выборки записи
   * @param поля в виде ассоциативного массива
   * @param таблица имя
   * @param критерии в виде ассоциативного массива
   * @param доплительные части запроса или директивы
   * @return mixed
   */
  function select($fields=array(), $table=null, $criteria=null) {
// SELECT *ПОЛЯ* FROM *ТАБЛИЦА* WHERE *УСЛОВИЯ* *ДИРЕКТИВЫ*
    $wheres = null;
    $order = null;
    $sort = null;
    $limit = null;
    $join = null;
    $fields = $this->fields($fields, $table);
    if (is_array($criteria)):
      foreach ($criteria as $type => $data):
        switch ($type):
          case "join":
            $join = array();
            foreach ($data as $value):
              $fields .=", " . $this->fields($value['fields'], $value['table']);
              $join[] = $value['type'] . ' ' . $value['table'] . ' ON ' . $table . '.' . $value['link']['a'] . ' = ' . $value['table'] . '.' . $value['link']['b'];
            endforeach;
            $join = implode(" ", $join);
            break;
          case "order": $order = ' ORDER BY ' . $data;
            break;
          case "sort": $sort = ' ' . $data;
            break;
          case "limit": $limit = ' LIMIT 0, ' . $data;
            break;
          case "where":
          default:
            $wheres = array();
            foreach ($data as $column => $value):
              $wheres[] = "{$column}='{$value}'";
            endforeach;
            $wheres = implode(" AND ", $wheres);
            break;
        endswitch;
      endforeach;
    endif;
    // Собираем запрос
    $this->query.="SELECT {$fields} ";
    if (!empty($table)):
      $this->query.=" FROM {$table}";
    endif;
    if (!empty($join)):
      $this->query.=" {$join}";
    endif;
    if (!empty($wheres)):
      $this->query.=" WHERE {$wheres}";
    endif;
    if (!empty($order)):
      $this->query.=$order;
    endif;
    if (!empty($sort)):
      $this->query.=$sort;
    endif;
    if (!empty($limit)):
      $this->query.=$limit;
    endif;
    $this->query.=";";
    return true;
  }

  /**
   * Создание текста запроса для добавления записи
   * @param поля в виде ассоциативного массива
   * @param таблица имя
   */
  function insert($fields=array(), $table=null) {
// INSERT INTO *ТАБЛИЦА* *ПОЛЯ* VALUES *ЗНАЧЕНИЯ*
    $values = array();
    foreach ($fields as $field):
      $values[] = "'{$field}'";
    endforeach;
    $columns = array_keys($fields);
    $this->query.="INSERT INTO {$table} (" . implode(", ", $columns) . ")";
    $this->query.=" VALUES (" . implode(", ", $values) . ")";
    $this->query.=";";
    return true;
  }

  /**
   * Создание текста запроса для обновления записи
   * @param поля в виде ассоциативного массива
   * @param таблица имя
   * @param критерии в виде ассоциативного массива
   * @return mixed
   */
  function update($fields, $table, $criteria) {
// UPDATE *ТАБЛИЦА* SET *ПОЛЯ* WHERE *УСЛОВИЯ*
    $wheres = array();
    $updates = array();
    foreach ($fields as $column => $value):
      $updates[] = "{$column}='{$value}'";
    endforeach;
    $update = implode(", ", $updates);
    foreach ($criteria as $column => $value):
      $wheres[] = "{$column}='{$value}'";
    endforeach;
    $where = implode(" AND ", $wheres);
    $this->query.="UPDATE {$table}";
    $this->query.=" SET {$update}";
    $this->query.=" WHERE {$where}";
    $this->query.=";";
    return true;
  }

  /**
   * Создание текста запроса для удаления записи
   * @param таблица имя
   * @param критерии в виде ассоциативного массива
   * @return mixed
   */
  function delete($table, $criteria) {
// DELETE *?!ПОЛЯ!?* FROM *ТАБЛИЦА* WHERE *УСЛОВИЯ*
    $wheres = array();
    foreach ($criteria as $column => $value):
      $wheres[] = "{$column}='{$value}'";
    endforeach;
    $where = implode(" AND ", $wheres);
    $this->query.="DELETE FROM {$table}";
    $this->query.=" WHERE {$where}";
    $this->query.=";";
    return true;
  }

  function procedure($fields, $procedure, $result='@result') {
//CALL *ИМЯ ПРОЦЕДУРЫ* (*ЗНАЧЕНИЯ*,*РЕЗУЛЬТАТ*)
    $values = array();
    foreach ($fields as $field):
      $values[] = "'{$field}'";
    endforeach;
    $columns = array_keys($fields);
    if ($result && !empty($result))
      $result = ',' . $result;
    $this->query = "CALL " . $procedure . "(" . implode(", ", $values) . $result . ");";
  }

  function import($filename) {
    if (!file_exists($filename)):
      return false;
    endif;
    $fdb = fopen($filename, 'r');
    $sql = '';
    while (!feof($fdb)):
      $sql .=fread($fdb, 1024);
    endwhile;
    fclose($fdb);
    $sql = str_replace("\r", '', $sql);
    $sql = split("\n\n", $sql);
    foreach ($sql as $string):
      $this->query = trim($string, "\r\n; ");
      if (ereg('^\#', $this->query)

        )continue;
      // strip out comments and \n for mysql 3.x
      if ($this->mysql < $this->compatibility):
        $this->query = preg_replace("~COMMENT.*[^']?'.*[^']?'~", "", $this->query);
        $this->query = str_replace('\r', "", $this->query);
        $this->query = str_replace('\n', "", $this->query);
      endif;

      $this->info = 'db->import(' . $filename . ')';
      $this->query();
    endforeach;
  }

}
?>
 
Покажи пример мультизапроса, мне интересно стало
 
  • Заблокирован
  • #16
PHP:
<?php

class MySQLDatabase {

    private $connection;
    private $magic_quotes_active;
    private $real_escape_string_ex;
    public $query_count = 0;
    public $last_querry;

    function __construct() {
        $this->open_connection();
        $this->query("SET NAMES CP1251");
        $this->magic_quotes_active = get_magic_quotes_gpc();
        $this->real_escape_string_ex = function_exists("mysql_real_escape_string");
    }

//основные функции
    private function open_connection() {
        $this->connection = mysql_connect(DB_SERVER, DB_USER, DB_PASS);
        if (!$this->connection) {
            die("Ошибка подключения к базе: " . mysql_error());
        } else {
            $db_select = mysql_select_db(DB_NAME, $this->connection);
            if (!$db_select) {
                die("Ошибка при выборе базы: " . mysql_error());
            }
        }
    }

    private function close_connection() {
        if (isset($this->connection)) {
            mysql_close($this->connection);
            unset($this->connection);
        }
    }

    public function getQuery_count() {
        return $this->query_count;
    }

    public function query($sql) {
        $this->query_count += 1;
        $this->last_querry = $sql;
        $result = mysql_query($sql, $this->connection);
        $this->confirm_query($result);
        return $result;
    }

//нейтральные функции
    public function escape_value($value) {
        if ($this->real_escape_string_ex) {
            if ($this->magic_quotes_active) {
                $value = stripslashes($value);
            }
            $value = mysql_real_escape_string($value);
        } else {
            if (!$this->magic_quotes_active) {
                $value = addslashes($value);
            }
        }
        return $value;
    }

    public function queryArray($result) {
        while ($array[] = $this->fetch_array($result)
            );
    }

    public function fetch_array($result) {
        return mysql_fetch_array($result);
    }

    private function confirm_query($result) {
        if (!$result) {
            $error = "Ошибка при запросе в базу" . mysql_error() . "<br />";
            $error .= "Краш-запрос: " . $this->last_querry;
            die($error);
        }
    }

    public function num_rows($result) {
        return mysql_num_rows($result);
    }

    public function insert_id() {
        return mysql_insert_id($this->connection);
    }

    public function affected_rows() {
        return mysql_affected_rows($this->connection);
    }

}

$db = new MySQLDatabase();
?>
 
Я бы рекомендовал DBSimple от dklab.ru Прост, функционал в норме, есть биндинг переменных, дока на русском.
 
chang

А это смотря с чем сравнивать. У меня не было еще жалоб. Вот вы с чем сравнивали?

upd.
Спасибо за ссылку на тест, познавательно.
 
я ни с чем не сравнивал .. а просто на тест взглянул ...

но даже если логично прикинуть то PDO - это библиотека написанная на си... уже откомпиленна... + на более низком СИ можно организовать более быстрые способы доступа к данными и манипуляцию ими ... пхп интерпретатору ее нужно "взять" и использовать

все остальное же - это пхп библиотеки... которые постоянно ( или почти постоянно) интерпретируются ... т.е. интерпретатор посимвольно читает то что в них написанное и пытается "разгадать" что от него хотят и это выполнить ...
хранится это все в пхп-шных массивах которые явно уступаю по скорости доступа Си-шным структурам данным ...

так что, мое личное мнение - везде где можно нужно использовать PDO. Если уже не хватает его мощностей - то тогда что-то настроенное поверх него. Скоростью выполнения всегда можно поступиться в пользу скорости разработки.
 
Назад
Сверху