Intereting Posts

подготовленные заявления – создание единого метода *

FYI. закончил с PDO решением, поскольку это было проще.

Я пытаюсь добавить один метод для обработки всех запросов в базу данных. Я хочу, чтобы запросы использовали привязку параметров. Как обрабатывать переменное количество параметров функции в mysqli_stmt_bind_param() ?

Этот пост привел меня к пониманию преимуществ привязки параметров.

Вот мой примерный код, где я сейчас застрял, отмечен.

ВХОДНЫЕ ПАРАМЕТРЫ

  $query = "INSERT INTO b0 VALUES (?, ?, ?)" $par_arr = {'bookmark', 'http://www.bookmark.com', 'tag'} 

КОД ПРОТОТИПОВ

  protected static function query($query, $par_arr) { if($statement=mysqli_prepare(one::$db, $query) { mysqli_stmt_bind_param($statement, "s", ...variable amount of parameters...);<----how should this be handled? ... 

Обновление 2: Если у вас возникнут какие-либо дополнительные проблемы с этим кодом, вы должны, вероятно, следовать этому совету и использовать PDO.

Вот как вы должны использовать call_user_func_array [docs] :

 protected static function query($query, $types, $values) { if($statement = mysqli_prepare(one::$db, $query) { $parameters = array_merge(array($statement, $types), $values); call_user_func_array('mysqli_stmt_bind_param', $parameters); // ... } } 

где $types – строка, указывающая тип каждого значения, как описано в документации call_user_func_array ( call_user_func_array упоминается call_user_func_array ).


Обновление. Кажется, это не так просто, и вам сначала нужно создать ссылки на значения:

  foreach($values as $k => $v) { $values[$k] = &$v; } $parameters = array_merge(array($statement, $types), $values); call_user_func_array('mysqli_stmt_bind_param', $parameters); // ... 

call_user_func_array предназначен для определенных пользователем функций на php.net

Нет, это не так. Первым параметром является callback типа, и в документации говорится (внимание мое):

Функция PHP передается по имени в виде строки. Любая встроенная или определяемая пользователем функция может использоваться, за исключением языковых конструкций, таких как: array (), echo (), empty (), eval (), exit (), isset (), list (), print () или unset ().

Следующее замечание:

просто используется для упрощения синтаксиса для передачи массивов в определенные пользователем функции

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

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

 private function prepareQuery($args) { $raw = $query = array_shift($args); preg_match_all('~(\?[az?])~',$query,$m,PREG_OFFSET_CAPTURE); $pholders = $m[1]; $count = 0; foreach ($pholders as $i => $p) { if ($p[0] != '??') { $count++; } } if ( $count != count($args) ) { throw new E_DB_MySQL_parser("Number of args (".count($args).") doesn't match number of placeholders ($count) in [$raw]"); } $shift = 0; $qmarks = 0; foreach ($pholders as $i => $p) { $pholder = $p[0]; $offset = $p[1] + $shift; if ($pholder != '??') { $value = $args[$i-$qmarks]; } switch ($pholder) { case '?n': $value = $this->escapeIdent($value); break; case '?s': $value = $this->escapeString($value); break; case '?i': $value = $this->escapeInt($value); break; case '?a': $value = $this->createIN($value); break; case '?u': $value = $this->createSET($value); break; case '??': $value = '?'; $qmarks++; break; default: throw new E_DB_MySQL_parser("Unknown placeholder type ($pholder) in [$raw]"); } $query = substr_replace($query,$value,$offset,2); $shift+= strlen($value) - strlen($pholder); } $this->lastquery = $query; return $query; } 

и таким образом запрос вставки можно назвать простым

 $db->run("INSERT INTO table SET ?u",$data); 

Я добавил полный код для создания единого метода для выбранного подготовленного оператора и вставки подготовленного оператора. Пожалуйста, следуйте инструкциям и прочитайте все комментарии. создать базу данных с именем «test» и добавить следующий запрос для создания таблицы «users» в

 CREATE TABLE IF NOT EXISTS `users` ( `users_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `first_name` varchar(100) NOT NULL, `last_name` varchar(100) NOT NULL, PRIMARY KEY (`users_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ; INSERT INTO `users` (`users_id`, `first_name`, `last_name`) VALUES (1, 'daniel', 'martin'), (2, 'daniel', 'martin'); <?php error_reporting(E_ALL); ini_set('display_errors',1); session_start(); class mysqli_access extends mysqli{ private $ip1; private $dbconn; private $hostname = HST; // hostname private $username = USR; // username private $password = PWD; // password private $dbname = DBN; // datbase name function mysqli_access() { $ip= $_SERVER['REMOTE_ADDR']; $ip1="ip_".str_replace('.', "", $ip); if(!is_resource($_SESSION[$ip1])) { $this->dbconn = new mysqli($this->hostname,$this->username,$this->password,$this->dbname); $_SESSION[$ip1] = $this->dbconn; $dbconn = $this->dbconn; if( $this->connect_error ) { $this->Display_error('', $this->connect_errno, $this->connect_error, __FUNCTION__); } } else { $this->dbconn = $_SESSION[$ip1]; // success } return $this->dbconn; } function SelectPrepared($sql,$types,$params,$rows = '') { $results = array(); if ($stmt = $this->dbconn->prepare($sql)) { if($types&&$params) { $bind_names[] = $types; for ($i=0; $i<count($params);$i++) { $bind_name = 'bind' . $i; $$bind_name = $params[$i]; $bind_names[] = &$$bind_name; } $return = call_user_func_array(array($stmt,'bind_param'),$bind_names); } $stmt->execute(); /* execute query */ $meta = $stmt->result_metadata(); while ($field = $meta->fetch_field()) { $var = $field->name; $$var = null; $fields_arr[$var] = &$$var; } call_user_func_array(array($stmt,'bind_result'),$fields_arr); if($rows == 1){ while ($stmt->fetch()) { $results = array(); foreach($fields_arr as $k => $v) $results[$k] = $v; } }else{ $i = 0; while ($stmt->fetch()) { $results[$i] = array(); foreach($fields_arr as $k => $v) $results[$i][$k] = $v; $i++; } } return $results; } } public function InsertPrepared($tblName,$arrFieldNameValue,$replace_flag=0){ $TableName = $tblName; if($replace_flag==0) { $sqlFirst ="INSERT INTO " . $TableName . "("; } if($replace_flag==1) { $sqlFirst ="INSERT IGNORE INTO " . $TableName . "("; } if($replace_flag==2) { $sqlFirst ="REPLACE INTO " . $TableName . "("; } $sqlSecond =" values("; $params = array(); $types = ''; while(list($key,$value) = each($arrFieldNameValue)) { $sqlFirst = $sqlFirst . $key . ","; $sqlSecond = $sqlSecond . '?' . ","; $params[] = $value; $types = $types . $this->GetValType($value); } $sqlFirst = substr($sqlFirst,0,strlen($sqlFirst)-1) . ") "; $sqlSecond = substr($sqlSecond,0,strlen($sqlSecond)-1) .")"; $sql = $sqlFirst . $sqlSecond; if ($stmt = $this->dbconn->prepare($sql)) { if($types&&$params) { $bind_names[] = $types; for ($i=0; $i<count($params);$i++) { $bind_name = 'bind' . $i; $$bind_name = $params[$i]; $bind_names[] = &$$bind_name; } $return = call_user_func_array(array($stmt,'bind_param'),$bind_names); } $stmt->execute(); /* execute query */ } return mysqli_insert_id($this->dbconn); } private function GetValType($Item) { switch (gettype($Item)) { case 'NULL': case 'string': return 's'; break; case 'integer': return 'i'; break; case 'blob': return 'b'; break; case 'double': return 'd'; break; } return 's'; } } class Model_NAME extends mysqli_access { function Model_NAME() { $this->tablename = TABLENAME; $this->mysqli_access(); } ##---------------------------- Custom function start from here -----------------# ## fetch settings values function getUserRow($id,$key) { $sql ="SELECT first_name,last_name FROM ".$this->tablename." WHERE first_name=? and users_id = ?"; $param = "si"; $array_of_params[] = addslashes($key); $array_of_params[] = addslashes($id); $result= $this->SelectPrepared($sql,$param,$array_of_params,1); //last parameter 1 use if want fetch single row , other wise function will return multi dimensional array return $result; } ## fetch settings values function getUserRows($last_name) { $sql ="SELECT first_name,last_name FROM ".$this->tablename." WHERE last_name= ?"; $param = "s"; $array_of_params[] = addslashes($last_name); $result= $this->SelectPrepared($sql,$param,$array_of_params); //last parameter 1 use if want fetch single row , other wise function will return multi dimensional array return $result; } function addValue($Array) { return $this->InsertPrepared( $this->tablename , $Array); } } // configuration define('HST','localhost'); define('USR','root'); define('PWD','techmodi'); define('DBN','test'); define('TABLENAME','users'); $obj = new Model_NAME(); $arr = array(); $arr['first_name'] = addslashes("daniel"); $arr['last_name'] = addslashes("martin"); $obj->addValue($arr); // for insert records // after inserting get the records $singleRow = $obj->getUserRow(1,'daniel'); // for select single records $multiRow =$obj->getUserRows('martin'); // for select records echo '<pre>'; echo '<br/>-------- Single Records -----------------<br/>'; print_r($singleRow); echo '<br/>-------- Multiple Records-----------------<br/>'; print_r($multiRow); ?>