MySQLi: запрос VS готовят

Есть кое-что, что я совсем не совсем понимаю, это prepare и query в mysqli.

Этот метод использует mysqli::query для обработки запроса, и было известно о отсутствии безопасности:

 public function fetch_assoc($query) { $result = parent::query($query); //$result = self::preparedStatement($query); if($result) { return $result->fetch_assoc(); } else { # call the get_error function return self::get_error(); # or: # return $this->get_error(); } } 

это тот, с помощью метода prepare-bind-execute, который, как я полагаю, имеет лучшую безопасность,

 public function fetch_assoc_stmt($sql,$types = null,$params = null) { # create a prepared statement $stmt = parent::prepare($sql); # bind parameters for markers # but this is not dynamic enough... //$stmt->bind_param("s", $parameter); 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); } # execute query $stmt->execute(); # these lines of code below return one dimentional array, similar to mysqli::fetch_assoc() $meta = $stmt->result_metadata(); while ($field = $meta->fetch_field()) { $var = $field->name; $$var = null; $parameters[$field->name] = &$$var; } call_user_func_array(array($stmt, 'bind_result'), $parameters); while($stmt->fetch()) { return $parameters; } # close statement $stmt->close(); } в public function fetch_assoc_stmt($sql,$types = null,$params = null) { # create a prepared statement $stmt = parent::prepare($sql); # bind parameters for markers # but this is not dynamic enough... //$stmt->bind_param("s", $parameter); 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); } # execute query $stmt->execute(); # these lines of code below return one dimentional array, similar to mysqli::fetch_assoc() $meta = $stmt->result_metadata(); while ($field = $meta->fetch_field()) { $var = $field->name; $$var = null; $parameters[$field->name] = &$$var; } call_user_func_array(array($stmt, 'bind_result'), $parameters); while($stmt->fetch()) { return $parameters; } # close statement $stmt->close(); } 

Однако оба этих метода возвращают один и тот же результат,

 $mysqli = new database(DB_HOST,DB_USER,DB_PASS,DB_NAME); $sql = " SELECT * FROM root_contacts_cfm ORDER BY cnt_id DESC "; print_r($mysqli->fetch_assoc_stmt($sql)); print_r($mysqli->fetch_assoc($sql)); 

они печатают это:

 Array ( [cnt_id] => 2 [cnt_email1] => lau@xx.net [cnt_email2] => [cnt_fullname] => Lau T [cnt_firstname] => Thiam [cnt_lastname] => Lau [cnt_organisation] => [cnt_website] => [cnt_biography] => [cnt_gender] => [cnt_birthday] => [cnt_address] => [cnt_postcode] => [cnt_telephone] => [cnt_note] => [cnt_key] => [cat_id] => [tcc_id] => [cnt_suspended] => 0 [cnt_created] => 2011-02-04 00:00:00 [cnt_updated] => 2011-02-04 13:54:36 ) Array ( [cnt_id] => 2 [cnt_email1] => lau@xx.net [cnt_email2] => [cnt_fullname] => Lau T [cnt_firstname] => Thiam [cnt_lastname] => Lau [cnt_organisation] => [cnt_website] => [cnt_biography] => [cnt_gender] => [cnt_birthday] => [cnt_address] => [cnt_postcode] => [cnt_telephone] => [cnt_note] => [cnt_key] => [cat_id] => [tcc_id] => [cnt_suspended] => 0 [cnt_created] => 2011-02-04 00:00:00 [cnt_updated] => 2011-02-04 13:54:36 ) 

Вы должны были заметить, что внутри метода fetch_assoc_stmt я вообще не использую fetch_assoc . Вероятно, вообще никакой возможности использовать его, поскольку prepare использует другой способ возврата результата.

Итак, мой вопрос заключается в том, что использование метода prepare лучше, чем query , почему вообще должен быть fetch_assoc ? Разве мы не должны просто забывать об этом или не должны ли php.net осуждать это? Это то же самое для fetch_all – зачем нам это делать в первую очередь! ??

Благодарю.

Подготовленные утверждения предпочтительнее простых SQL-запросов, когда вы используете параметры для динамического генерации запроса. В вашем примере ваш SQL не содержит переменных, поэтому использование простого запроса или подготовленного оператора функционально эквивалентно.

Когда вы должны изменить значения параметров, например, в WHERE , тогда подготовленные операторы дадут вам дополнительную безопасность:

 ... WHERE col1 = ? AND col2 = ? 

Но когда ваш запрос прост и исправлен, может потребоваться меньше кода для использования $mysqli->query($sql) вместе с fetch_assoc() . Использование прямых запросов, а не готовых заявлений, не является повсеместно плохой практикой, так как некоторые могут вам верить. Когда ваш запрос требует параметризации или когда один и тот же запрос необходимо скомпилировать и выполнить повторно, вы получите выгоду от подготовленного оператора.

Извините, что это не ответ, но я недостаточно хорош, чтобы оставить комментарий.

Похоже, в вашей второй функции есть ошибка. Ваш код не будет работать правильно для запросов, которые возвращают более одной строки. Не должно быть этого заявления:

 while($stmt->fetch()) { //to dereference $row_copy = $parameters; $return_array[] = $row_copy; } 

И тогда функция должна заканчиваться:

 return $return_array;