0

Hi I have the following code :

try {
    $sth = $this->container->db->prepare("select  x from table");
    $sth->execute();
    $result = $sth->fetchAll(PDO::FETCH_ASSOC);
    return $result;
} catch (\PDOException $e) {
    throw new ServerException("Could not get data");
} catch (\Exception $e) {
    return false;
}

using slim 3 with wamp the problem is when I point to the API(polling every 1 second) I got the following error:

Fatal error: Call to a member function prepare() on boolean in /

2 issues : it throws an error to the client and it throws an error in php_error.log under wamp and the file becomes bigger

how can I prevent and catch those errors

PDO class:

public function getConnection($dsn, $username, $password) {

    $conn = null;
    try {
        $conn = new PDO($dsn, $username, $password);
        //Set common attributes
        $conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

        return $conn;

    } catch (PDOException $e) {
        return false;
        //TODO: flag to disable errors?
        throw $e;

    }
    catch(Exception $e) {
        die();
        //TODO: flag to disable errors?
        throw $e;

    }
}
Tuz
  • 1,810
  • 5
  • 29
  • 58
  • 1
    You should fix the error so no error message is thrown in the first place. That error means that the db connection failed. You should also check if the connection was successful before trying to use it, instead of assuming it was. – M. Eriksson Dec 21 '17 at 08:22
  • Fatal errors aren't catchable, the only thing I found was this: https://stackoverflow.com/questions/277224/how-do-i-catch-a-php-fatal-error. My best guess is that your first line $this->container->db->prepare() returns false – Niels Dec 21 '17 at 08:23
  • @Niels . how is it possible – Tuz Dec 21 '17 at 08:26
  • Could you post the whole class of the first piece of code? – Niels Dec 21 '17 at 08:29

2 Answers2

1

Like many learners, you are taking this matter upside down

You should never actually catch an exception like this.

it throws an error to the client

Disable it for the whole site on the live server. There should be not a single PHP error message shown to the user, no matter if it's PHP exception or a filesystem error. Set display_errors to a negative value and forget this matter for all.

how can I prevent and catch those errors

Again, you should never do anything like this, bluntly catching every error and just dismissing it. It's like using the notorious @ operator

it throws an error in php_error.log under wamp and the file becomes bigger

Ok, only this one makes sense. There are two possible solutions:

  1. The best one: configure your mysql server properly so it wouldn't die under such a light load like 1 RPS.
  2. Okay, what you actually want but I still don't recommend as it never pays to sweep the dirt under the rug: catch the exception, then verify if it's one you expect, then do something (i.e. try to reconnect after a short timeout), but re-throw the exception otherwise so you will have an idea when something else would go wrong. For this purpose you should add a condition in the try..catch block that should verify the error, handle it if it's one that you expect or just throw it again otherwise.

Of course, in order to catch a PDOException you have to enable it for PDO.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
0

1) In Slim you should use the container (service factory) to build the PDO object. Example:

$container['db'] = function (Container $container) {
    $settings = $container->get('settings');

    $host = $settings['db']['host'];
    $dbname = $settings['db']['database'];
    $username = $settings['db']['username'];
    $password = $settings['db']['password'];
    $charset = $settings['db']['charset'];
    $collate = $settings['db']['collate'];
    $dsn = "mysql:host=$host;dbname=$dbname;charset=$charset";

    $options = [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_PERSISTENT => false,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES $charset COLLATE $collate"
    ];

    return new PDO($dsn, $username, $password, $options);
};

2) You must set the PDO options into the constructor to make it work. Example:

$options = [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
];

$pdo = new PDO($dsn, $username, $password, $options);
odan
  • 4,757
  • 5
  • 20
  • 49