【问题标题】:Unable to handle 'getaddrinfo failed'无法处理“getaddrinfo 失败”
【发布时间】:2017-10-24 18:35:07
【问题描述】:

我有一个连接到数据库的 PHP 应用程序。

连接详细信息(主机名、用户名、密码等)由用户提供。问题是当用户输入一个不存在的主机名时,我收到以下警告:

警告:mysqli::mysqli(): php_network_getaddresses: getaddrinfo 失败

我该如何处理这个错误?我已经在使用 try-catch 并且它可以完美地处理其他异常(错误的用户名或密码),但不是这个。

这是我的代码:

后端.php

<?php
// Library setup
require_once "instlib.php";
$lib = new installer;

// Header
header('Content-Type: application/json; Charset=UTF-8');

try {
    $lib->create_mysqli(array(
        "host" => "a",
        "user" => "b",
        "pass" => "c",
        "database" => "",
        "port" => "3306"
    ));
    echo $lib->build_response("AWESOME!", true);
} catch (Exception $e) {
    echo $lib->build_response($e->getMessage(), false);
}
?>

instlib.php

<?php
require_once 'library.php';
class installer extends nncms
{   
    public function build_response($response = "", $success, $extra = array())
    {
        return json_encode(array_merge(array('success' => $success, 'response' => $response),$extra));
    }
}
?>

库.php

<?php
class nncms
{   
    var $mysqli;

    public function create_mysqli($config)
    {
        // Set MySQLi to throw expection instead of warning
        mysqli_report(MYSQLI_REPORT_STRICT);

        // Connection setup
        $mysqli = new mysqli(
            $config["host"],
            $config["user"],
            $config["pass"],
            $config["database"],
            $config["port"]
        );
        $mysqli->set_charset('utf8mb4');

        // In case of an error that somehow didn't throw an exception
        if ($mysqli->connect_errno)
            throw new Exception("Connection error: ".$mysqli->connect_error);

        // Set MySQLi object of class
        $this->mysqli = $mysqli;
    }
}
?>

【问题讨论】:

    标签: php mysqli


    【解决方案1】:

    要在有Warning 时更改 PHP 的行为,有几个选项。

    第一个选项,使用error suppressor operator @您不想这样做。它“有效”,但是当您找不到错误的原因时,它会给您带来麻烦。

    if ($db = @mysqli_connect("a", "a", "a", "a")) {
        // connected
    }
    

    更好的选择是在遇到Warning 时使用set_error_handler() 抛出ErrorException。这将让您像Exceptions 一样优雅地处理错误:

    function errorHandler($errno, $errstr, $errfile, $errline) {
        throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
    }
    set_error_handler("errorHandler");
    try {
        if ($db = mysqli_connect("a", "a", "a", "a")) {
            // connected
        }
    }
    catch(ErrorException $e) {
        echo "Exception: ".$e->getMessage();
    }
    

    【讨论】:

    • 这不是 MYSQLI_REPORT_STRICT 的用途吗?根据documentation,“为错误而不是警告抛出 mysqli_sql_exception”。为什么它可以处理错误的用户名,但不能处理无效的主机名?
    • 是的,您的代码应该可以正确捕获它,但无论如何都会显示Warning。这就是为什么你需要使用set_error_handler()
    • 您的代码有效,但我仍然不明白为什么 MYSQLI_REPORT_STRICT 无法使用主机名。
    • 它们是不同类型的错误。如果 PHP 无法连接到主机名,则会显示该警告,因为调用级别较低且与 mysqli 无关。 OTOH,当用户名错误时,PHP 已经连接,但是 MySQL 拒绝了凭据,所以你得到了你的 mysqli_sql_exception 正确。
    • 没错。可以这样想:PHP first 尝试转到http://wrong.hostname。如果它有效,它将继续使用 MySQL 流程。如果没有,则显示Warning
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多