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
Форумы портала PHP.SU :: Версия для печати :: Класс для работы с БД
Форумы портала PHP.SU » PHP » Пользовательские функции » Класс для работы с БД

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

1. Eihwaz - 09 Апреля, 2008 - 18:28:41 - перейти к сообщению
Начал изучать ООП, вот, класс наваял. Не знал, куда лучше выложить, класс-то работает, но хочется критики и советов по улучшению (сразу оговорюсь, что необъективных критиков буду посылать на юга).
В принципе, "умеет" самые распространенные вещи. С JOIN'ами пока не работает.
Есть простенький дебаггер (ну, как, дебаггер - одно название, просто если при вызове функции класса указать атрибут debug равный true, то запрос идет не в базу, а пользователю на экран).
Если произошла ошибка во время запроса, пользователю дается та ссылка, куда чаще всего посылают - в гугль.
В архиве примеры использования.
Умеет:
Заводить и удалять таблицы
Вставлять и обновлять данные
Делать выборку в массив (ассоциативный или числовой - указывается в параметре функции)
Считать ячейки, ну и т.п.
В основном заточен под работу с массивами.
P.S.: Вообще идея была сделать класс, который в итоге формирует "хороший" запрос к БД, т.е., с обратными кавычками (`) в нужных местах и т.п. Получилось не везде Улыбка
2. -SCHATTEN- - 10 Апреля, 2008 - 11:55:30 - перейти к сообщению
Сильно не смотрел, так пробежался тока заметил подобные недочеты :
1) Когда код пишешь юзай рефакторинг, ато иногда в отступах путаешься.
2) При выполнении запросов данные нигде не проверяются, тоесть если при использовании не проверить то сайт можно сломать без проблем.
3) Как узнать выполнился ли запрос или нет ?

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

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


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

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

И я у тебя ненашел такой вещи как вернуть объект , у тебя тока массив можно получить
(Добавление)
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, то запрос будет выполняться.

Есть вероятность ошибки БД. поэтому и надо смотеть точно ли выполнился запрос или нет
5. Eihwaz - 10 Апреля, 2008 - 15:02:58 - перейти к сообщению
-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.: И вопрос тогда сразу: имеет ли все-таки смысл делать таким способом, как здесь - т.е., когда пользователь класса (ну, разработчик, скажем), не формирует запрос напрямую, а создает массив с данными, которые нужно вставить в запрос, условия и т.п., а самим составлением запроса занимается класс? Потому что в моем случае большинство функций принимает кучу параметров, которые разработчику нужно будет запомнить (имя таблицы, массив для вставки/обновления данных, условие, и т.д.). Вобщем, оправдан подобный подход или нет?
6. -SCHATTEN- - 12 Апреля, 2008 - 10:56:37 - перейти к сообщению
Подход оправдан, причем более чем. Такой подход гарантирует валидный 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
7. Eihwaz - 12 Апреля, 2008 - 11:25:36 - перейти к сообщению
Ясно, спасибо за развернутые комментарии, уже переделываю.
Насчет вывода ошибок в браузер и дизайна - ну, да, я под себя пишу в основном этот класс (да, как любой человек, изучающий php я тоже пишу свою cms Улыбка ), потому решил включить в класс и обработку ошибок, но вчера все-таки начал склоняться к отдельному обработчику ошибок, хотя бы потому, что ошибки вызывают не только неверные запросы к БД.
Ну, первый блин, че там Улыбка
8. -SCHATTEN- - 14 Апреля, 2008 - 08:38:13 - перейти к сообщению
Да пожалста.
И мой тебе совет, если решил писать на классах, использую ООП . То не смотри на PHP 4 н для этого не преспособлен практически.

Но с другой стороны ещё очень много хостингов и платформ используют именно PHP 4
9. Eihwaz - 14 Апреля, 2008 - 16:50:14 - перейти к сообщению
Вторая попытка. Переделал под синтаксис 5-го PHP, входящие данные проверяются, с отступами, кажется, все нормально, добавлен вывод текста последней ошибки, номера последней ошибки и текста последнего запроса. Еще считает общее количество запросов к БД с момента начала работы класса, тоже можно вывести в браузер на этапе разработки. Функиця, которая выполняет все запросы теперь возвращает либо результат запроса, либо false (но сначала присваивает соответствующие данные переменным _last_errno и _last_errtext).
Дизайна больше нету никакого.
Все еще работаю над ним, (JOIN'ы, объекты и т.п.).
-SCHATTEN-, скажи, на это уже можно без слез смотреть? Улыбка
10. EuGen - 15 Апреля, 2008 - 13:14:41 - перейти к сообщению
Бегло просмотрел (извиняюсь, если нарушаю Ваш диалог), есть несколько советов:
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 (это будет работать намного быстрее для больших таблиц).
11. Eihwaz - 15 Апреля, 2008 - 14:17:12 - перейти к сообщению
EuGen пишет:
То есть сделано экранирование, а потом в запрос подставляем исходный (неэкранированный) текст? .. Непонятно..

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

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

Тоже принял к сведению Улыбка
Спасибо за комментарии, потихоньку уже все-таки осваиваю... Был бы признателен администрации, если бы тему перенесли куда-то в другое место, потому что она превратилась в "помогите написать класс для работы с БД" Улыбка
12. EuGen - 15 Апреля, 2008 - 14:41:17 - перейти к сообщению
Еще вспомнил: в функции select_from_table (и всех select-функциях) нужно сделать необязательным параметры where, order_by и limit; так как по синтаксису SELECT их указывать необязательно.
13. Eihwaz - 15 Апреля, 2008 - 15:43:36 - перейти к сообщению
Наконец-то осознал, что прогонять всю строку запроса к БД через 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\'.
Пока думаю убрать экранирование из класса, и обрабатывать данные еще до передачи их в функции, но может есть еще какой-то вариант?
14. -SCHATTEN- - 16 Апреля, 2008 - 12:25:11 - перейти к сообщению
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.  
15. Eihwaz - 16 Апреля, 2008 - 14:09:59 - перейти к сообщению
V 0.03 Улыбка
Уже когда выложил заметил, что в конце оставил перенос строки (после закрывающего тега php), если кто будет пользоваться - не забудьте убрать...

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

 

Powered by ExBB FM 1.0 RC1