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 :: Класс для работы с MySQL, class DB

 PHP.SU

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


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

> Описание: PHP
DeepVarvar Супермодератор
Отправлено: 06 Марта, 2011 - 05:03:22
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


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




Кароче как всегда получилось что-то корявое, млин...
Отцы!!! Тыкайте в ошибки...
(собак наставил правда дофига)

Вэлком ту ВЭЛОСЫПЕДЪ
PHP:
скопировать код в буфер обмена
  1.  
  2. class report extends Exception {
  3.         public function get() {
  4.                 return parent::getMessage();
  5.                 }
  6.         }
  7.  
  8. abstract class db {
  9.         static $link;
  10.         static $error;
  11.         public static function connect() {
  12.                 self::$link = @mysql_connect('host','user','pass') or $e = new report(mysql_error());
  13.                 if (isset($e)) self::eset($e->get());
  14.                 @mysql_query('SET NAMES "utf8";');
  15.                 @mysql_query('SQL_QUERY_CACHE_TYPE = 2;');
  16.                 @mysql_select_db('db_name');
  17.                 @mysql_query('FLUSH QUERY CACHE;');
  18.                 @mysql_query('RESET QUERY CACHE;');
  19.                 }
  20.         private function parse($data) {
  21.                 if (is_array($data)) {
  22.                         if (count($data) > 0) {
  23.                                 if (count($data) < 2) {
  24.                                         foreach ($data as $value) return self::parse($value);
  25.                                         }
  26.                                 else return $data;
  27.                                 }
  28.                         else return false;
  29.                         }
  30.                 else return $data;
  31.                 }
  32.         public function get($query) {
  33.                 $result = @mysql_query($query) or $e = new report(mysql_error());
  34.                 if (isset($e)) self::eset($e->get());
  35.                 while ($row = @mysql_fetch_assoc($result)) {
  36.                         $pre[] = $row;
  37.                         }
  38.                 @mysql_free_result($result);
  39.                 return self::parse($pre);
  40.                 }
  41.         public function set($query) {
  42.                 mysql_query($query) or $e = new report(mysql_error());
  43.                 if (isset($e)) self::eset($e->get());
  44.                 }
  45.         public function eset($m) {
  46.                 self::$error = $m;
  47.                 }
  48.         public function emessage() {
  49.                 return self::$error;
  50.                 }
  51.         public static function close() {
  52.                 @mysql_query('RESET QUERY CACHE;');
  53.                 @mysql_query('FLUSH QUERY CACHE;');
  54.                 @mysql_close(self::$link);
  55.                 }
  56.         }
  57.  

Юзать так:
PHP:
скопировать код в буфер обмена
  1. db::connect();
  2.  
  3. $result = db::get("SELECT name FROM users WHERE id = 1 LIMIT 1");
  4. // вернет $result = "имя" (не массив)
  5.  
  6. $result = db::get("SELECT id,name FROM users WHERE id = 1 LIMIT 1");
  7. // вернет уже массив $result = array("1","имя")
  8.  
  9. $result = db::get("SELECT * FROM users LIMIT 20");
  10. // ну догадались что вернет :)
  11.  
  12. // в случае если запрос прошел но ничего не вернул $result = false
  13. // ошибку вывести можно в любое время в любом месте
  14. // естественно даже после закрытия соединения с базой
  15. // про накопление ошибок в массив думал
  16. echo db::emessage();
  17.  
  18. db::close();

Не особо нраца оно мне. Но работает так как задумал...
(Добавление)
Только раместил - пришла мысль закатать любой и каждый запрос,
в том числе и внутренние "приватные", в обертку проверки на эксцепшн.
Щас переделаю...
 
 Top
ALEN Модератор
Отправлено: 06 Марта, 2011 - 08:59:05
Post Id



Участник


Покинул форум
Сообщений всего: 1459
Дата рег-ции: Авг. 2008  
Откуда: Крым


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




1) многие юзают mysqli
2) Честно сказать не понял смысла класса
3) Где не уверен? что не пройдет ошибка, не ставь собак, а просто делай проверку на ошибки и выводи на экран
 
 Top
Champion Супермодератор
Отправлено: 07 Марта, 2011 - 09:26:53
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


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




DeepVarvar пишет:
('host','user','pass')
Лучше сделать это свойствами класса и инициализировать либо передав параметры в конструктор, либо сделать метод для инициализации их.
DeepVarvar пишет:
"utf8"
Тоже должен быть гибкий настраиваемый параметр.
И тип БД тоже неплохо бы выбирать, а не привязываться к одному mysql.
DeepVarvar пишет:

PHP:
скопировать код в буфер обмена
  1. if (is_array($data)) {
  2.                         if (count($data) > 0) {
  3.                                 if (count($data) < 2) {
  4.                                         foreach
Ой какая лесенка. Не хорошо.
DeepVarvar пишет:

// вернет $result = "имя" (не массив)
...
// вернет уже массив $result = array("1","имя")
На мой взгляд, такое разное поведение функции - не гуд.
 
 Top
ALEN Модератор
Отправлено: 07 Марта, 2011 - 09:32:35
Post Id



Участник


Покинул форум
Сообщений всего: 1459
Дата рег-ции: Авг. 2008  
Откуда: Крым


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




Champion пишет:
На мой взгляд, такое разное поведение функции - не гуд.

Согласен
 
 Top
DeepVarvar Супермодератор
Отправлено: 09 Марта, 2011 - 09:11:08
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


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




Доработаю сегодня вечером. Сейчас на работе.
(Добавление)
Champion пишет:
На мой взгляд, такое разное поведение функции - не гуд.

Раньше всегда массив возвращала. Решил сделать чуть удобнее.
Зачем инициализировать лишний массив для хранения результата,
если мы всеравно тащим только одну строчку из БД?
В остальных случаях возвращает массив.

Вот например так не очень удобно кажется:
PHP:
скопировать код в буфер обмена
  1. $result = db::get("SELECT COUNT(*) as count FROM users");
  2. echo $result['count'];

Так лаконичнее:
PHP:
скопировать код в буфер обмена
  1. $userscount = db::get("SELECT COUNT(*) FROM users");
  2. echo $userscount;
 
 Top
EuGen Администратор
Отправлено: 09 Марта, 2011 - 09:22:54
Post Id


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


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


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




Не используйте static где попало
Используйте Singleton для создания соединений к БД (иначе на каждый вызов будете соединяться - беда)
Используйте try..catch вместо @
Желательно использовать возможность подстановки параметров в запросы, дабы снизить риск injection (впрочем, в ряде случаев его не избежать как правило, но в том же Zend это оформлено изящно)


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
DeepVarvar Супермодератор
Отправлено: 09 Марта, 2011 - 09:41:46
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


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




EuGen,ALEN,Champion спасибо за замечания - буду переделывать.
 
 Top
ALEN Модератор
Отправлено: 09 Марта, 2011 - 13:59:05
Post Id



Участник


Покинул форум
Сообщений всего: 1459
Дата рег-ции: Авг. 2008  
Откуда: Крым


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




DeepVarvar
Проще работать с массивом всегда.
Таким образом ты сократишь действия в своем классе, а кому нужно в частном порядке сам будет выводить и проверять. Тем более, что в общем плане скорость обращения к массиву с одним элементом, не будет отличатся от скорости обращения к переменной. Чтоб было хоть какое-то значительное изменение нужно умножать в сотни раз. Да и потом сделать нечто в виде:
$name=$array['name']; unset($array); - не составит труда для тех кому это нужно, а такие случаи достаточно редко будут встречаться.
В общем действительно не нужна штука.
 
 Top
DeepVarvar Супермодератор
Отправлено: 12 Марта, 2011 - 17:58:02
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


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




Попытка %2
Вчерашние роды Радость
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. $db = new db('localhost','user','pass');
  3. $db->param('SET NAMES "utf8"');
  4. $db->selectDB('db_name');
  5. $find = 11;
  6. $find = clean($find);
  7. $result = $db->get("SELECT name FROM users WHERE id = $find",PARSE);
  8. $db->close();
  9.  
  10. if (error::$init) echo error::viewlog();
  11. ?>

0. Убрал собак, объявил иной уровень вывода ошибок.
1. Установка host,user,pass при инициализации.
2. В метод ->param() можно отправлять любой запрос, он ссылается на обычный mysql_query();
3. Выбор БД вынес в публичный метод ->selectDB()
4. От SQL-инъекций сперва чистим, ф-ция clean() работает и с массивами.
5. Необязательный аргумент PARSE в методе ->get(), если объявлен,
делает "$name=$array['name'];" внутри обработки запроса, (for Champion,ALEN)
в противном случае возвращает "$array['name']".
6. Ошибки теперь собирает в массив и если надо, выводит списком <ul><li>.....

To EuGen: что-то я запарился с try...throw...catch и прочими экспериментировать.
Пока эта часть не реализована, смысл и принцип ясны, но пока не прикрутил...

А вот и листинг:
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.  
  3. error_reporting(E_NOTICE);
  4.  
  5. define("PARSE",true);
  6.  
  7. class ex extends Exception {
  8.         private static $e = NULL;
  9.         public static function getInstance() {
  10.                 if ($this->e == NULL) $this->e = new ex;
  11.                 return $this->e;
  12.                 }
  13.         public function get() {
  14.                 return parent::getMessage();
  15.                 }
  16.         }
  17.  
  18. function clean($str,$len = 32) {
  19.         if (is_array($str)) {
  20.                 foreach ($str as $k => $v) $str[$k] = clean($v);
  21.                 return $str;
  22.                 }
  23.         else return '"'.htmlentities(substr($str,0,$len)).'"';
  24.         }
  25.  
  26. class error {
  27.         public static $init = false;
  28.         public static $errors = array(false);
  29.         public function writelog($fn) {
  30.                 $ex = new ex($fn);
  31.                 self::$errors[] = $ex->get();
  32.                 unset($ex);
  33.                 self::$init = true;
  34.                 }
  35.         public function viewlog() {
  36.                 if (count(self::$errors) > 1) {
  37.                         $out = "<ul>";
  38.                         foreach (self::$errors as $mess) {
  39.                                 if ($mess) $out .=  "<li>".$mess."</li>";
  40.                                 }
  41.                         $out .= "</ul>";
  42.                         return $out;
  43.                         }
  44.                 }
  45.         }
  46.  
  47. class db {
  48.         private static $db = NULL;
  49.         private $link = NULL;
  50.         private $result = NULL;
  51.         public static function getInstance() {
  52.                 if ($this->db == NULL) $this->db = new db;
  53.                 return $this->db;
  54.                 }
  55.         public function __construct($host,$user,$pass) {
  56.                 $this->link = $this->checker("mysql_connect('$host','$user','$pass');",false);
  57.                 }
  58.         public function close() {
  59.                 $this->checker('mysql_close($this->link);',false);
  60.                 }
  61.         public function selectDB($db) {
  62.                 $this->checker("mysql_select_db('$db');",false);
  63.                 }
  64.         public function param($query) {
  65.                 $this->set($query);
  66.                 }
  67.         public function set($query) {
  68.                 $this->checker("mysql_query('$query');",false);
  69.                 }
  70.         public function get($query,$parse = false) {
  71.                 $result = $this->checker("mysql_query('$query');",true);
  72.                 $arr = array();
  73.                 $cr = mysql_num_rows($result);
  74.                 if ($cr > 0) {
  75.                         while ($row = mysql_fetch_assoc($result)) $arr[] = $row;
  76.                         if ($cr == 1) {
  77.                                 $cf = mysql_num_fields($result);
  78.                                 if ($parse and $cf == 1) {
  79.                                         $f = mysql_fetch_field($result,0);
  80.                                         $return = $arr[0][$f->name];
  81.                                         }
  82.                                 else $return = $arr[0];
  83.                                 }
  84.                         else $return = $arr;
  85.                         $this->checker("mysql_free_result('$result');",false);
  86.                         return $return;
  87.                         }
  88.                 else return false;
  89.                 }
  90.         private function checker($query,$t) {
  91.                 $r = NULL;
  92.                 eval('$r = '.$query) or error::writelog(mysql_error());
  93.                 if (!$t) unset($r);
  94.                 else if ($r) return $r;
  95.                 }
  96.         }
  97. ?>

(Отредактировано автором: 12 Марта, 2011 - 18:09:50)

 
 Top
Champion Супермодератор
Отправлено: 12 Марта, 2011 - 18:17:54
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


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




DeepVarvar пишет:
метод ->param()
Не очень удачное название) Название clean для функции обезопашивания данных тоже не вызывает чувства удовлетворения при прочтении. И раз уж она призвана обезопашивать данные, почему бы ее не сделать членом класса?
Потом можно использовать запросы с подставляемыми параметрами и не утруждать пользователя руками вызывать функцию clean().
DeepVarvar пишет:

public static $init = false;
public static $errors = array(false);
плохо.

Раз речь пошла о синглтонах, то конструктор надо сделать приватным, а инициализацию host, login, pass производить другим методом.

Очень мне не нравится подход с функцией checker(). И как-то не очень он с инъекциями по-моему борется. А больше никто не борется. Функцию clean() никто не обязывает пользователя использовать.

Ай-ай-ай. Давай что-нибудь другое рожай)
 
 Top
DeepVarvar Супермодератор
Отправлено: 12 Марта, 2011 - 18:29:03
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


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




Champion пишет:
Раз речь пошла о синглтонах

Сделаем..
Champion пишет:
Не очень удачное название ->param

Почему?
Champion пишет:
почему бы clean() не сделать членом класса?

Думал об этом - сделаю.
Champion пишет:
public static $init = false;
public static $errors = array(false); ПЛОХО

Почему?
Champion пишет:
checker()

Он не борется с инъекцией - он только проверяет успешность запроса.
(Добавление)
Champion пишет:
Название clean для функции обезопашивания данных тоже не вызывает чувства удовлетворения при прочтении

Однако обезопашивает.
Или есть методы обхода?
 
 Top
Champion Супермодератор
Отправлено: 12 Марта, 2011 - 18:43:15
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


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




DeepVarvar пишет:
Почему?
Название функции должно описывать, что она делает. Например, на турецком языке это слово означает деньги. Турецких программистов ты запутаешь, у них начнется паника и стресс.
DeepVarvar пишет:
Он не борется с инъекцией
А кто же тогда бороться будет? Я вызываю публичный метод класса, я должен быть уверен, что всё будет хорошо и безопасно.
DeepVarvar пишет:
ПЛОХО
Почему?
Потому что я могу поменять эти члены класса снаружи и нарушить работу внутренних методов. Менять свойства класса должны только методы класса. И поэтому св-ва должны быть приватными.
(Добавление)
DeepVarvar пишет:
Однако обезопашивает.
Или есть методы обхода?
Я не написал, что она не обезопашивает. Я написал, что название не удачно. Такое название больше подойдет для функции, которая что-то полностью очищает.
(Добавление)
А то, что она возвращает значение в двойных кавычках не хорошо, потому что, например в firebird двойные кавычки выполняют такую же функцию, как в mysql символ `.
Еще обезопашивать данные именно htmlentities не очень здорово, потому что не все данные предназначены для вывода на веб страницы. Иногда лучше сохранять их в первоначальном виде, просто проэкранировав опасные символы.
 
 Top
Мелкий Супермодератор
Отправлено: 12 Марта, 2011 - 18:57:37
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


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




DeepVarvar пишет:
Или есть методы обхода?

Есть. Не обрабатываются одинарные кавычки. См описание htmlentities.

Использование eval - жирный минус классу. Он здесь не требуется и класс теряет в переносимости, т.к. может быть отключен eval на хостингах.


-----
PostgreSQL DBA
 
 Top
DeepVarvar Супермодератор
Отправлено: 12 Марта, 2011 - 19:28:31
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


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




Champion пишет:
на турецком языке

Ну и пусть турки едут в дурку Радость
Champion пишет:
А кто же тогда бороться будет?

Только clean()
Champion пишет:
Потому что я могу поменять эти члены класса снаружи.

В контексте именно этого класса это необходимо...
Champion пишет:
например в firebird...

Не подумал об этом, однако тут идет речь только о MySQL, т.к. я отказался делать поддежку других БД.
Champion пишет:
потому что не все данные предназначены для вывода на веб страницы

Эти данные никогда не выводятся на страницу - они посылаются в запросе к БД.
(Добавление)
Мелкий пишет:
Не обрабатываются одинарные кавычки

Упс, упустил - ENT_QUOTES
(Добавление)
Мелкий пишет:
eval

Буду думать...

(Отредактировано автором: 12 Марта, 2011 - 19:29:09)

 
 Top
Champion Супермодератор
Отправлено: 12 Марта, 2011 - 20:13:25
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


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




DeepVarvar пишет:
В контексте именно этого класса это необходимо...
Неконтролируемое изменение членов класса необходимо? Так же не бывает.
DeepVarvar пишет:
Эти данные никогда не выводятся на страницу - они посылаются в запросе к БД.
Тем более обработка htmlentities тут неуместна.
 
 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