Использование try-catch PDO в функциях

Я подумываю использовать PDO во всех своих будущих Webapp. В настоящее время (используя то, что я узнал из SO до сих пор), то, что у меня есть на моем сайте для обработки соединения с базой данных, является класс Singleton следующим образом:

class DB { private static $instance = NULL; private static $dsn = "mysql:host=localhost;dbname=mydatabase;"; private static $db_user = 'root'; private static $db_pass = '0O0ooIl1'; private function __construct() { } private function __clone() { } public static function getInstance() { if (!self::$instance) { self::$instance = new PDO(self::$dsn, self::$db_user, self::$db_pass); self::$instance-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } return self::$instance; } } 

и другой файл (functions.php) с функциями, специфичными для контента, которые выглядят точно так же:

 function get_recent_activities () { try { $db = DB::getInstance(); // --prepare and execute query here, fetch the result-- return $my_list_of_recent_activities; } catch (PDOException $e) { return "some fail-messages"; } } ... 

что я должен повторить try .. catch часть во всех функциях.

Мои вопросы:

  1. Как я могу сделать это более эффективным? (например, не нужно повторять try..catch во всех функциях и, тем не менее, все еще может возвращать разные «сообщения об try..catch » на каждом из них)
  2. Это уже хорошая практика? Я все еще новичок в PDO и OOP (еще многое предстоит узнать), поэтому (на данный момент) я не вижу никаких недостатков или вещей, которые можно улучшить там.

Извините, если это кажется неясным или слишком длинным. Заранее спасибо.

    Related of "Использование try-catch PDO в функциях"

    Ваша реализация просто прекрасна, и она будет отлично работать для большинства целей.

    Нет необходимости ставить каждый запрос внутри блока try / catch, и на самом деле в большинстве случаев вы на самом деле этого не хотите. Причина этого в том, что если запрос генерирует исключение, это результат фатальной проблемы, такой как синтаксическая ошибка или проблема с базой данных, и это не проблемы, которые вы должны учитывать при каждом запросе, который вы делаете.

    Например:

     try { $rs = $db->prepare('SELECT * FROM foo'); $rs->execute(); $foo = $rs->fetchAll(); } catch (Exception $e) { die("Oh noes! There's an error in the query!"); } 

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

    Вместо этого просто напишите:

     $rs = $db->prepare('SELECT * FROM foo'); $rs->execute(); $foo = $rs->fetchAll(); 

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

     // We're handling a file upload here. try { $rs = $db->prepare('INSERT INTO files (fileID, filename) VALUES (?, ?)'); $rs->execute(array(1234, '/var/tmp/file1234.txt')); } catch (Exception $e) { unlink('/var/tmp/file1234.txt'); throw $e; } 

    Вы хотите написать простой обработчик исключений, который регистрирует или уведомляет вас о ошибках базы данных, которые происходят в вашей производственной среде, и отображает дружественное сообщение об ошибке вашим пользователям, а не трассировку исключений. См. http://www.php.net/set-exception-handler для получения информации о том, как это сделать.

    Несколько предостережений здесь:

    • Этот код написан для учета нескольких унаследованных проблем, таких как ведение журнала базы данных и управление конфигурацией базы данных.
    • Я бы настоятельно рекомендовал вам взглянуть на существующее решение, прежде чем создавать свои собственные. Многие люди думают про себя, когда начинают, что они не хотят использовать существующую инфраструктуру или библиотеку, потому что они слишком большие, требуют слишком много времени для обучения и т. Д., Но после того, как я был одним из этих людей, я не может заявить достаточно решительно, что я оставляю свои пользовательские рамки и классы-оболочки для перехода к структуре. Я хочу переехать в Zend, но есть ряд отличных вариантов.

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

    Вот моя текущая реализация класса оболочки PDO:

     class DB extends PDO { // Allows implementation of the singleton pattern -- ndg 5/24/2008 private static $instance; // Public static variables for configuring the DB class for a particular database -- ndg 6/16/2008 public static $error_table; public static $host_name; public static $db_name; public static $username; public static $password; public static $driver_options; public static $db_config_path; function __construct($dsn="", $username="", $password="", $driver_options=array()) { if(isset(self::$db_config_path)) { try { if(!require_once self::$db_config_path) { throw new error('Failed to require file: ' . self::$db_config_path); } } catch(error $e) { $e->emailAdmin(); } } elseif(isset($_ENV['DB'])) { self::$db_config_path = 'config.db.php'; try { if(!require_once self::$db_config_path) { throw new error('Failed to require file: ' . self::$db_config_path); } } catch(error $e) { $e->emailAdmin(); } } parent::__construct("mysql:host=" . self::$host_name . ";dbname=" .self::$db_name, self::$username, self::$password, self::$driver_options); $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('QueryStatement', array($this))); if(!isset(self::$error_table)) { self::$error_table = 'errorlog_rtab'; } } /** * Return a DB Connection Object * * @return DB */ public static function connect() { // New PDO Connection to be used in NEW development and MAINTENANCE development try { if(!isset(self::$instance)) { if(!self::$instance = new DB()) { throw new error('PDO DB Connection failed with error: ' . self::errorInfo()); } } return self::$instance; } catch(error $e) { $e->printErrMsg(); } } /** * Returns a QueryBuilder object which can be used to build dynamic queries * * @return QueryBuilder * */ public function createQuery() { return new QueryBuilder(); } public function executeStatement($statement, $params = null, $FETCH_MODE = null) { if($FETCH_MODE == 'scalar') { return $this->executeScalar($statement, $params); } try { try { if(!empty($params)) { $stmt = $this->prepare($statement); $stmt->execute($params); } else { $stmt = $this->query($statement); } } catch(PDOException $pdo_error) { throw new error("Failed to execute query:\n" . $statement . "\nUsing Parameters:\n" . print_r($params, true) . "\nWith Error:\n" . $pdo_error->getMessage()); } } catch(error $e) { $this->logDBError($e); $e->emailAdmin(); return false; } try { if($FETCH_MODE == 'all') { $tmp = $stmt->fetchAll(); } elseif($FETCH_MODE == 'column') { $arr = $stmt->fetchAll(); foreach($arr as $key => $val) { foreach($val as $var => $value) { $tmp[] = $value; } } } elseif($FETCH_MODE == 'row') { $tmp = $stmt->fetch(); } elseif(empty($FETCH_MODE)) { return true; } } catch(PDOException $pdoError) { return true; } $stmt->closeCursor(); return $tmp; } public function executeScalar($statement, $params = null) { $stmt = $this->prepare($statement); if(!empty($this->bound_params) && empty($params)) { $params = $this->bound_params; } try { try { if(!empty($params)) { $stmt->execute($params); } else { $stmt = $this->query($statement); } } catch(PDOException $pdo_error) { throw new error("Failed to execute query:\n" . $statement . "\nUsing Parameters:\n" . print_r($params, true) . "\nWith Error:\n" . $pdo_error->getMessage()); } } catch(error $e) { $this->logDBError($e); $e->emailAdmin(); } $count = $stmt->fetchColumn(); $stmt->closeCursor(); //echo $count; return $count; } protected function logDBError($e) { $error = $e->getErrorReport(); $sql = " INSERT INTO " . self::$error_table . " (message, time_date) VALUES (:error, NOW())"; $this->executeStatement($sql, array(':error' => $error)); } } class QueryStatement extends PDOStatement { public $conn; protected function __construct() { $this->conn = DB::connect(); $this->setFetchMode(PDO::FETCH_ASSOC); } public function execute($bound_params = null) { return parent::execute($bound_params); } }