Класс для MySQL

kabachok

Новичок
Класс для MySQL

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

От класса требуются стандартные возможности класса mysqli + то что я написал выше.
 

Farsh

~ on ~ high ~ wave ~
А, понял, что нужно )
Здесь можно даж без всякого ооп обойтись , обычной функцией .. Делаешь запрос -> проверка на экземпляр mysqli ( если нет -> создание ) -> выполнение запроса .
 

kabachok

Новичок
Автор оригинала: Farsh
А, понял, что нужно )
Здесь можно даж без всякого ооп обойтись , обычной функцией .. Делаешь запрос -> проверка на экземпляр mysqli ( если нет -> создание ) -> выполнение запроса .
и как в таком случае будет выглядеть запрос?
мне кажется что нужно как-то обернуть основной класс mysqli и в нем добавить эту самую проверку экземпляра.
Такое возможно сделать?
 

fixxxer

К.О.
Партнер клуба
rtfm: singleton, lazy load

-~{}~ 24.09.08 23:24:

условный пример без классов:
PHP:
function query($q) {
    static $dbconn;
    if (!isset($dbconn)) $dbconn = mysql_connect();
    return mysql_query($q);
}
 

kabachok

Новичок
Моё серое вещество (мозг) родило сиё извращение:

PHP:
Class DB extends mysqli {

var $db_server='localhost';
var $db_user='user';
var $db_pass='pass';
var $db_name='db';
var $mysqli;

function query($guery) {

if (!$this->mysqli) { 
$this->mysqli = new mysqli($this->db_server,$this->db_user,$this->db_pass,$this->db_name); 
$this->mysqli->query("SET NAMES utf8;");
echo 'connect';
}

return $this->mysqli->query($guery);
}

}

$mysqli = new DB(); 

    $result = $mysqli->query("SELECT SQL_CACHE HIGH_PRIORITY COUNT(`site_id`) AS `sites_c_rating`
FROM `sites` 
WHERE `site_c_rating`>0 ;");

    $result = $mysqli->query("SELECT SQL_CACHE HIGH_PRIORITY COUNT(`site_id`) AS `sites_c_rating`
FROM `sites` 
WHERE `site_c_rating`>0 ;");
и это извращение работает :eek: и вроди даже так как мне нужно :D

если закомментировать запросы, то connect не выводится, при двух запросах выводится один connect.

стоит ли юзать подобную реализацию?
Может кто нибудь подправит некоторые моменты?

Строго не судите, с классами я на Вы.
 

dimagolov

Новичок
kabachok, у тебя вроде не php 4. тогда почему var? кроме того, не нужно тебе наследование, совсем не нужно. кроме того, ты его даже никак не используешь.
 

kabachok

Новичок
Автор оригинала: dimagolov
kabachok, у тебя вроде не php 4. тогда почему var? кроме того, не нужно тебе наследование, совсем не нужно. кроме того, ты его даже никак не используешь.
а почему не нужно? я подменил одну функцию класса, остальные то я буду использовать, просто в примере я не показал их.
Может Вы подправите как нужно?

-~{}~ 25.09.08 01:54:

PHP:
$mysqli = new DB(); 

    $result = $mysqli->query("SELECT SQL_CACHE HIGH_PRIORITY COUNT(`site_id`) AS `sites_c_rating`
FROM `sites` 
WHERE `site_c_rating`>0 ;");

    $row = $result->fetch_array();
$sites_c_rating=(int)$row['sites_c_rating'];

echo $sites_c_rating;
такой пример отрабатывается, и насколько я понимаю используется наследованный метод fetch_array(). или я не прав?

-~{}~ 25.09.08 02:04:

Автор оригинала: dimagolov
kabachok, у тебя вроде не php 4. тогда почему var?
var нужно заменить на public, правильно я понял?
 

fixxxer

К.О.
Партнер клуба
Наследование и делегирование сразу - это что-то не то ;)
Я бы как то так сделал

PHP:
class Db {

    protected $conn;
    protected $params;

    public function __construct($host, $user, $passwd='', $dbname=NULL) {
        $this->params = compact('host', 'user', 'passwd', 'dbname');
    }

    protected function doConnect() {
        extract($this->params);
        $this->conn = new mysqli($host, $user, $passwd, $dbname);
        if (!is_object($this->conn) || $this->conn->connect_error) {
            $this->conn = NULL;
            throw new Exception("Database connection failed: " . $this->conn->connect_error);
        }
        return $this->conn;
    }

    public function __call($method, $args) {
        if (!isset($this->conn)) $this->doConnect();
        if (method_exists($this->conn, $method)) {
            return call_user_func_array( array($this->conn, $method), $args);
        }
        throw new Exception("Unknown method: " . $method);
    }   
    
}
То, что не для всех методов mysqli нужно иметь соединение, и оптимальнее сначала делать объект, а потом при необходимости коннект, тут не учтено, это домашнее задание :D
 

kabachok

Новичок
fixxxer
Из твоего примера я ничего не понял, можно прокомментировать?

Так при создании обьекта mysqli сразу происходит подключение к базе
 

fixxxer

К.О.
Партнер клуба
можно
делаем своего рода прокси-класс
в конструкторе он просто запоминает параметры соединения
дальше мы предполагаем что любой вызов метода класса подразумевает что надо создать соединение
все вызовы идут в __call, читай в мане, это magic method
там если еще не создан объект mysqi мы его создаем и дергаем его метод с аргументами
внешне все выглядит как обычная работа с mysqli просто вместо new mysqli делаем new db

недостатков три - не все вызовы mysqli требуют наличия соединения (наверное; я с ним не работал); следует учитывать что параметры соеднения надо передавать строго в конструкторе; doConnect() делается до проверки наличия метода и в случае ошибочного вызова соединение все равно будет сделано (но это мелочь)
 

kabachok

Новичок
fixxxer
с этим понятно, а еще вы не могли бы пояснить что в моем варианте плохого?
 

Farsh

~ on ~ high ~ wave ~
Потому, что получается 2 экземпляра класса mysqli, и смысл обертки теряется .

-~{}~ 25.09.08 16:02:

Используй первый пример fixxxer'a и не парь моск )
 

kabachok

Новичок
Автор оригинала: Farsh
Потому, что получается 2 экземпляра класса mysqli, и смысл обертки теряется .

-~{}~ 25.09.08 16:02:

Используй первый пример fixxxer'a и не парь моск )
Вот теперь мне стало ясно :) убрал extends mysqli из своего вариантра.

Первый пример мне не очень нравится.

-~{}~ 25.09.08 18:14:

PHP:
    public function __call($method, $args) { 
        if (!isset($this->conn)) $this->doConnect(); 
        if (method_exists($this->conn, $method)) { 
            return call_user_func_array( array($this->conn, $method), $args); 
        } 
        throw new Exception("Unknown method: " . $method); 
    }
этот метод будет автоматически вызваться при каждом обращении к объекту?
 

HraKK

Мудак
Команда форума
man читать не пробовали? Или вы любите танцы с бубном?
 

HraKK

Мудак
Команда форума
действительно нету.
Ладно __call вызывается каждый раз при обращении к несуществующему методу обьекта.
 

kabachok

Новичок
Автор оригинала: fixxxer
http://ru.php.net/manual/en/language.oop5.overloading.php

представляете я написал на php.net в поиске __call и нашел в 2 клика. утрудился, жуть!
понимаю, много сложнее писать без подковырок и упреков ;)

-~{}~ 02.10.08 02:19:

fixxxer
наконец-то дошли руки до внедрения в проект, и столкнулся с проблемой.
Использую отчасти вашу реализацию, так вот не работают переменные типа $mysqli->affected_rows, $mysqli->num_rows
предполагаю что не работают из-за того что их в классе просто нет.

сделал следующее:

PHP:
Class DB {

    protected $conn; 
    protected $params;
    protected $tpl;
    
    public $queris;
    
    public $affected_rows;
    public $num_rows;

    public function __construct($host, $user, $passwd='', $dbname=NULL, $tpl) { 
        $this->params = compact('host', 'user', 'passwd', 'dbname');
        $this->tpl = $tpl; 
    }
    
    protected function doConnect() {
        extract($this->params); 
        $this->conn = new mysqli($host, $user, $passwd, $dbname); 
        if (!is_object($this->conn) || $this->conn->connect_error) { 
            $this->conn = NULL; 
            
            $this->tpl->assign('page_title','DB Error');
            $this->tpl->assign('db_error',$this->conn->connect_error());
            $this->tpl->caching = true;
            $this->tpl->display('db_error.tpl');
            exit;
        }
        $this->conn->query("SET NAMES utf8;"); 
        return $this->conn; 
    }

    function query($guery) {
      if (!isset($this->conn)) $this->doConnect();
    
      ++$this->queris;

  return $this->conn->query($guery);
      $this->affected_rows=$this->conn->affected_rows;
      $this->num_rows=$this->conn->num_rows;
    }

    public function __call($method, $args) { 
        if (!isset($this->conn)) $this->doConnect(); 
        if (method_exists($this->conn, $method)) { 
            return call_user_func_array( array($this->conn, $method), $args); 
        } 
        throw new Exception("Unknown method: " . $method); 
    }   

}

$mysqli = new DB($db_server,$db_user,$db_pass,$db_name,$tpl);
но этот вариант так же не работает, подскажите где я не правильно делаю.
 

fixxxer

К.О.
Партнер клуба
я верно понимаю что

$mysqli->affected_rows, $mysqli->num_rows

это переменные класса?

тогда надо по аналогии с __call использовать __get
 
Сверху