Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Класс для работы с БД

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (2): [1] 2 »   

> Без описания
Eihwaz
Отправлено: 09 Апреля, 2008 - 18:28:41
Post Id


Гость


Покинул форум
Сообщений всего: 112
Дата рег-ции: Нояб. 2007  


Помог: 0 раз(а)




Начал изучать ООП, вот, класс наваял. Не знал, куда лучше выложить, класс-то работает, но хочется критики и советов по улучшению (сразу оговорюсь, что необъективных критиков буду посылать на юга).
В принципе, "умеет" самые распространенные вещи. С JOIN'ами пока не работает.
Есть простенький дебаггер (ну, как, дебаггер - одно название, просто если при вызове функции класса указать атрибут debug равный true, то запрос идет не в базу, а пользователю на экран).
Если произошла ошибка во время запроса, пользователю дается та ссылка, куда чаще всего посылают - в гугль.
В архиве примеры использования.
Умеет:
Заводить и удалять таблицы
Вставлять и обновлять данные
Делать выборку в массив (ассоциативный или числовой - указывается в параметре функции)
Считать ячейки, ну и т.п.
В основном заточен под работу с массивами.
P.S.: Вообще идея была сделать класс, который в итоге формирует "хороший" запрос к БД, т.е., с обратными кавычками (`) в нужных местах и т.п. Получилось не везде Улыбка
Скачать файл: db_class.tar.gz
Скачан раз: 528
 
 Top
-SCHATTEN-
Отправлено: 10 Апреля, 2008 - 11:55:30
Post Id



Пользователь


Покинул форум
Сообщений всего: 615
Дата рег-ции: Июль 2006  
Откуда: Оттуда !


Помог: 0 раз(а)




Сильно не смотрел, так пробежался тока заметил подобные недочеты :
1) Когда код пишешь юзай рефакторинг, ато иногда в отступах путаешься.
2) При выполнении запросов данные нигде не проверяются, тоесть если при использовании не проверить то сайт можно сломать без проблем.
3) Как узнать выполнился ли запрос или нет ?

Потом покопаюсь мож ещё что найду
 
 Top
Eihwaz
Отправлено: 10 Апреля, 2008 - 12:05:02
Post Id


Гость


Покинул форум
Сообщений всего: 112
Дата рег-ции: Нояб. 2007  


Помог: 0 раз(а)




-SCHATTEN- пишет:
Сильно не смотрел, так пробежался тока заметил подобные недочеты :
1) Когда код пишешь юзай рефакторинг, ато иногда в отступах путаешься.
2) При выполнении запросов данные нигде не проверяются, тоесть если при использовании не проверить то сайт можно сломать без проблем.
3) Как узнать выполнился ли запрос или нет ?

Потом покопаюсь мож ещё что найду


1) Учтем, спасибо Улыбка
2) Тоже согласен, не учел.
3) Если запрос не выполнился, в браузер выводится сообщение с номером ошибки, текстом ошибки и текстом запроса, который вызвал ошибку.
Да, я забыл сказать, там в примерах везде включен режим debug, т.е., просто вывод запроса в браузер. Если последний параметр любой функции установить в false, то запрос будет выполняться.
 
 Top
-SCHATTEN-
Отправлено: 10 Апреля, 2008 - 14:28:29
Post Id



Пользователь


Покинул форум
Сообщений всего: 615
Дата рег-ции: Июль 2006  
Откуда: Оттуда !


Помог: 0 раз(а)




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

Это если дебаг включен. А когда пишешь порталы часто возникает ситуация когда надо знать выполнился запрос или нет, и в зависимости от этого решать что делать дальше. А У тебя это проблемотично.

И я у тебя ненашел такой вещи как вернуть объект , у тебя тока массив можно получить
(Добавление)
PHP:
скопировать код в буфер обмена
  1.  
  2. <?
  3. if ($result = $this->query_execute($select_query))
  4. {
  5.     return mysql_fetch_array($result, $type);
  6. }
  7. ?>
  8.  

Условие неимеет смысла. Потому что в $result вернется либо TRUE либо текст Ошибки.
(Добавление)
>Если последний параметр любой функции установить в false, то запрос будет выполняться.

Есть вероятность ошибки БД. поэтому и надо смотеть точно ли выполнился запрос или нет
 
 Top
Eihwaz
Отправлено: 10 Апреля, 2008 - 15:02:58
Post Id


Гость


Покинул форум
Сообщений всего: 112
Дата рег-ции: Нояб. 2007  


Помог: 0 раз(а)




-SCHATTEN- пишет:
Если запрос не выполнился, в браузер выводится сообщение с номером ошибки, текстом ошибки и текстом запроса, который вызвал ошибку.

Это если дебаг включен. А когда пишешь порталы часто возникает ситуация когда надо знать выполнился запрос или нет, и в зависимости от этого решать что делать дальше. А У тебя это проблемотично.
...
Есть вероятность ошибки БД. поэтому и надо смотеть точно ли выполнился запрос или нет

Нет, в классе все запросы выполняются функцией query_execute, которая, в случае запроса, который привел к ошибке, пишет ошибку в браузер. Т.е., по-сути, тот же дебаггер. А если включен дебаг, то запрос не будет пытаться выполняться - просто выводится сообщение в браузер, вне зависимости от того, правильно он составлен или нет.
-SCHATTEN- пишет:

И я у тебя ненашел такой вещи как вернуть объект , у тебя тока массив можно получить

Согласен, добавил к JOIN'ам и проверке данных Улыбка
-SCHATTEN- пишет:

(Добавление)
PHP:
скопировать код в буфер обмена
  1.  
  2. <?
  3. if ($result = $this->query_execute($select_query))
  4. {
  5.     return mysql_fetch_array($result, $type);
  6. }
  7. ?>
  8. Условие неимеет смысла. Потому что в $result вернется либо TRUE либо текст Ошибки.
  9.  


Согласен, если имелось ввиду, что не имеет смысла ставить условие 'if', потому что функция query_execute либо вернет TRUE, либо сама выведет ошибку.
Или что-то другое имеется ввиду?
P.S.: И вопрос тогда сразу: имеет ли все-таки смысл делать таким способом, как здесь - т.е., когда пользователь класса (ну, разработчик, скажем), не формирует запрос напрямую, а создает массив с данными, которые нужно вставить в запрос, условия и т.п., а самим составлением запроса занимается класс? Потому что в моем случае большинство функций принимает кучу параметров, которые разработчику нужно будет запомнить (имя таблицы, массив для вставки/обновления данных, условие, и т.д.). Вобщем, оправдан подобный подход или нет?
 
 Top
-SCHATTEN-
Отправлено: 12 Апреля, 2008 - 10:56:37
Post Id



Пользователь


Покинул форум
Сообщений всего: 615
Дата рег-ции: Июль 2006  
Откуда: Оттуда !


Помог: 0 раз(а)




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

Eihwaz пишет:
Согласен, если имелось ввиду, что не имеет смысла ставить условие 'if', потому что функция query_execute либо вернет TRUE, либо сама выведет ошибку.


Да именно это я имел в виду.

Eihwaz пишет:
Нет, в классе все запросы выполняются функцией query_execute, которая, в случае запроса, который привел к ошибке, пишет ошибку в браузер. Т.е., по-сути, тот же дебаггер. А если включен дебаг, то запрос не будет пытаться выполняться - просто выводится сообщение в браузер, вне зависимости от того, правильно он составлен или нет.


Я бы на твоем месте переделал этот метод чтобы метод query_execute возвращал BOOLEAN.

Если ты хочешь написать класс, то это должен быть один класс который можно использовать в разработке. В твоем случае у тебя подключается много сторонних вещей со своим дизайном и т.п. Этого недолжно быть. Хотя бы по 2-м причинам :
1) У разработчика должен быть набор мотодов которыми он пользуется и не задумывается о том что в случае ошибки всё пойдет нетак
2) В большинстве порталов есть свои обработчики ошибок и их вывод
(Добавление)
К вопросу о смысле использования такой модели :
Гораздо проще написать :
PHP:
скопировать код в буфер обмена
  1.  
  2. <?
  3. $select = $db->select()
  4.     ->from(array('p' => 'products'),
  5.         array('product_id'))
  6.     ->join(array('l' => 'line_items'),
  7.         'p.product_id = l.product_id',
  8.         array('line_items_per_product' => 'COUNT(*)'))
  9.     ->group('p.product_id')
  10.     ->having('line_items_per_product > 10');
  11. ?>
  12.  


чем

PHP:
скопировать код в буфер обмена
  1. SELECT p."product_id", COUNT(*) AS line_items_per_product
  2.    FROM "products" AS p JOIN "line_items" AS l
  3.      ON p.product_id = l.product_id
  4.    GROUP BY p.product_id
  5.    HAVING line_items_per_product > 10
 
 Top
Eihwaz
Отправлено: 12 Апреля, 2008 - 11:25:36
Post Id


Гость


Покинул форум
Сообщений всего: 112
Дата рег-ции: Нояб. 2007  


Помог: 0 раз(а)




Ясно, спасибо за развернутые комментарии, уже переделываю.
Насчет вывода ошибок в браузер и дизайна - ну, да, я под себя пишу в основном этот класс (да, как любой человек, изучающий php я тоже пишу свою cms Улыбка ), потому решил включить в класс и обработку ошибок, но вчера все-таки начал склоняться к отдельному обработчику ошибок, хотя бы потому, что ошибки вызывают не только неверные запросы к БД.
Ну, первый блин, че там Улыбка
 
 Top
-SCHATTEN-
Отправлено: 14 Апреля, 2008 - 08:38:13
Post Id



Пользователь


Покинул форум
Сообщений всего: 615
Дата рег-ции: Июль 2006  
Откуда: Оттуда !


Помог: 0 раз(а)




Да пожалста.
И мой тебе совет, если решил писать на классах, использую ООП . То не смотри на PHP 4 н для этого не преспособлен практически.

Но с другой стороны ещё очень много хостингов и платформ используют именно PHP 4
 
 Top
Eihwaz
Отправлено: 14 Апреля, 2008 - 16:50:14
Post Id


Гость


Покинул форум
Сообщений всего: 112
Дата рег-ции: Нояб. 2007  


Помог: 0 раз(а)




Вторая попытка. Переделал под синтаксис 5-го PHP, входящие данные проверяются, с отступами, кажется, все нормально, добавлен вывод текста последней ошибки, номера последней ошибки и текста последнего запроса. Еще считает общее количество запросов к БД с момента начала работы класса, тоже можно вывести в браузер на этапе разработки. Функиця, которая выполняет все запросы теперь возвращает либо результат запроса, либо false (но сначала присваивает соответствующие данные переменным _last_errno и _last_errtext).
Дизайна больше нету никакого.
Все еще работаю над ним, (JOIN'ы, объекты и т.п.).
-SCHATTEN-, скажи, на это уже можно без слез смотреть? Улыбка
Скачать файл: db_class.php.tar.gz
Скачан раз: 340

(Отредактировано автором: 14 Апреля, 2008 - 16:51:14)

 
 Top
EuGen Администратор
Отправлено: 15 Апреля, 2008 - 13:14:41
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Бегло просмотрел (извиняюсь, если нарушаю Ваш диалог), есть несколько советов:
0. Можно поподробнее смысл вот этого:
CODE (text):
скопировать код в буфер обмена
  1.  
  2. $this->_query = $this->escape($sql);
  3. $result = mysql_query($sql);
  4.  

То есть сделано экранирование, а потом в запрос подставляем исходный (неэкранированный) текст? .. Непонятно..
1. Функция select_from_table имеет неудачно объявленный набор аргументов. Для того, чтобы выбрать `*`, то есть значение по-умолчанию, придется написать:
CODE (text):
скопировать код в буфер обмена
  1.  
  2. select_from_table($table, , $where, $order_by, $limit);
  3.  

То есть, фактически, указать пустой аргумент.. Я лично не сторонник такого использования, да и запятая - та же звездочка по числу символов (мы ничего не сэкономили). Лучше все то, что можно не указывать при вызове функции, ставить на последние места в объявлении списка аргументов функции. Но может быть, я тут не прав.
2. Аналогично про select_row_from_table
3. В функции delete_from_table нужно обязательно указывать where, а это не правильно, как я думаю. А если я хочу удалить все в таблице.. мне нужно будет обязательно указать "1" в where. Более того, неплохо было бы дать не просто возможность не указывать where, но и, если последнее не указано, делать TRUNCATE (это будет работать намного быстрее для больших таблиц).


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Eihwaz
Отправлено: 15 Апреля, 2008 - 14:17:12
Post Id


Гость


Покинул форум
Сообщений всего: 112
Дата рег-ции: Нояб. 2007  


Помог: 0 раз(а)




EuGen пишет:
То есть сделано экранирование, а потом в запрос подставляем исходный (неэкранированный) текст? .. Непонятно..

А?! Тьфу ты... все моя невнимательность...
EuGen пишет:
1. Функция select_from_table имеет неудачно объявленный набор аргументов. Для того, чтобы выбрать `*`, то есть значение по-умолчанию, придется написать:

Согласен, переносим...
EuGen пишет:
В функции delete_from_table нужно обязательно указывать where, а это не правильно, как я думаю. ... Более того, неплохо было бы дать не просто возможность не указывать where, но и, если последнее не указано, делать TRUNCATE (это будет работать намного быстрее для больших таблиц).

Тоже принял к сведению Улыбка
Спасибо за комментарии, потихоньку уже все-таки осваиваю... Был бы признателен администрации, если бы тему перенесли куда-то в другое место, потому что она превратилась в "помогите написать класс для работы с БД" Улыбка
 
 Top
EuGen Администратор
Отправлено: 15 Апреля, 2008 - 14:41:17
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Еще вспомнил: в функции select_from_table (и всех select-функциях) нужно сделать необязательным параметры where, order_by и limit; так как по синтаксису SELECT их указывать необязательно.

(Отредактировано автором: 15 Апреля, 2008 - 14:44:15)



-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Eihwaz
Отправлено: 15 Апреля, 2008 - 15:43:36
Post Id


Гость


Покинул форум
Сообщений всего: 112
Дата рег-ции: Нояб. 2007  


Помог: 0 раз(а)




Наконец-то осознал, что прогонять всю строку запроса к БД через mysql_real_escape_string нельзя, потому что валидный запрос вида:
SELECT `user_name` FROM `tbl_users` WHERE `user_name` = 'User'
после real_escape даст невалидный результат:
SELECT `user_name` FROM `tbl_users` WHERE `user_name` = \'User\'
Прогонять параметры функции (тот же $where) тоже нельзя, потому что если $where = '`user_name` = 'User'' даст в итоге тот же результат - `user_name` = \'User\'.
Пока думаю убрать экранирование из класса, и обрабатывать данные еще до передачи их в функции, но может есть еще какой-то вариант?
 
 Top
-SCHATTEN-
Отправлено: 16 Апреля, 2008 - 12:25:11
Post Id



Пользователь


Покинул форум
Сообщений всего: 615
Дата рег-ции: Июль 2006  
Откуда: Оттуда !


Помог: 0 раз(а)




EuGen пишет:
нужно сделать необязательным параметры where, order_by и limit; так как по синтаксису SELECT их указывать необязательно.

Согласен и код
PHP:
скопировать код в буфер обмена
  1. $limit = (isset($limit) ? $limit : '0, 100');

Смысла неимеет, если не передать этот параметр функция напросто отвалится.

Так вроде ничего, тока сразу лучше юзать PHP docs и коменты вида :
PHP:
скопировать код в буфер обмена
  1. <?
  2. /****************************
  3.     * Удаляет данные из таблицы *
  4.     *****************************/
  5.     public function delete_from_table($table, $where) ?>
  6.  

меняй на
PHP:
скопировать код в буфер обмена
  1.  
  2. <?
  3. /**
  4.      *  Удаляет данные из таблицы
  5.      *
  6.      * @param string $table имя таблицы в БД
  7.      * @param string $where условие WHERE для SQL запроса
  8.      * @return bool
  9.      */
  10.     public function delete_from_table($table, $where)...
  11. ?>
  12.  
 
 Top
Eihwaz
Отправлено: 16 Апреля, 2008 - 14:09:59
Post Id


Гость


Покинул форум
Сообщений всего: 112
Дата рег-ции: Нояб. 2007  


Помог: 0 раз(а)




V 0.03 Улыбка
Уже когда выложил заметил, что в конце оставил перенос строки (после закрывающего тега php), если кто будет пользоваться - не забудьте убрать...

И вопрос тогда вдогонку:
Если использовать класс в "боевых" условиях, т.е., при разработке, каким образом организовать выборку, добавление, удаление, скажем, статей? Всмысле, имеет ли смысл писать некий класс, например, "content", который будет потомком класса для базы данных, или писать независимый класс, который в себе использует функции класса БД (получается просто довольно громоздкая и не очень красивая конструкция вроде:
$this->_article = $this->db->select_row_from_table(тра-ля-ля, ля))
В случае с потомком класса эта конструкция выглядит приятнее, но разрастается сам класс. До этого пользовался только функциональным подходом, но в ООП подкупает удобная расширяемость...
Скачать файл: db_class2.php.tar.gz
Скачан раз: 410

(Отредактировано автором: 16 Апреля, 2008 - 14:34:01)

 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Пользовательские функции »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB