Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: проектирование классов для работы с бд
 
 автор: psychomc   (26.03.2010 в 11:19)   письмо автору
 
 

только недавно начал изучать ооп

Делаю классы для работы с базами данных.
Есть базовый класс db, который является интерфейсом, и содержит методы connect, error, num_rows и т.п. 2 (пока что) класса db_mysql и db_sqlite реализуют его интерфейс, но методы естественно отличаются (стандартные функции для работы с бд разные). Хочу создать 3 класс db_base_func, который будет содержать базовые простейшие методы выборки и поиска данных, здесь уже функционал один и тот же.
Вопрос собственно в чем: как правильно наследовать классу db_base_func функционал от db_mysql или db_sqlite в зависимости от того, какой из родительских классов используется? То есть как сделать, чтобы db_base_func чтобы он "знал" от какого класса наследовать методы и автоматически их наследовал?

спасибо. если можно, объясните всё на пальцах. и укажите пожалуйста на ошибки если они есть

  Ответить  
 
 автор: Саня   (26.03.2010 в 12:53)   письмо автору
 
   для: psychomc   (26.03.2010 в 11:19)
 

В данном случае лучше сделать абстрактный класс вместо интерфейса. Эта задача идеально ложится на паттерн adapter. Fluent interface тут тоже к месту.

Вот как это может выглядеть:
<?
abstract class DB_Abstract {
  
  protected 
$_query;
  protected 
$_connection;
  
  public function 
fetchAll() {
    
$result = array();
    while ( 
$fe $this->fetch() ) {
      
$result[] = $fe;
    }
    return 
$result;
  }
  
  abstract public function 
connect($params);
  abstract public function 
query($sql);
  abstract public function 
fetch();
  abstract public function 
numRows();
  abstract public function 
escape($str);
  
}

class 
DB_Mysql extends DB_Abstract {
  
  public function 
connect($params) {
    
$this->_connection = @mysql_connect($params['host'], $params['user'], $params['password']);
    if ( 
$this->_connection ) {
      if ( !
mysql_select_db($params['db'], $this->_connection) ) {
        throw new 
Exception('База данных '.$params['db'].' не пашет');
      }
    } else {
      throw new 
Exception('Не могу приконнектиться к СУБД');
    }
  }
  
  public function 
query($sql) {
    if ( 
$this->_connection ) {
      
$this->_query mysql_query($sql$this->_connection);
      if ( !
$this->_query ) {
        throw new 
Exception(mysql_error($this->_connection));
      } else {
        return 
$this;
      }
    } else {
      throw new 
Exception('Соединения с СУБД нет. Запрос не был осуществлён.');
    }
  }
  
  public function 
fetch() {
    if ( 
$this->_query ) {
      return 
mysql_fetch_assoc($this->_query);
    } else {
      throw new 
Exception('Нечего фетчить');
    }
  }
  
  public function 
numRows() {
    
// ...
  
}
  
  public function 
escape($param) {
    if ( 
$this->_connection ) {
      return 
mysql_real_escape_string($param$this->_connection);
    } else {
      return 
mysql_escape_string($param);
    }
  }
  
}

$o = new DB_Mysql;
$o->connect(array('host' => 'l''user' => 'root''password' => '''db' => 'test'));
print_r($o->query("SHOW TABLES")->fetchAll());

  Ответить  
 
 автор: psychomc   (26.03.2010 в 13:08)   письмо автору
 
   для: Саня   (26.03.2010 в 12:53)
 

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

ну допустим создал я еще один класс:
<?php
class DB_Mysqi extends DB_Abstract { }
?>


и замутил соответственно для него все методы абстрактного. далее я хочу создать класс db_base_func, который должен наследовать уже методы того базового, который я в данный момент использую (DB_Mysql или DB_Mysqi). как мне создать класс db_base_func так (или в других классах это сделать), чтобы он сам выбрал быть ему наследником DB_Mysql или DB_Mysqi ?

p.s если что - извиняюсь за тупость

  Ответить  
 
 автор: Саня   (26.03.2010 в 13:14)   письмо автору
 
   для: psychomc   (26.03.2010 в 13:08)
 

В DB_Abstract уже реализованы методы, которые вы хотите выделить в db_base_func (в моём примере это fetchAll()).

  Ответить  
 
 автор: psychomc   (26.03.2010 в 13:59)   письмо автору
 
   для: Саня   (26.03.2010 в 13:14)
 

Саня, дорубил,

но все-таки сделал по-другому

<?php

abstract class db_base_func
{
    function 
test()
    {
        
$this->pr();
    }
}

class 
db_sqlite extends db_base_func implements db
{
    ......
        public function 
pr()
    {
        echo 
"test";
    }
}


// вызов
$db = new db_sqlite("sqlite");

// подключаемся к sclite
$db->connect();

$db->test();
?>


что скажете?

  Ответить  
 
 автор: Саня   (26.03.2010 в 14:17)   письмо автору
 
   для: psychomc   (26.03.2010 в 13:59)
 

Зачем вы разделили интерфейс и базовый класс? Этому есть какое-то обоснование?

  Ответить  
 
 автор: psychomc   (26.03.2010 в 15:03)   письмо автору
 
   для: Саня   (26.03.2010 в 14:17)
 

базовым его сложно назвать.

дело в том, что интерфейс db должны обязательно реализовывать db_mysql и db_sqlite, а db_base_func у меня будет содержать стандартные простейшие операции для работы базой (max. min, count) и т.п. получается что вызывать его методы я буду из объекта производного класса, отдельно их использовать смысла нет. вроде бы очень похоже на ваш вариант, но с использованием интерфейса, и немного сложнее.
есть какие-нибудь ошибки с точки зрения ООП?

  Ответить  
 
 автор: Саня   (26.03.2010 в 15:13)   письмо автору
 
   для: psychomc   (26.03.2010 в 15:03)
 

Если бы были ошибки, PHP сам сказал бы об этом.

  Ответить  
 
 автор: psychomc   (26.03.2010 в 15:25)   письмо автору
 
   для: Саня   (26.03.2010 в 15:13)
 

я понимаю. я имел ввиду другое. как по-вашему, оправдано ли было с моей стороны делать еще один абстрактный класс?

  Ответить  
 
 автор: Саня   (26.03.2010 в 15:30)   письмо автору
 
   для: psychomc   (26.03.2010 в 15:25)
 

Если db_base_func и db не будут использоваться где-то ещё отдельно друг от друга, то такое разделение не имеет смысла.

  Ответить  
 
 автор: psychomc   (26.03.2010 в 15:54)   письмо автору
 
   для: Саня   (26.03.2010 в 15:30)
 

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

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования