Php 使用PDO处理错误的最佳实践

Php 使用PDO处理错误的最佳实践,php,mysql,pdo,error-handling,database-connection,Php,Mysql,Pdo,Error Handling,Database Connection,问题: <?php // Error handling error_reporting(0); // Get credentials from outside document root require_once('../settings.php'); // Tests connection to database try { $dbh = new PDO( sprintf( 'mysql:host=%

问题:

<?php
  // Error handling
  error_reporting(0);

  // Get credentials from outside document root
  require_once('../settings.php');

  // Tests connection to database
  try {
    $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);
  }
  // Catches errors raised by PDO
  catch (PDOException $e) {
    // Prints error messages to file
    file_put_contents('/home/ubuntu/errors.log', 'Error: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
    // Shows generic error message to user
    header('Location: 404.php');
    exit;
  }
?>
寻找使用PDO处理错误的最佳实践。我在网站上找到的选项,所以,书籍,等等

  • 很多网站都说你应该在
    catch
    块中回显错误消息
  • 上的大量用户表示,由于存在安全风险,您不应回显错误消息
  • 其他人则建议将其记录到文档根目录之外的日志文件中
  • 有些人使用错误处理将其记录到SQL表中 有了大量的选项,你很容易就会被你应该使用的选项淹没。当然,您可以使用MVC框架,让它为您处理错误日志记录,但是如果您不使用MVC,它会是什么样子呢

    据我所知,在开发环境中,错误处理应该如下所示:

    display_errors = On
    display_startup_errors = On
    error_reporting = -1
    log_errors = On
    
    display_errors = Off
    display_startup_errors = Off
    error_reporting = E_ALL
    log_errors = On
    
    或者,如果无法访问php.ini文件:

    error_reporting(-1);
    ini_set("display_errors", 1);
    
    error_reporting(0);
    
    生产环境中

    display_errors = On
    display_startup_errors = On
    error_reporting = -1
    log_errors = On
    
    display_errors = Off
    display_startup_errors = Off
    error_reporting = E_ALL
    log_errors = On
    
    或者,如果无法访问php.ini文件:

    error_reporting(-1);
    ini_set("display_errors", 1);
    
    error_reporting(0);
    
    以生产环境中的数据库连接为例

    代码:

    <?php
      // Error handling
      error_reporting(0);
    
      // Get credentials from outside document root
      require_once('../settings.php');
    
      // Tests connection to database
      try {
        $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);
      }
      // Catches errors raised by PDO
      catch (PDOException $e) {
        // Prints error messages to file
        file_put_contents('/home/ubuntu/errors.log', 'Error: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
        // Shows generic error message to user
        header('Location: 404.php');
        exit;
      }
    ?>
    
    
    
    问题:

    <?php
      // Error handling
      error_reporting(0);
    
      // Get credentials from outside document root
      require_once('../settings.php');
    
      // Tests connection to database
      try {
        $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);
      }
      // Catches errors raised by PDO
      catch (PDOException $e) {
        // Prints error messages to file
        file_put_contents('/home/ubuntu/errors.log', 'Error: ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
        // Shows generic error message to user
        header('Location: 404.php');
        exit;
      }
    ?>
    
    • 在PHP中处理一般错误的最佳实践是什么
    • 处理catch块中错误的最佳实践是什么

    这是一个很好的问题,但在一开始就有一个错误的前提:您将PDO的错误报告与站点范围的错误报告分开。这没有什么意义:PDO错误在各个方面都与其他错误相同——文件系统错误、HTTP错误等等。因此,没有理由只建立PDO错误报告。您只需正确设置站点范围的错误报告

    关于php.ini不可访问性还有一个错误的假设:始终可以使用ini_set()函数设置任何配置指令。因此,将error_reporting设置为灾难性级别0并不是唯一的原因

    要回答剩下的问题,你只需要一点常识

    很多网站都说你应该在catch块中回显错误消息。 上的大量用户表示,由于存在安全风险,您不应回显错误消息

    你觉得自己怎么样?向用户显示系统错误消息有什么好处吗?向恶意用户展示系统内部有什么好处吗

    其他人则建议将其记录到文档根目录之外的日志文件中

    你对此有什么反对意见吗

    有些人使用错误处理将其记录到SQL表中

    难道你们不认为将数据库错误记录到数据库中是一个非常矛盾的想法吗

    在PHP中处理一般错误的最佳实践是什么

    您已经展示了它:在dev中显示并在prod中登录。所有这些都是通过几个简单的配置选项在站点范围内控制的

    处理catch块中错误的最佳实践是什么

    完全不要使用try-catch-block进行错误报告。您不会像另一个答案中建议的那样,为应用程序中的每个查询编写包含友好错误消息的catch-block
    ,是吗

    因此,您的代码必须是

    <?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);
    
    在那里你可以写任何你想要的借口


    或者,您可以在PHP中设置一个自定义错误处理程序,该程序也可以处理所有PHP错误,我在关于此问题的文章中给出了一个示例:

    不向用户显示错误消息听起来并不优雅。我的意思是,即使Facebook在出现错误时也会显示一般错误。在您的示例中,没有显示此类一般错误。这真的是一种优雅的错误处理方式吗?谢谢你的更新!您能否举例说明自定义错误处理程序的外观,以便了解如何实现这些错误处理程序?如果没有,你能给一个链接到一篇讨论这个问题的文章吗?只是试图充实出一个合理的错误处理方法。我特别感兴趣的是这样的处理程序如何处理显示自定义错误消息。感谢链接,非常有用。我沿着路径找到了
    set\u error\u handler()
    set\u exception\u handler()
    ,这让我进入了一个有趣的世界。但有一件事让我困惑,为什么在一个处理程序中使用include(),而在另一个处理程序中使用readfile()?这只是一个复制粘贴错误。在原始代码中包含一个php文件,只是为了在错误页面上显示广告。感谢您的澄清。我已经采纳了您的所有建议,并编写了三个功能,希望您在有时间的情况下继续考虑: