PHP Try and Catch для вставки SQL - PullRequest
       24

PHP Try and Catch для вставки SQL

22 голосов
/ 17 декабря 2009

У меня есть страница на моем веб-сайте (высокий трафик), которая выполняет вставку при каждой загрузке страницы.

Мне любопытен самый быстрый и безопасный способ (поймать ошибку) и продолжить, если система не может выполнить вставку в MySQL. Должен ли я использовать попробовать / поймать или умереть или что-то еще. Я хочу убедиться, что вставка происходит, но если по какой-то причине она не может, я хочу, чтобы страница все равно продолжала загружаться.

...
$db = mysql_select_db('mobile', $conn);
mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'") or die('Error #10');
mysql_close($conn);
...

Ответы [ 9 ]

25 голосов
/ 17 декабря 2009

Проверка документации показывает, что она возвращает false в случае ошибки. Поэтому используйте статус возврата, а не or die(). В случае неудачи он вернет false, что вы можете записать в журнал (или что вы хотите сделать) и затем продолжить.

$rv = mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'");
if ( $rv === false ){
     //handle the error here
}
//page continues loading
10 голосов
/ 10 мая 2011

Это может сделать трюк,

function createLog($data){ 
    $file = "Your path/incompletejobs.txt";
    $fh = fopen($file, 'a') or die("can't open file");
    fwrite($fh,$data);
    fclose($fh);
}
$qry="INSERT INTO redirects SET ua_string = '$ua_string'"   
$result=mysql_query($qry);
if(!$result){
    createLog(mysql_error());
}
7 голосов
/ 07 сентября 2012

Вы можете реализовать исключение бросания при сбое запроса MySQL самостоятельно. Вам нужно написать оболочку для функции mysql_query, например ::100100

// user defined. corresponding MySQL errno for duplicate key entry
const MYSQL_DUPLICATE_KEY_ENTRY = 1022;

// user defined MySQL exceptions
class MySQLException extends Exception {}
class MySQLDuplicateKeyException extends MySQLException {}

function my_mysql_query($query, $conn=false) {
    $res = mysql_query($query, $conn);
    if (!$res) {
        $errno = mysql_errno($conn);
        $error = mysql_error($conn);
        switch ($errno) {
        case MYSQL_DUPLICATE_KEY_ENTRY:
            throw new MySQLDuplicateKeyException($error, $errno);
            break;
        default:
            throw MySQLException($error, $errno);
            break;
        }
    }
    // ...
    // doing something
    // ...
    if ($something_is_wrong) {
        throw new Exception("Logic exception while performing query result processing");
    }

}

try {
    mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'")
}
catch (MySQLDuplicateKeyException $e) {
    // duplicate entry exception
    $e->getMessage();
}
catch (MySQLException $e) {
    // other mysql exception (not duplicate key entry)
    $e->getMessage();
}
catch (Exception $e) {
    // not a MySQL exception
    $e->getMessage();
}
5 голосов
/ 17 декабря 2009

если вы хотите записать ошибку и т. Д., Вы должны использовать try / catch, если вы этого не делаете; просто поставьте @ перед mysql_query

изменить: Вы можете использовать попробовать поймать, как это; так что вы можете зарегистрировать ошибку и позволить странице продолжать загружаться

function throw_ex($er){  
  throw new Exception($er);  
}  
try {  
mysql_connect(localhost,'user','pass'); 
mysql_select_db('test'); 
$q = mysql_query('select * from asdasda') or throw_ex(mysql_error());  
}  
catch(exception $e) {
  echo "ex: ".$e; 
}
2 голосов
/ 17 октября 2014
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

Я не уверен, что есть версия mysql, но добавление этой строки кода позволяет вызвать mysqli_sql_exception.
Я знаю, прошло много времени, и вопрос уже проверен, ответили, но я получил другой ответ, и это может быть полезно.

2 голосов
/ 07 сентября 2012

Обрабатывая ответ yasaluyari, я бы придерживался чего-то вроде этого:

Мы можем просто изменить наш mysql_query следующим образом:

function mysql_catchquery($query,$emsg='Error submitting the query'){
    if ($result=mysql_query($query)) return $result;
    else throw new Exception($emsg);
}

Теперь мы можем просто использовать его вот так, хороший пример:

try {
    mysql_catchquery('CREATE TEMPORARY TABLE a (ID int(6))');
    mysql_catchquery('insert into a values(666),(418),(93)');
    mysql_catchquery('insert into b(ID, name) select a.ID, c.name from a join c on a.ID=c.ID');
    $result=mysql_catchquery('select * from d where ID=7777777');
    while ($tmp=mysql_fetch_assoc($result)) { ... }
} catch (Exception $e) {
    echo $e->getMessage();
}

Обратите внимание, как это красиво. Всякий раз, когда какой-либо из qq терпит неудачу, мы исправляем ошибки. И вы также можете заметить, что нам теперь не нужно сохранять состояние запросов на запись в переменную $result для проверки, потому что наша функция теперь обрабатывает ее сама. И так же, как он обрабатывает выборки, он просто присваивает результат переменной, как и обычная функция, но обрабатывает ошибки внутри себя.

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

0 голосов
/ 10 июля 2018
$new_user = new User($user);
$mapper = $this->spot->mapper("App\User");

try{
    $id = $mapper->save($new_user);     
}catch(Exception $exception){

    $data["error"] = true;
    $data["message"] = "Error while insertion. Erron in the query";
    $data["data"] = $exception->getMessage();

    return $response->withStatus(409)
    ->withHeader("Content-Type", "application/json")
    ->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));        
}

если произойдет ошибка, вы получите что-то вроде этого ->

{
    "error": true,
    "message": "Error while insertion. Erron in the query",
    "data": "An exception occurred while executing 'INSERT INTO \"user\" (...) VALUES (...)' with params [...]:\n\nSQLSTATE[22P02]: Invalid text representation: 7 ERROR:  invalid input syntax for integer: \"default\"" }

с кодом состояния: 409.

0 голосов
/ 25 апреля 2014
    $sql = "INSERT INTO   customer(FIELDS)VALUES(VALUES)";
    mysql_query($sql);
    if (mysql_errno())
    {
            echo "<script>alert('License already registered');location.replace('customerform.html');</script>";
    }   
0 голосов
/ 17 декабря 2009

Используйте любой метод, описанный в предыдущем посте, чтобы как-то перехватить ошибку mysql.
Наиболее распространенным является:

$res = mysql_query('bla');
if ($res===false) {
  //error
  die();
}
//normal page

Это также будет работать:

function error() {
  //error
  die()
}
$res = mysql_query('bla') or error();
//normal page

try { ... } catch {Exception $e) { .... } не будет работать!

Примечание: Не имеет прямого отношения к вашему вопросу, но я думаю, что было бы намного лучше, если бы вы отобразили что-то полезное для пользователя. Я бы никогда не зашел на сайт, который просто отображает пустой экран или какое-либо загадочное сообщение об ошибке.

...