короче вот так плохо PHP: <? $db -> query( "INSERT INTO mytable VALUES('" . mysql_real_escape_string( $_POST['something'] ) ."', '" . mysql_real_escape_string( $_POST['something'] ) ."', '" . mysql_real_escape_string( $_POST['something'] ) ."', '" . mysql_real_escape_string( $_POST['something'] ) ."', '" . mysql_real_escape_string( $_POST['something'] ) ."', '" . mysql_real_escape_string( $_POST['something'] ) ."', '" . mysql_real_escape_string( $_POST['something'] ) ."', '" . mysql_real_escape_string( $_POST['something'] ) ."', '" . mysql_real_escape_string( $_POST['something'] ) ."', '" . mysql_real_escape_string( $_POST['something'] ) ."', '" . mysql_real_escape_string( $_POST['something'] ) ."')" ); $db -> query( "INSERT INTO mytable VALUES('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')", $_POST['something'], $_POST['something'], $_POST['something'], $_POST['something'], $_POST['something'], $_POST['something'], $_POST['something'], $_POST['something'], $_POST['something'], $_POST['something'] ); ?> вот так хорошо PHP: <? class db{ function insert( $table, $content ){ foreach( $content as &$v ){ $v = mysql_real_escape_string( $v ); } $sql = "INSERT INTO `$table` "; $sql .= "(`" . implode( "`,`", array_keys( $content ) ) . "`) "; $sql .= "VALUES('" . implode( "','", $content ) . "') "; $this -> query( $sql ); } } $db = new db; $db -> insert( 'mytable', array( 'something' => $_POST['something'], 'something' => $_POST['something'], 'something' => $_POST['something'], 'something' => $_POST['something'], 'something' => $_POST['something'], 'something' => $_POST['something'], 'something' => $_POST['something'], 'something' => $_POST['something'], 'something' => $_POST['something'], 'something' => $_POST['something'], ) ); ?>
Mr.M.I.T. В принципе, все верно, относительно следующего поста. Но тут дело в чем - программер всегда должен видеть запрос в базу. Вот какую он делает обработку - не обязательно. С одной стороны удобно пихнуть в метод название таблицы и переменные, а с другой - нет. Если мне надо апдейтить какие-то определенные строки или выбирать сложным запросом? Поэтому на мой взгляд, должен быть метод обработки переменных, которые возвращаются в виде строки, в свою очередь которую мы конкатенируем в основной запрос.
О классов интерфейсы могут быть самыми разными, интрефйс работы с функцией всегда одинаков, тем более, что некоторые редакторы даже высвечивают список аргументов, при вводе имени функции! :Р
[vs] Некоторые редакторы даже высвечивают список доступных свойств и методов при вводе "имени объекта". А потом соответственно для методов даже высвечивают список аргументов!
итак, с сегодняшнего дня буду переходить с немного переделанного mysql-класса от Slaed CMS 2.0 (фуууу, достало спринтэфом фигачить). Перехожу на goDB, который является настройкой над Mysqli. Так-с, но вот проблемка: я считаю, что не нужно фигачить данные в массив array($id). Нужно их передавать просто так, списком. Поэтому нафигачил еще один класс, надстройку "под себя". В дальнейшем планирую отказаться от goDB и написать что-то свое. PHP: <?php //TODO: как получить количество затронутых рядов уже после выполнения запроса? //TODO: каким образом сделать видимым методы которых нет в IDE? class DB { private $db; public $errors; function __construct($settings) { $this->db = new goDB($settings); } function __call($m, $argv) { $types = array( 'query'=>NULL, 'assocAll'=>'assoc', 'fetchAll'=>'row', 'colAll'=>'col', 'iassocAll'=>'iassoc', 'ifetchAll'=>'irow', 'icolAll'=>'icol', 'assoc'=>'assocrow', 'fetch'=>'rowrow', 'el'=>'el', 'id'=>'id', 'ar'=>'ar', 'num'=>'num' ); if(!array_key_exists($m, $types)) $m = 'query'; $pattern = array_shift($argv); try { $result = $db->query( $pattern, // sql pattern $argv, // data $types[$m] // type ); } catch (goDBExceptionQuery $e) { $this->errors[] = array( 'error'=>$e->error(), 'errorNo'=>$e->errno(), 'query'=>$e->query() ); } return $result; } } ?> если кто-то может помочь с TODO, буду рад
Разрабатываю поделку наподобие goDB. скажите пожалуйста, а вот насколько оправданы такие конструкции: PHP: <?php $what = array( array('goods', 'id'), 'cid', 'mid', 'model', 'price', 'quantity', 'is_active', 'attribute_set', 'atr_set', 'atr_set_nva', array('manufacturer', 'title', 'manufacturer') ); $from = array('goods', 'category', 'attribute_set', 'manufacturer'); $db->query('SELECT ?c@ FROM ?t@ WHERE ?c=?i AND ?c=cid AND ?c=?c AND ?c=mid LIMIT 0,1', $what, $from, array('goods', 'id'), $_GET['id'], array('category', 'id'), array('attribute_set', 'id'), array('category', 'attribute_set'), array('manufacturer', 'id') ); в итоге это преобразуется в [sql] SELECT `tt_goods`.`id`,`cid`,`mid`,`model`,`price`,`quantity`,`is_active`,`attribute_set`,`atr_set`,`atr_set_nva`,`tt_manufacturer`.`title` AS manufacturer FROM `tt_goods`,`tt_category`,`tt_attribute_set`,`tt_manufacturer` WHERE `tt_goods`.`id`=2 AND `tt_category`.`id`=cid AND `tt_attribute_set`.`id`=`tt_category`.`attribute_set` AND `tt_manufacturer`.`id`=mid LIMIT 0,1[/sql] стоит ли использовать такие штуки в реальных проектах или будет очень тормозить? Парсится все это дело регуляркой PHP: <?php $r = preg_replace_callback( '#\?(\?|c@|t@|k@|i@|f@|s@|c|t|k|i|f|s|@)#', array($this, 'formatQueryСallback'), $subject ); , где formatQueryСallback - ф-ция из 1 switch и кучи case
А зачем это? Одно дело так подставлять значения, чтобы каждый раз их не проверять. А другое - имена полей =\ И вообще, @ - это спецсимвол. Я такую фигню написал: PHP: <?php /* Класс для работы с базой данных 2.01.2009 collaider.com Кича Владимир */ class database { private $connect; private static $instance; private $resourse; public $query_value = 1; public $query_text; function __construct () { global $sqladd, $sqlport, $sqluser, $sqlpwd, $sqlbase; $this->connect = new mysqli ($sqladd, $sqluser, $sqlpwd, $sqlbase, $sqlport); if (!$this->connect) throw new Exception("db_no_connect"); $this->connect->query("SET NAMES 'utf8', lc_time_names = 'ru_RU'"); } /* * Возвращает ссылку на объект * @return &object */ public static function getInstance() { if (!isset(self::$instance)) { $class = __CLASS__; self::$instance = new $class; } return self::$instance; } /* * Метод, делающий запрос к базе * @param mixed $method - имя обрабатывающего метода * @param string $query - запрос * @return mixed */ public function query($method, $query) { $this->query_value++; if (func_num_args() > 2) { $types = array(); $newquery = ''; $args = func_get_args(); for ($i = 0, $length = strlen($query), $arg = 2; $i < $length; $i++) { if ($query[$i] == '?') { switch ($query[$i+1]) { case "i": $newquery .= (int)$args[$arg]; break; case "d": $newquery .= (double)$args[$arg]; break; case "s": $newquery .= $this->connect->real_escape_string($args[$arg]); break; } $i++; $arg++; } else { $newquery .= $query[$i]; } } $this->query_text = $newquery; } else { $this->query_text = $query; } $this->resourse = $this->connect->query($this->query_text); if (!$this->resourse) throw new Exception('db_error'); if (is_array($method)) $result = call_user_func(array($this, array_shift($method)), $method); else $result = ($method != 'nonresult') ? $this->{$method}() : true; return $result; } /* * Метод, возвращающий выборку из базы в виде массива * @param string $keyrow - имя ключа (по умолчанию итерационная нумерация с 0) * @param bool $unsetKey - удаляет ключ из вложенного массива в случае $unsetKey == true * @return array - результат выборки: * Array ( [0] => Array ( [id] = 1, [text] = "abc"), [1] => Array ( [id] = 2, [text] = "def")) -- без параметров * Array ( [id=1] => Array ( [id] = 1, [text] = "abc"), [id=2] => Array ( [id] = 2, [text] = "def")) -- со вторым параметром, равным id * Array ( [id=1] => Array ( [text] = "abc"), [id=2] => Array ( [text] = "def")) -- со вторым параметром, равным id, и третьим true */ public function getArray($keyrow = false, $unsetKey = false) { $args = func_get_args(); if (isset($args[0])) { if (sizeof($args[0]) > 0) { $keyrow = $args[0][0]; if (isset($args[0][1])) $unsetKey = true; } } $result = Array(); if ($keyrow == false) { while ($row = $this->resourse->fetch_array(MYSQLI_ASSOC)) $result[] = $row; } else { while ($row = $this->resourse->fetch_array(MYSQLI_ASSOC)) { $key = $row[$keyrow]; if ($unsetKey == true) unset($row[$keyrow]); $result[$key] = $row; } } $this->resourse->close(); return $result; } /* * Метод, возвращающий последний вставленный id. * @return int */ public function lastId() { return $this->connect->insert_id; } /* * Метод, возвращающий выборку из базы в виде простого ассоциативного массива, ключ которого являются выбранными полями: * @param string $key - имя ассоциативного ключа * @param string $value - имя поля в базе * @return array - результат выборки: * Array ( [id=1] = [text= "abc"], [id=2] = [text= "def]) * Array ( [0] = [text= "abc"], [1] = [text= "def]) -- в случае $key == 0 */ public function getSimpleAssocArray($key, $value) { $args = func_get_args(); if (sizeof($args[0]) < 2) throw new Exception("db_error"); $result = Array(); if ($args[0][0]) { while ($row = $this->resourse->fetch_array(MYSQLI_ASSOC)) { $id = $row[$args[0][0]]; $result[$id] = $row[$args[0][1]]; } } else { while ($row = $this->resourse->fetch_array(MYSQLI_ASSOC)) $result[] = $row[$args[0][1]]; } $resourse->close(); return $result; } /* * Метод, возвращающий выборку из базы в виде одномерного ассоциативного массива * @return array - результат выборки: * Array ( [id] = 1, [text] = "abc") */ public function getSimpleArray() { $result = $this->resourse->fetch_array(MYSQLI_ASSOC); $this->resourse->close(); return $result; } /* * Метод, возвращающий выборку из базы в виде переменной * @return string - результат выборки */ public function getValue() { $result = $this->resourse->fetch_array(MYSQLI_NUM); return $result[0]; } /* * Метод, возвращающий ошибки * @param array $vars - переменные * @return string - результат выборки */ public function getErrors() { return date("[d.m.Y H:i] ") . $this->connect->error."<br>Query: ".$this->query_text.'<br>'; } } ?> Про ?s подсмотрел в запросах vasa_c Юзать так: PHP: <?php $query = 'SELECT * FROM `pages` WHERE `id`=?i' $array = $db->query('getArray', $query, $_GET["id"]); PHP: <?php $db = database::getInstance(); $db->query(mixed $method, string $query [, mixed $var [, ...]]); $method: Для UPDATE, DELETE, INSERT возвращается true в случае удачи. $method == noresult Для SELECT: string $method_name -- для вызова метода без аргументов array (string $method_name, mixed $arg [, mixed $arg2 [, ...]]) -- метод с аргументами Методы: getArray([mixed $keyrow ] [, midex $unsetKey]) -- возвращает массив без аргументов: со вторым параметром, равным id: Array ( Array ( [0] => Array ( id ->[1] => Array ( [id] = 1, [id] = 1, [text] = "abc" [text] = "abc" ), ), [1] => Array ( [2] => Array ( [id] = 2, [id] = 2, [text] = "def" [text] = "def" ) ) ) ) Array ( -- со вторым параметром, равным id, и третьим true id ->[1] => Array ( [text] = "abc" ), [2] => Array ( [text] = "def" ) ) lastId() - Метод, возвращающий последний вставленный id. getSimpleAssocArray(string $key, string $value) $key == "id" && $value == "text" $key == 0 && $value == "text" Array ( Array ( -- в случае id ->[1] = [ "abc"] <- text, [0] = ["abc"]<- text, [2] = ["def"] [1] = ["def"] ) ) getSimpleArray() getValue() Array ( mixed value [id] = 1, [text] = "abc" )
имена полей для того, что б подставлять префиксы к таблицам. + у меня есть общий класс-листер для товаров, атрибутов, категорий и тд. Я в него буду только загонять в виде массива поля и таблицу из которой делать выборку, а все остальное он мне сам выведет. Класс твой гляну, может че-нить из него почерпну. А вернее уже почерпнул getInstance. А вот передавать настройки в класс глобальными переменными - имхо весьма плохо. Как сделать так, что бы при вызове метода класса сначала выполнялся не он, а какой-то другой, а потом уже он? То есть есть class A { function a(){} function b(){} function _f(){} } $o = new A; $o->a(); //а на самом деле выполняется сначала _f, а потом уже a();
дело в том, что нужно передавать значения в _f и не массивом. вернее не так. Нужно из 4 методов вынести $argv = func_get_args();
чето не врубился вообще.... Кстати, не хочу раздувать тему аля "А потом надо будет поменять СУБД...", но почему никто не делает обертки прямо наследую от mysqi и обворачивая родные методы? Это че фигово?
бгыг, удалил свое прошлое сообщение, а тему все равно заметили) ну эта, goDB наследует mysqli. есть несколько методов: PHP: <? // ... public function insert() { $argv = func_get_args(); $this->_query($argv); return $this->insert_id; } public function multiQuery() { $argv = func_get_args(); $this->_query($argv, true); return $this->result; } public function formatQuery() { $argv = func_get_args(); return $this->_prepareQuery($argv); } // ... как видно в каждом есть $argv = func_get_args(); вот это я и хочу как-то оптимизировать.
ну по твоему варианту нужны в этих методах различное количество параметров передавать? Верно я понимаю. И ты хочеш избавиться от вызова func_get_args(); в каждом. Тогда убери вообще func_get_args(); и передавай в эти методы массивы со значениями которые надо передать.
так массивы передавать - нифига не удобно. Это мне нужно будет писать array в каждом вызове? $db->query(array('SELECT * FROM ?t WHERE id=?i', 'content', $_GET['id'])); а сейчас так $db->query(SELECT * FROM ?t WHERE id=?i', 'content', $_GET['id']);
А, та ничего там с func_get_args не надо оптимизировать! Какую ты представляешь оптимизацию? В чем выигрыш? Максимум что я могу представить(сделать это наверно не реально), что func_get_args будет написано один раз... Даже строчек кода останется столько же...
гг, вообще я оптимизировать методы хотел в феврале этого года) Сейчас июль уже, полет и так нормальный. Вот нужно добавить плейсхолдеры вида 3?t, что значит что будет подставлен 3 отправленный параметр. Но это пока не критично и сложновато
kostyl Я так делаю Правда я сделал ещё круче - я сделал класс, который может создавать несколько экземпляров mysqli в себе для разных коннекций и доступ по ключевому слову идет к нужной коннекции
Psih ну, дык Database::setInstance($settings, $name = 'db'); Database::getInstance($name = 'db'); $settings - массив настроек (хост, база, логин, пароль, включена отладка или нет, использовать отложенное подключение или нет, префикс таблиц) задай $name другой и другие настройки - и будет у тебя другое подключение.
Сейчас у таблиц есть префиксы, которые забиты в настройках. PHP: <? $this->db->query('SELECT * FROM ?t WHERE a=?i' self::TABLE, $_GET['id']); как видно, таблицы перечисляются через ?t а потом в конце подставляются. Запросы растут. Так делать уже не удобно, начинаю путаться в списках. Какие будут предложения? Возможно что-то типа PHP: <? $this->db->bind(array('main' => self::TABLE))->query('SELECT * FROM :main WHERE a=?i', $_GET['id']);