PHP & WP: try catch not working when error from DB

2020-04-14 08:14发布

I'm currently trying to write error handling for the following situation. I want to be able to catch an error when a data base is --read-only and is trying to write.

WordPress database error INSERT command denied to user 'readonly'@

This error is thrown because the database is a --read-only and is trying to write into the database. However, this error should have been caught by my catch conditional.

function drools_request($data, $uid) {
  try {
    $db = _get_db();
    $db->insert("requests", [
      "uid" => $uid,
      "data" => json_encode($data),
    ]);
  }
  catch(Error $e){
    echo 'Error writing to database: ',  $e->getMessage(), "\n";
  }
}

As you see from the above snippet the $db->insert( method correctly breaks because is trying to write into a $db instance that is --read-only. However, the catch(Error $e) did not work, why?

Here is the full class:

    <?php

namespace StatCollector;

function drools_request($data, $uid) {
  try {
    $db = _get_db();
    $db->insert("requests", [
      "uid" => $uid,
      "data" => json_encode($data),
    ]);
  }
  catch(Exception $e)
  {
    echo 'Error writing to database: ',  $e->getMessage(), "\n";
  }
}

function drools_response($response, $uid) {
  try {
    $db = _get_db();
    $db->insert("responses", [
      "uid" => $uid,
      "data" => json_encode($response),
    ]);
  }
  catch(Exception $e)
  {
    echo 'Error writing to database: ',  $e->getMessage(), "\n";
  }
}

function results_sent($type, $to, $uid, $url = null, $message = null) {
  try {
    $db = _get_db();
    $db->insert("messages", [
      "uid" => $uid,
      "msg_type" => strtolower($type),
      "address" => $to,
      "url" => $url,
      "message" => $message
    ]);
  }
  catch(Exception $e)
  {
    echo 'Error writing to database: ',  $e->getMessage(), "\n";
  }
}

function peu_data($staff, $client, $uid) {
  try {
    if (empty($uid)) {
      return;
    }
    $db = _get_db();

    if (! empty($staff)) {
      $db->insert("peu_staff", [
        "uid" => $uid,
        "data" => json_encode($staff)
      ]);
    }
    if (! empty($client)) {
      $db->insert("peu_client", [
        "uid" => $uid,
        "data" => json_encode($client)
      ]);
    }
  }
  catch(Exception $e)
  {
    echo 'Error writing to databse: ', $e->getMessage(), "\n";
  }
}

function response_update() {
  $uid = $_POST['GUID'];
  $url = $_POST['url'];
  $programs = $_POST['programs'];
  if (empty($uid) || empty($url) || empty($programs)) {
    wp_send_json(["status" => "fail","message" => "missing values"]);
    return wp_die();
  }

  try {
    $db = _get_db();
    $db->insert("response_update", [
      "uid" => $uid,
      "url" => $url,
      "program_codes" => $programs
    ]);
    wp_send_json(["status" => "ok"]);
    wp_die();
  }
  catch(Exception $e)
  {
    echo 'Error writing to database: ', $e->getMessage(), "\n";
  }
}

Why is the try and catch not working? What can I do to solve this issue? this post didn't work. PHP try/catch and fatal error

2条回答
祖国的老花朵
2楼-- · 2020-04-14 08:28

In PHP, both Error and Exception implement the Throwable interface, but an Error is not a subclass of Exception.

You need to use:

catch(Exception $e) ...

Besides that, you should know that PHP database connectors like PDO and Mysqli don't throw exceptions by default. The calling application has to enable exceptions.

Wordpress doesn't enable the database connector to throw exceptions.

See this blog for some examples of error handling in Wordpress:

https://medium.com/the-metric/modern-wordpress-development-you-should-throw-an-exception-when-you-encounter-a-wp-error-81fb82275cbd

WordPress methods like wp_insert_user don’t throw exceptions when they fail, but instead — and in some cases only if you tell the method to — return a WP_Error object.

查看更多
Lonely孤独者°
3楼-- · 2020-04-14 08:43

Your code is in a custom namespace:

namespace StatCollector;

so this code:

catch (Exception $ex)

is looking for an exception class of \StatCollector\Exception, which isn't what's thrown: \Exception is.

Since the Error and Exception classes are in the root namespace, you need to do:

catch (\Exception $ex)

and/or:

catch (\Error $ex)

or just:

catch (\Throwable $t)

then also follow Bill Karwin's advice above.

查看更多
登录 后发表回答