Автор Тема: Помогите с ООП  (Прочитано 17635 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Алексей

  • Фанат форума
  • Постоялец
  • ***
  • Сообщений: 176
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Помогите с ООП
« : 28 Октября 2004, 19:10:54 »
У меня цель - написать класс для гостевой книги работающей с мускулом.
Изучил ООП в 4 версии. Собственно, изучать то там толком нечего... да вот только не могу я класс создать. ну не представляю, как это правильно сделать. Начинаю делать - получается какая то смесь ООП с процедурным. Бредятина...

вот какая то фигня получилась:


class db{
	
var 
$lnk;
	

	
//Соеденение с MySql, выбор базы данных, возвращение идентификатора ссылки
	
function 
db($server$username$password$db){
	
	
$this->lnk mysql_connect($server$username$password) or die("Не могу соедениться");
	
	
mysql_select_db($db$this->lnk) or die("Не могу выбрать базу $db");
	
}
	

	
/* Запрос к БД, возвращение массив многомерный вида
Array
(
    [user_id] => Array
        (
            [0] => 12
            [1] => 45
        )

    [user_name] => Array
        (
            [0] => "Вова"
            [1] => "Костя"
        )
...
*/
function db_get_rezult($query){
	
	
$result mysql_query($query$this->lnk) or die();
	
	
	
if(
mysql_num_rows($result)>0){
	
	
	
	
while(
$array mysql_fetch_assoc($result)){
	
	
	
	
	
foreach(
$array as $key=>$value)
	
	
	
	
	
	
$HTML[$key][] = $value;
	
	
	
	
}
	
	
	
return 
$HTML;
	
	
	
}
	
	
return 
false;
	
}
	

	
//количество записей в гостевой возвращает...
	
function 
db_count_query(){
	
	
$c mysql_fetch_row(mysql_query("SELECT COUNT(*) FROM gb"$this->lnk));
	
	
return 
$c[0];
	
}
	
//закрытие соеденения
	
function 
close(){
	
	
@
mysql_close($this->lnk);
	
}
}



	

$myDb = new db($server$username$password$db);
	

$HTML $myDb->db_get_rezult("SELECT .........");
	

$c $myDb->db_count_query();


ну и непойму что делать дальше... т.е. как то неуклюже всё это. надо данные теперь обрабатывать, массив $HTML - как это делать?... и вообще, мне кажется я всё в корне не верно делаю...

Оффлайн Меняздесьдавнонет

  • новичЕк
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 5698
  • +0/-0
  • 2
    • Просмотр профиля
    • http://
Помогите с ООП
« Ответ #1 : 28 Октября 2004, 19:33:09 »
Нормально ты все делаешь.
вот только функцию db_count_query() надо, конечно, выкинуть оттуда.
ведь ее функционал прекрасно покрывается функцией db_get_rezult

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

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

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

Оффлайн Макс

  • vir magni ingenii
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3534
  • +0/-0
  • 2
    • Просмотр профиля
Помогите с ООП
« Ответ #2 : 28 Октября 2004, 23:28:39 »
Алексей
что должен делать твой класс ?
Если абстракция от базы данных или упрощенная работа с MySQL - то это один класс.
Если управление записями - это другой класс.

Если тебе надо и то и другое, то тебе надо 2 класса, а не один.

По твоему классу замечение только одно - имя таблицы вынеси в переменную класса:
var $table = "gb";
First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack. ( George Carrette )

Оффлайн Алексей

  • Фанат форума
  • Постоялец
  • ***
  • Сообщений: 176
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Помогите с ООП
« Ответ #3 : 29 Октября 2004, 08:39:03 »
Цитировать
RomikChef:
ты делаешь какой-то очень странный массив.

ну..это для шаблона.
Цитировать
RomikChef:
массив $HTML здесь же обрабатывать не надо.

а где надо?
Цитировать
Макс:
что должен делать твой класс ?

всё, что нужно с простейшей гостевой - вносить запись, получать результат, обрабатывать результат (htmlspecialchars etc) делать отстраничиватель и всё остальное.

Суть в том, что я не знаю, как правильно и сколько именно нужно сделать классов.

Вообще то хотел сделать один супер-класс, который манипулировал бы с гостевой, но как я понимаю, так не делают, а нужно сделать общий класс для работы с БД, класс для вывода записей, класс для отстраничивателя и т.д. Так?

Оффлайн Меняздесьдавнонет

  • новичЕк
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 5698
  • +0/-0
  • 2
    • Просмотр профиля
    • http://
Помогите с ООП
« Ответ #4 : 29 Октября 2004, 10:52:57 »
Цитировать
Алексей:
ну..это для шаблона.

для шаблона он все равно очень странный.

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

Но если так уж хочется - напиши два класса - 1 дб, а второй - гостевая, расширяющий первы.
Будет у тебя супер крутое ооп приложение.

лабу-то когда сдавать?

Оффлайн Меняздесьдавнонет

  • новичЕк
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 5698
  • +0/-0
  • 2
    • Просмотр профиля
    • http://
Помогите с ООП
« Ответ #5 : 29 Октября 2004, 10:55:11 »
похоже, ты и с процедурным гостевую не очень хорошо представляешь, как написать, то есть, твоя задача усложняется в два раза.

Оффлайн Алексей

  • Фанат форума
  • Постоялец
  • ***
  • Сообщений: 176
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Помогите с ООП
« Ответ #6 : 29 Октября 2004, 11:24:46 »
Цитировать
RomikChef:
Но с другой стороны,Ю в веб-программировании классы- вещь весьма спорная, и в гостевой притянута за уши.

тут дело в том, что я пишу эту гостевую не ради самой гостевой, а ради изучения ООП.
Цитировать
RomikChef:
лабу-то когда сдавать?

какую лабу? :-/

Цитировать
RomikChef:
для шаблона он все равно очень странный.

я знаю, что в меня щас камни полетят, но я делаю так:

<?
	
for(
$i=0$i<$fornum$i++){
	
?>
<strong>Имя:</strong> <a href="/users/<?=$HTML["user_id"][$i]?>.html"  onclick="infoWindow(this.href); return false;"><?=$HTML["user_name"][$i]?></a>


<strong>Комментарий:</strong> <?=$HTML["user_message"][$i]?>

<small class="color_4"><?=$HTML["date"][$i]?></small><hr />

<?
	
}
	
?>

Оффлайн Макс

  • vir magni ingenii
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3534
  • +0/-0
  • 2
    • Просмотр профиля
Помогите с ООП
« Ответ #7 : 29 Октября 2004, 11:48:58 »
Если английский знаешь - то поищи информацию про паттерн DAO
Цитировать
Алексей:
вносить запись, получать результат, обрабатывать результат (htmlspecialchars etc) делать отстраничиватель и всё остальное.

никаких "все остальное". Должен быть четкий список, что будет делать класс.

Можно сделать 2 или 3 класса.
1. Работа с MySQL
2. Работа с одной записью (добавление/редактирование/удаление/проверка)
3. Работа со списком записей (постраничный вывод, сортировка)

2 и 3 можно объединить в один класс.
First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack. ( George Carrette )

Оффлайн Алексей

  • Фанат форума
  • Постоялец
  • ***
  • Сообщений: 176
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Помогите с ООП
« Ответ #8 : 29 Октября 2004, 12:25:42 »
Цитировать
Макс:
1. Работа с MySQL

что ты под этим подразумеваешь? что значит работа с майскёл?

Цитировать
Макс:
2. Работа с одной записью (добавление/редактирование/удаление/проверка)

хм.. я чес. говоря с бооооольштим трудом представляю, как в класс можно запихнуть "добавление/редактирование/удаление/проверка" записей... вот смотри, это проверка информации перед внесением в базу:


if($_SERVER["REQUEST_METHOD"]=="POST")
{
	

	
foreach(
$_POST as $key=>$value)
	
	
$_POST[$key]=clearPost($value);
	

	
if(!
$user_is_login)
	
	
$err .= "<li>Вы не являетесь зарегестрированным пользователем.
Вероятно, Вы начинающий кулхацкер? Хе-хе...</li>"
;
	
if(!
$_POST["user_message"])
	
	
$err .= "<li>Вы не ввели сообщение.</li>";
	
else if(
$t bad_max_length($_POST["user_message"],$ml_user_message))
	
	
$err .= "<li>Введённое Вами сообщение слишком велико. Удалите $t символов.</li>";
	
if(
is_referer())
	
	
$err .= "<li>Форма, с которой отправляется запрос, должна находиться на сервере.</li>";
	

	
//Ошибок нет
	
if(!
$err){
	
//Только тут используется ООП...
	
$myDb = new db;
	
$myDb->db_query("INSERT INTO gb VALUES(NULL, $_COOKIE[user_id], \'".adds($_POST["user_message"])."\', NOW(), \'\', 0)");
	
$myDb->close();
	
header("Location: ./?".time());
	
exit;
	
}
	
else 
$err "<div class=\\"alert\\">Ошибка!<ul class=\\"error_mesage\\">$err</ul></div>";
} else 
$_POST["user_message"] = "";

не нужно вникать в этот код. Просто это мой наглядный пример - смесь ООП с структ. программированием. Просто я не могу понять, как можно все эти проверки в класс запихнуть.. да и стоит ли так делать?

Оффлайн Меняздесьдавнонет

  • новичЕк
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 5698
  • +0/-0
  • 2
    • Просмотр профиля
    • http://
Помогите с ООП
« Ответ #9 : 29 Октября 2004, 12:34:13 »
Этот код оформляется метод класса, скажем, Write.

Но, по хорошему, как мне кажется, на гостевой ООП изучать неправильно..

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

Оффлайн Алексей

  • Фанат форума
  • Постоялец
  • ***
  • Сообщений: 176
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Помогите с ООП
« Ответ #10 : 29 Октября 2004, 13:59:01 »
Цитировать
RomikChef:
Этот код оформляется метод класса, скажем, Write.

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

Оффлайн Меняздесьдавнонет

  • новичЕк
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 5698
  • +0/-0
  • 2
    • Просмотр профиля
    • http://
Помогите с ООП
« Ответ #11 : 29 Октября 2004, 14:13:31 »
скажем так.
Для гостевой даже и функции-то не нужны.

Классы, как и функции - это модули. Кубики. Для многократного использования.
В частности, кубик для работы с базой можно написать, и он пригодится для написания гостевой, новостей и чего угодно.

Писать же целиком гостевую с использованием ООП имеет смысл тому, кто все всегда так пишет.

Оффлайн Макс

  • vir magni ingenii
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3534
  • +0/-0
  • 2
    • Просмотр профиля
Помогите с ООП
« Ответ #12 : 29 Октября 2004, 14:27:43 »
Цитировать
Алексей:
что ты под этим подразумеваешь? что значит работа с майскёл?

Если тебе не нужна работа с несколькими СУБД (абстрактный доступ к базам данных), то класс для работы с БД ИМХО нужен лишь для упрщения твоей работы. В класс вынести некоторые часто используемые операции. Например :
 - получить одно значение из таблицы
 - получить одну запись из таблицы.
....
В качестве примера я могу привести лишь класс для ПХП5.
Можешь посмотреть там идеи и реализовать что-то похожее для ПХП4

Цитировать
RomikChef:
Макс, ты можешь привести пример нормального приложения, в котором клсссы, кроме дб, действительно нужны?
Если ключевыми словами в твоем вопросе являются "действительно нужны", то нет, не могу. Я сейчас сяду писать текст, как у меня используются классы, но  он будет большой (не знаю, насколько заумный)
First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack. ( George Carrette )

Оффлайн Макс

  • vir magni ingenii
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3534
  • +0/-0
  • 2
    • Просмотр профиля
Помогите с ООП
« Ответ #13 : 29 Октября 2004, 16:31:16 »
Итак, как у меня используютя классы.

Я не буду описывать работу с БД. У меня пока используется adodb (статья по нему есть на detail.phpclub.ru).
Также я пропущу работу с классом шаблонизатора (pear::html::teamplate::sigma) - работа с ним принципиально ничем не отличается от работы с другими шаблонизаторами.

Первое о чем я упомяну - это регистр объектов.
Изнутри, регистр объектов (ObjectRegistry) представляет собой массив, в котором хранятся ссылки
на объекты.
Зачем это нужно ? Допустим у нас класс, которому нужен доступ к классу базы данных и шаблонизатору.
Если не использовать global (а я его принципиальноне использую), то эти объекты
можно получить лишь передав их через конструктор или соответствующий метод.
$object = new SomeObject($conn$tmpl);
Если допустим появятся еще и настройки (почему у меня настройки в своем классе объяснять не хочу - это необязательное решение)
то надо будет
 1. переписать класс, чтобы он принимал 3 параметра
 2. переписать код в котром используется класс и добавить еще один параметр:
$object = new SomeObject($conn$tmpl$settings);
Мало того, что мы кучу вего написали, так еще и конструктор стал получать кучу параметров

В случае с ObjectRegistry у меня всегда вызов конструктора выглядит :
$object = new SomeObject($registry);

Хотя основная его цель - позволить объектам взаимодействовать друг с другом.

Теперь переходим к основной части.
Допустим на сайте есть Новости, Регистрация, Статьи.
То есть на сайте есть такие сущности как новость, пользователь и статья
У этих 3-х сущностей есть общее поведение:
 - добавление (проверяем входные данные, если все Ок, генерируем INSERT-запрос и выполняем его)
 - уделаение (тут все ясно)
 - редактирование (очень похоже на добавление только UPDATE-запрос генерируется)
Но есть и различия. Например у разных сущностей разные проверки.
Также некоторые сущности имеют еще и дополнительное поведение (например у юзера есть авторизация, "Вспомнить пароль")

У меня есть абстрактный класс DBObject.
В его задачу входит работа с сущностями - проверка/добавление/редактирование/удаление и т.д.
Рассмотрим добавление сущности в таблицу.
Здесь можно выделить такие этапы:
1. Получение данных из POST-запроса
2. Проверка данных
3. Подготовка данных к добавлению
Например при регистрации юзера надо пароль зашифровать.
Также здесь к данным добавляется время добавления (если в таблице есть такое поле).
Также на этом этапе при регистрации юзера генерируется случайное число, которое шлется ему на e-mail для подтверждения регистрации
Вобщем здесь генерируются некоторые значения для полей, которых нет в реальной форме добавления.
4. Выполняем INSERT-запрос и получаем идентификатор новой записи
5. Еще что-нибудь
Например если юзер закачивал картинку, то она из временной папки копируется в папку с картинками и получает имя
$user_id.jpeg
Также здесь можно выполнить некоторые другие SQL-запросы, если например сущность
хранится в нескольких таблицах. Например юзер указал свои интересы и здесь они записываются в отдельную таблицу (связь "многие-ко-многим")

Метод add() класса DBObjects выполняет вставку записи. Выглядит он так (упрощенно) :

   
function add() {
      
$this->loadFromPost();     // загружаем данные из ПОСТ
      
$this->checkData(\'add\');   // проверяем
      if (sizeof($this->errors) == 0) { // если нет ошибок
         // if data OK
         $this->prepareData(\'add\');  // подготавливаем данные в вставке
         // генерируем INSERT-запрос (это фича adodb)
         $res = $this->conn->Execute("SELECT * FROM ".$this->table." WHERE ".$this->id_name." = -1");
         $sql = $this->conn->GetInsertSQL($res, $this->fields);
         // запрос сгенерировали, теперь выполняем
         $this->conn->Execute($sql);
         $this->id = $this->conn->Insert_ID(); 
         $this->onAdd(); // вызывается после вставки данных
         return $this->id;
      } else {
         return false;
      }
   }

я убрал некоторые проверки, чтобы код был более понятным.
У трех упомянутых сущностей только 3 метода (используемые в этом коде) могут
различаться : $this->onAdd(), $this->prepareData(), $this->checkData()
Именно эти методы надо будет переопределить в наследниках (можно и не переопределять если они не нужны)

Класс DBObject имеет такие методы (только основные)
setID($id) - получает ИД объекта, делает запрос к БД и получает данные о сущности
add() - описан выше
edit() - редактирование объекта
delete() - удаление объекта
Эти объекты переопределять не надо
onAdd(), onEdit(), onDelete() - эти объекты можно переопределить
checkData() - проверка данных (тоже переопределяется)
prepareData() - подготовка данных (тоже переопределяется)
--------
Как все это работает.
Делаем наследника (для этого есть генератор), ручкам пишем методы
checkData(), prepareData() + события on*() а в скриптах код выглядит :


добавление

      $news 
= new News($reg); // $reg == ObjectRegistry
      
if ($_SERVER[\'REQUEST_METHOD\'] == \'POST\') {
         if ($news->add()) {
            // новость добавлена
            _header(\'news.php?\'.SID);
            exit;
         } else {
            // произошла ошибка
            $errors = $news->errors;
            $tpl->setVariable(er_convert($errors)); // передаем ошибку в шаблон
         }
      }
      /// тут работа с шаблонизатором

редактирование

      $cat 
= new Category($reg);
      
// идентификатор категории, которую редактируем
      
$cat_id max(0intval($_REQUEST[\'cat_id\']));
      if ($_SERVER[\'REQUEST_METHOD\'] == \'POST\') {
         $cat->setID($cat_id); 
         if ($cat->edit()) {
            // если ошибок нет
            _header("cats.php?".SID);
            exit;
         } else {
            $errors = $cat->errors;
            // передаем ошибки шаблону
            $tpl->setVariable(er_convert($errors));
            // передаем введенные данные шаблону
            $tpl->setVariables($cat->getFields()) //
         }
      } else {
         $cat->setID($cat_id); 
         // передаем шаблону данные, которые надо отредактировать
         $tpl->setVariables($cat->getFields()) //
      }

Удаление

      $cat_id 
max(0intval($_GET[\'cat_id\']));
      $cat = new Category($reg);
      $cat->setID($cat_id);
      $cat->delete();
      _header(\'cats.php?\'.SID);


Если используемые методы не предоставляют нужную мне функциональность, то
я могу дописать метод или реализовать его без класса (я на классах не помешан)

Позволяет ли этот подход повторно использовать код ?
Да позволяет.
Написал класс User. Сделал наследника, чуть модфицировал - получил класс Admin.
Сделал класс для управления файлами (с upload-ом), сделал наследника, чуть модифицировал - получил класс для управления только изображениями.

Пример, как создается наследник.
Сначало создаем ini-файл. Примерно такого типа

[db]
table = tgp_links # название таблицы
id_name = link_id # имя первичного ключа

[class]
name = Link # имя класса
extends = DBObject # имя родительского класса

[fields] # это поля и фильтры для них
cat_id = intval
url =
title = htmlspecialchars
description = "htmlspecialchars|nl2br"

По этому ini-файлу генератор генерирует класс.
Дальше ручками надо написать нужные методы:

   
// проверка просто для примера
   
function checkData($mode=\'add\') {
      if (empty($this->fields[\'title\'])) {
         $this->errors[\'title\'] = _("Title is empty");
      } 
      if (empty($this->fields[\'description\'])) {
         $this->errors[\'description\'] = _("Description is empty");
      } 
      if (empty($this->fields[\'url\'])) {
         $this->errors[\'url\'] = _("URL is empty");
      }  
   }
   function prepareData($mode = \'add\') {
      if ($mode == \'add\')    { // в массив данных (которые будут вставлены в таблицу)
                               // добавляем время записи.
         $this->fields[\'date\'] = time();
      }
   }

создав эти 2 метода класс полностью готов к работе.
Правда еще шаблоны сверсать надо, но это уже другая история.

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

Одно из преимуществ того, что классы всех сущностей похожи, в том, что очень
много кода можно генерировать (не толлько классы, но и код)

По поводу объемов кода
DBObject + DBObjectList  = 15 кб
Наследники по разному = от 1 - 17 кб (в среднем около 7 кб)

Все дальше писать лень.
First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack. ( George Carrette )

Оффлайн Макс

  • vir magni ingenii
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3534
  • +0/-0
  • 2
    • Просмотр профиля
Помогите с ООП
« Ответ #14 : 29 Октября 2004, 16:40:53 »
Ключевые слова по теме:
DAO (pattern)
ORM
First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack. ( George Carrette )

 

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28