Problem:
Finding best practice for error handling using PDO. The options I have found on websites, SO, books, etc.
That's a very good question, but there is one wrong premise at the very beginning: you are taking error reporting for PDO separated from site-wide error reporting. Which makes very little sense: PDO errors in every way are the same as other errors - filesystem errors, HTTP errors, and so on. Thus, there is no reason in establishing PDO-only error reporting. All you need is to properly set site-wide error reporting.
There is also one wrong assumption regarding php.ini inaccessibility: you can always set any configuration directive using ini_set() function. Thus, here is not a single reason in setting error_reporting to disastrous level of 0.
To answer the rest of your questions all you need is a little common sense.
A great number of websites say you should echo your error messages in your catch block. A large number of users on SO say that you should never echo error messages due to security risks.
What you think yourself? Does it any good showing system error messages to user? Does it any good showing system internals to a malicious user?
Others are recommending logging it to a log file outside the document root.
Do you have any objections for this?
Some use error handling to log it to a SQL table.
Don't you think it's quite contradicting idea - to log database errors into database?
What is the best practice for handling errors in general in PHP?
You have shown it already: display in dev and log in prod. All is controlled site-wide through few simple configuration options.
What is the best practice for handling errors in the catch-block?
NOT to use try-catch block for error reporting at all. You aren't going to write a catch block with a friendly error message for the every query in your app, as it's suggested in the other answer, are you?
Thus your code have to be
<?php
// Error handling
error_reporting(-1);
ini_set('display_errors',0);
ini_set('log_errors',1);
// Get credentials from outside document root
require_once('../settings.php');
// Tests connection to database
$dbh = new PDO(
sprintf(
'mysql:host=%s;dbname=%s;port=%s;charset=%s',
$settings['host'],
$settings['name'],
$settings['port'],
$settings['charset']
),
$settings['username'],
$settings['password']
);
// Prevents emulated prepares and activates error handling
// PDO::ERRMODE_EXCEPTION
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Now to the question you voiced in the comment.
A custom error screen is a very different matter and your code is especially bad with it. Neither it should be a 404 error nor an HTTP redirect have to be used (thats very bad for SEO).
To create a custom error page you have to use either your web-server features (preferred) or an error handler in PHP script.
When encountering a fatal error (and uncaught exception is one), PHP responds not with 200 OK HTTP status but with 5xx status. And every web-server can catch this status and show an according error page. E.g. for Apache it would be
ErrorDocument 503 server_error.html
where you can write whatever excuses you want.
Or you can set up a custom error handler in PHP which would handle all PHP errors as well, an example can be seen in the article I wrote on the matter: The (im)proper use of try..catch.