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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Классы для работы с MySQL, зацените, пожалуйста 
:(
    Опции темы
newProgrammer
Дата 15.2.2009, 20:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Всем доброго времени суток. 
Сразу оговорюсь, что знания PHP у меня кое-какие есть, только с опытом напряг. Так что сильно не ругайтесь, а будет что сказать, внимательно выслушаю. Написал я тут пару классов для сайта по недвижимости и не знаю правильно ли я все делаю. Конечно все еще очень сыро, но не хотелось бы в начале наделать принципиальных ошибок, противоречащих ООП и PHP в целом.
Вот и сам код:
Код

class mysql {
    private $host = "localhost";
    private $user = "root";
    private $pass = "";
    
    private $cnxn;
    
    public function __construct($db) {
        $this->cnxn = mysql_connect($this->host, $this->user, $this->pass);
        if ($this->cnxn) {
            if (mysql_select_db($db, $this->cnxn)) {
                return true;        
            } else {
                die(mysql_error());
            }
        } else {
            die(mysql_error());    
        }
    }

    // $s - something / Например: '*'
    // $f - from / Например: 'table_name'
    // $w - where_opt / Например: array('type'=>'Апартаменты', 'price_min'=>'100000','price_max'=>'500000') или $_GET...
    // $o - order by / Например: 'price'
    // $d - direction / Например: 'ASC' (по умолчанию) или 'DESC'
    // $l - limit / Например: '5'
    public function select($s, $f, $w=array(), $o='', $d='ASC', $l='') {
        $query = "SELECT " . $s . " FROM `" . $f . "` WHERE 1 = '1'";
        
        if (!empty($w)) {
            foreach ($w as $key => $val) {
                if (strstr($key, "_") == "_min" && substr($key, -4, 4) == "_min") {
                    $query .= " AND `" . substr($key, 0, strlen($key)-4) . "` >= '" . intval($val) . "'";
                } elseif (strstr($key, "_") == "_max" && substr($key, -4, 4) == "_max") {
                    $query .= " AND `" . substr($key, 0, strlen($key)-4) . "` <= '" . intval($val) . "'";
                } else {
                    $query .= " AND `$key` = '$val'";
                }
            }            
        }
        if (!empty($o)) $query .= " ORDER BY `".$o."` $d";
        if (!empty($l)) $query .= " LIMIT $l";
        
        $result = mysql_query($query, $this->cnxn);
        if (mysql_num_rows($result) > 0) {
            while ($row = mysql_fetch_assoc($result)) {
                $array_from_db[] = $row;
            }    
            return $array_from_db;
        } else {
            echo "\t <div class=\"div\">\n"
                ."\t\t<h1 class=\"div_heading\">РЕЗУЛЬТАТ ПО ВАШЕМУ ЗАПРОСУ</h1>\n"
                ."\t\t<p class=\"warn\">По Вашему запросу ничего не найдено!</p>\n"
                ."\t </div>";
        }
    }
}

class item {
    public $id;
    public $thumb;
    public $type;
    public $country;
    public $region;
    public $price;
    public $area;
    public $rooms;
    
    public function __construct($array_from_db) {
        $this->id            = $array_from_db['id'];
        $this->thumb        = $array_from_db['thumb'];
        $this->type        = $array_from_db['type'];
        $this->country    = $array_from_db['country'];
        $this->region        = $array_from_db['region'];
        $this->price        = $array_from_db['price'];
        $this->area        = $array_from_db['area'];
        $this->rooms        = $array_from_db['rooms'];
    }
    
    public function view() {
        $this->price = strrev(chunk_split(strrev($this->price),3, " "));
        $it = "\t <div class='item'>\n"
            . "\t\t<a href='viewdetails.php?id=$this->id'>"
            . "<img src='$this->thumb' class='thumb' alt='' /></a>\n"
            . "\t\t<p><strong>Цена:</strong><span class='price'>$this->price &euro;</span></p>\n"
            . "\t\t<p><strong>Тип:</strong> $this->type</p>\n"
            . "\t\t<p><strong>Страна:</strong> $this->country</p>\n"
            . "\t\t<p><strong>Регион:</strong> $this->region</p>\n"
            . "\t\t<p><strong>Площадь:</strong> $this->area</p>\n";
        $it    .=($this->type == "Земельные участки") ? "\t\t<br />\n" 
            : "\t\t<p><strong>Кол-во комнат:</strong> $this->rooms</p>\n";
        $it    .="\t\t<p class='details'><a href='viewdetails.php?id=$this->id'>подробнее</a></p>\n"
            . "\t </div>";
        return $it;
    }
}

А пользоваться этим можно так:
Код

$mysql = new mysql('db_name');
$a = $mysql->select('*','items',array('price_min'=>'100000','price_max'=>'500000')); // или $a = $mysql->select('*','items',$_GET);

foreach ($a as $val) {
    $item = new item($val);
    echo $item->view();
}


Подскажите пожалуйста что здесь нужно исправить или можно подправить. Заранее благодарю.
PM MAIL   Вверх
Arch1S
Дата 15.2.2009, 21:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 14.1.2008
Где: Беларусь, Гомель

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



переменые в функции select страноватые smile 

вот к примеру моё рукаделие

Код

class DBLayer {
    var $link_id;
    var $query_result;
    var $saved_queries = array();
    var $num_queries = 0;

    function close() {
        if ($this->link_id) {
            if ($this->query_result)
            @mysql_free_result($this->query_result);

            return @mysql_close($this->link_id);
        } else
        return false;
    }

    function DBLayer($db_host, $db_username, $db_password, $db_name) {
        $this->link_id = @mysql_connect($db_host, $db_username, $db_password, true);
        if ($this->link_id)    {
            if (@mysql_select_db($db_name, $this->link_id))
            return $this->link_id;
            else
            echo '<b class=error>Unable to select database. MySQL reported: '.mysql_error().'</b><br>';
        }    else
        echo '<b class=error>Unable to connect to MySQL server. MySQL reported: '.mysql_error().'</b><br>';
    }

    function query($sql) {
        $this->query_result = @mysql_query($sql, $this->link_id);

        if ($this->query_result) {
            ++$this->num_queries;
            return $this->query_result;
        } else {
            return false;
        }
    }

    function result($query_id = 0, $row = 0) {
        return ($query_id) ? @mysql_result($query_id, $row) : false;
    }

    function fetch_assoc($query_id = 0) {
        return ($query_id) ? @mysql_fetch_assoc($query_id) : false;
    }

    function fetch_row($query_id = 0)    {
        return ($query_id) ? @mysql_fetch_row($query_id) : false;
    }

    function num_rows($query_id = 0) {
        return ($query_id) ? @mysql_num_rows($query_id) : false;
    }

    function affected_rows()    {
        return ($this->link_id) ? @mysql_affected_rows($this->link_id) : false;
    }

    function insert_id()    {
        return ($this->link_id) ? @mysql_insert_id($this->link_id) : false;
    }

    function get_num_queries()    {
        return $this->num_queries;
    }

    function get_saved_queries()    {
        return $this->saved_queries;
    }

    function free_result($query_id = false)    {
        return ($query_id) ? @mysql_free_result($query_id) : false;
    }

    function escape($str)    {
        if (function_exists('mysql_real_escape_string'))
        return mysql_real_escape_string($str, $this->link_id);
        else
        return mysql_escape_string($str);
    }

    function delete($from,$where='',$fields='') {
        if (!$from)
        return false;
        else {
            $table = $from;
            $where = ($where != "") ? "WHERE $where" : "";
            return $this->query("DELETE $fields FROM $table $where");
        }
    }

    function update($fields, $table, $where = "") {
        if (!$table)
        return false;
        else {
            if (!is_array($fields))
            $flds = $fields;
            else {
                $flds = '';
                foreach ($fields as $key => $value) {
                    if (!empty ($flds))
                    $flds .= ",";
                    $flds .= $key . "=";
                    $flds .= "'" . $value . "'";
                }
            }
            $where = ($where != "") ? "WHERE $where" : "";
            return $this->query("UPDATE $table SET $flds $where");
        }
    }

    function select($fields = "*", $from = "", $where = "", $orderby = "", $limit = "") {
        if (!$from)
        return false;
        else {
            $table = $from;
            $where = ($where != "") ? "WHERE $where" : "";
            $orderby = ($orderby != "") ? "ORDER BY $orderby " : "";
            $limit = ($limit != "") ? "LIMIT $limit" : "";
            return $this->query("SELECT $fields FROM $table $where $orderby $limit");
        }
    }

}

PM MAIL   Вверх
newProgrammer
Дата 15.2.2009, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Да я и не спорю, что твой класс круче. Мне просто нужно самому разобраться что к чему.

Цитата(Arch1S @  15.2.2009,  21:23 Найти цитируемый пост)
переменые в функции select страноватые

А по-конкретнее можно?


Это сообщение отредактировал(а) newProgrammer - 15.2.2009, 21:43
PM MAIL   Вверх
Acer
Дата 15.2.2009, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



newProgrammer, я бы на твоем месте не делал коннект к базе в конструкторе.
Сделай отдельные методы

bool connect(string $server,string $port,string $usr,string $pwd);
bool disconnect();
bool reconnect();
int exec(string $query) //returns count of affected rows
string value(int $column) //if 'select
PM MAIL   Вверх
bars80080
Дата 15.2.2009, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прапор творюет
****
Награды: 1



Профиль
Группа: Завсегдатай
Сообщений: 12022
Регистрация: 5.12.2007
Где: Königsberg

Репутация: 71
Всего: 315



Цитата(Arch1S @  15.2.2009,  20:23 Найти цитируемый пост)
переменые в функции select страноватые 

а у тебя он очень полезный, как я погляжу. не вижу ничего полезного, кроме как замена стандартных функций своими именами и некоторая автоматизация построения запроса update (хотя почему того же нет для insert - загадка, как и автоматизация экранирования mysql_real_escape_string). 
у newProgrammer, хотя бы возвращается массив после селекта

правда, не понятно, а что больше ничего в классе нет?
PM MAIL WWW   Вверх
Sentox
Дата 15.2.2009, 22:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


как то так
**


Профиль
Группа: Участник
Сообщений: 392
Регистрация: 27.1.2009
Где: Зимбабве

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



Странно во первых видеть в классе оболочке к базе данных вшитый запрос!
Во вторых надо стремиться к меньшему числу дефолтовых аргументов в методах.
Советую почитать про классы оболочки вокруг базы данных или при рефакторинге будет много неприятностей.
Да и наследование в классах тоже придумали не просто так.Разбей на функциональность класс а потом используй его а не вшивай в него всю систему.

Это сообщение отредактировал(а) Sentox - 15.2.2009, 22:59
PM MAIL   Вверх
newProgrammer
Дата 16.2.2009, 00:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Acer @  15.2.2009,  22:42 Найти цитируемый пост)
newProgrammer, я бы на твоем месте не делал коннект к базе в конструкторе.
Что-то подсказывает, что так, действительно, правильнее. Так и сделаю. Но все же, почему нежелательно соединяться с бд в конструкторе?

Цитата(bars80080 @  15.2.2009,  22:51 Найти цитируемый пост)
правда, не понятно, а что больше ничего в классе нет? 
Есть еще несколько методов в классе mysql, но я решил пока не выкладывать, т.к. на длинные посты редко когда отвечают, наверное, читать влом.
Они написаны по этому же принципу - "$key => $val" пары передавать массивами. Например, так:
Код

/**
 * @param string $t - table
 * @param array  $w - where options
 * 
 * @return $result
 */
public function delete($t, $w) {
    $query = "DELETE FROM `".$t."` WHERE 1='1'";
    foreach ($w as $key => $val) {
        if (strstr($key, "_") == "_min" && substr($key, -4, 4) == "_min") {
            $query .= " AND `" . substr($key, 0, strlen($key)-4) . "` >= '" . intval($val) . "'";
        } elseif (strstr($key, "_") == "_max" && substr($key, -4, 4) == "_max") {
            $query .= " AND `" . substr($key, 0, strlen($key)-4) . "` <= '" . intval($val) . "'";
        } else {
            $query .= " AND `$key` = '$val'";
        }
    }
    $result = mysql_query($query, $this->cnxn);
    return $result;
}

Правда, я еще не все продумал; вчера только начал писать. Хотелось бы написать что-то универсальное...


Цитата(Sentox @  15.2.2009,  22:57 Найти цитируемый пост)
Странно во первых видеть в классе оболочке к базе данных вшитый запрос!
Во вторых надо стремиться к меньшему числу дефолтовых аргументов в методах.
Советую почитать про классы оболочки вокруг базы данных или при рефакторинге будет много неприятностей.
Да и наследование в классах тоже придумали не просто так.Разбей на функциональность класс а потом используй его а не вшивай в него всю систему.
Что касается дефолтовых аргументов, то, действительно, как-то некрасиво получается, а с другой стороны, когда надо выбрать из таблицы все без всяких условностей, то прийдется дописывать в параматры пустые кавычки. Насчет всего остального, мне надо почитать и разобраться что есть оболочки и рефакторинг. А так, спасибо за совет smile

PM MAIL   Вверх
Sanchezzz
  Дата 16.2.2009, 08:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 41
Всего: 60



сделай шаблон запросов как в mysqli.

Цитата

Но все же, почему нежелательно соединяться с бд в конструкторе?

тогда с твоим класом будет неудобно работать лучше передавать классу ссылку на Бд типа SetDB($db) GetDB()


Мое мнение: Обертки для БД не очень mysqli круче.






--------------------
Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS.
PM MAIL Skype GTalk   Вверх
awers
Дата 16.2.2009, 10:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 21
Всего: 31



Я вот такое юзаю
Код

<?php
class M_Core_DB{
    static private $instance = null;
    static function getInstance($params = false){
        if (self::$instance == null){
            self::$instance = new M_Core_DB($params);
        }
        return self::$instance;
    }
    public $handler = null;
    protected $stmt = null;
    protected $keys = array();
    protected $meta = null;
    public function __construct($params = false){
        if ($params) $this->connect($params);
    }

    public function connect($params){
        if (!$params) throw new Exception('Params error');
        if (!$this->handler = new mysqli($params['host'],$params['login'],$params['password'],$params['db'])) throw new Exception(mysqli_error());
        if (array_key_exists('encoding',$params)) $this->query("set names ".$params['encoding']); else $this->query("set names UTF8");
    }
    
    public function query($query, $params = false){
        $this->stmt = $this->handler->prepare($query);
        if (!$this->stmt){
            throw new Exception(mysqli_error($this->handler)."\n\n".$query); 
        }
        if ($params){
            if (!is_array($params)) $params = array($params);
            array_unshift($params, str_repeat('s', count($params)));
            call_user_func_array(array($this->stmt, 'bind_param'),$params);
        }
        $this->stmt->execute();
        $this->stmt->close();
    }
    
    
    public function _execute($query,$params = false){
        $this->stmt = $this->handler->prepare($query);
        if (!$this->stmt){
            throw new Exception(mysqli_error($this->handler)."\n\n".$query); 
        }
        if ($params){
            if (!is_array($params)) $params = array($params);
            array_unshift($params, str_repeat('s', count($params)));
            call_user_func_array(array($this->stmt, 'bind_param'),$params);
        }
        $this->stmt->execute();
        
        $this->meta = $this->stmt->result_metadata();
        $this->keys = array();
        foreach ($this->meta->fetch_fields() as $col) $this->keys[] = $col->name;
        $this->stmt->store_result();
    }
    
    public function fetch(){
        $values = array_fill(0, count($this->keys), null);
        $refs = array();
        foreach ($values as $i => &$f) $refs[$i] = &$f;
        
        call_user_func_array(array($this->stmt, 'bind_result'),$values);
        $retval = $this->stmt->fetch();
        if (!$retval){
         $this->stmt->reset();
         return $retval;
        }
        return array_combine($this->keys, $values);
    }
    
    public function fetchAll($query,$params = false){
        $this->_execute($query,$params);
        
        $data = array();
        while ($row = $this->fetch()){
            $data[] = $row;
        }
        return $data;
        
    }
    
    public function fetchOne($query, $params = false){
        $this->_execute($query,$params);
        
        $this->stmt->bind_result($result);
        $this->stmt->fetch();
        $this->stmt->reset();
        return $result;
    }
    
    public function num_rows(){
        return $this->stmt->num_rows();
    }
    
    public function lastInsertId(){
        return $this->handler->insert_id;
    }
}

PM MAIL WWW ICQ Skype   Вверх
Acer
Дата 16.2.2009, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(newProgrammer @ 16.2.2009,  00:01)
Что-то подсказывает, что так, действительно, правильнее. Так и сделаю. Но все же, почему нежелательно соединяться с бд в конструкторе?

Потому, что может возникнуть исключительная ситуация и у тебя обьект умрет до своего создания.

Я считаю не разумным писать методы типа select(), delete() и т.п для запросов.
Ваши статические select'ы выполнят такой запрос?
Код

select a.Luno, a.DateTimeSend, al.name, al.adres, al.syb_branch, b.name
from Base1..Table1 a
join Base2..Table1 al on al.compassname = a.luno
left join Base1..Table2 p on p.problemid = a.id
inner join Base2..branches b on al.syb_branch = b.syb_branch
where a.finished = 0
and a.datetimefixed is null
and a.overdue in (0, 1)
and al.bank = 1
and al.state=1
and p.id is null
and a.status&2<>0
order by b.name

PM MAIL   Вверх
newProgrammer
Дата 16.2.2009, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Acer
Нет, ну такие запросы конечно мой класс не потянет. Теперь-то я понимаю, что проще писать запрос полностью и через переменную вставлять в метод. Тогда действительно в таких методах как select, insert, update нет необходимости. А есть смысл писать такой класс для простеньких запросов?
PM MAIL   Вверх
bars80080
Дата 16.2.2009, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прапор творюет
****
Награды: 1



Профиль
Группа: Завсегдатай
Сообщений: 12022
Регистрация: 5.12.2007
Где: Königsberg

Репутация: 71
Всего: 315



Цитата(newProgrammer @  16.2.2009,  13:43 Найти цитируемый пост)
действительно в таких методах как select, insert, update нет необходимости

в корне не согласен. всё зависит от того, какие цели преследуете
PM MAIL WWW   Вверх
Acer
Дата 16.2.2009, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(newProgrammer @ 16.2.2009,  14:43)
А есть смысл писать такой класс для простеньких запросов?

По моему мнению, нужно стремиться к универсальности и оптимизации. А методы типа select() и т.п. с предопределенной структурой запросов - это просто для самоудовлетворения.
PM MAIL   Вверх
awers
Дата 16.2.2009, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 21
Всего: 31



Цитата(Acer @  16.2.2009,  18:10 Найти цитируемый пост)
По моему мнению, нужно стремиться к универсальности и оптимизации. А методы типа select() и т.п. с предопределенной структурой запросов - это просто для самоудовлетворения.

Для этого надо писать/пользовать ORM
PM MAIL WWW ICQ Skype   Вверх
nerezus
Дата 16.2.2009, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вселенский отказник
****


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

Репутация: 12
Всего: 43



блин, ужас )
Оказывается мой класс был и не таким ужасным =)
Только решение awers понравилось(кстати оно Zend_Db сильно отдает) =)

Только вот смысла в этом нету: проще использовать более функциональный, отлаженный и поддерживаемый стандартный класс =)



--------------------
Сообщество художников Artsociety.ru
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

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


 




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


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

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