MySQLi: запрос VS подготовить - PullRequest
       6

MySQLi: запрос VS подготовить

10 голосов
/ 24 февраля 2011

Есть кое-что, чего я совсем не понимаю, это 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();
    }

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

$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 - почему мы должны иметь это во-первых! ??

Спасибо.

Ответы [ 2 ]

22 голосов
/ 24 февраля 2011

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

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

...
WHERE col1 = ? AND col2 = ?

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

0 голосов
/ 28 июня 2011

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

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

while($stmt->fetch()) {

    //to dereference
    $row_copy = $parameters;
    $return_array[] = $row_copy;

}

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

return $return_array;
...