在 Laravel 5 中处理来自 DomDocument 的 500 内部服务器错误

Handling 500 Internal Server Error from DomDocument in Laravel 5

我为 Laravel 编写的库使用 DomDocument

我在我的控制器下使用这个库,它的命名空间是app/Services/Verify/。当我将一些输入放入表单时,该库会被初始化和使用。

当库失败时,Laravel 将以它应该的方式失败 - return 显示以下消息:Whoops, looks like something went wrong.

我使用以下正则表达式在客户端验证 URL - 'our_team_link' => 'required|url|regex:/^http:\/\/www\.ugcleague\.com\/team_page\.cfm\?clan_id=\d+$/'

下面是上面 URL 的 DomXPath 代码。

    // Generate our team's HTML file
    $this->ourTeamHTML = new \DomDocument;
    $this->ourTeamHTML->loadHTMLFile($this->ourTeamURL);

大多数时候网络应用程序运行良好。但是,在某些情况下,即使他们输入了正则表达式有效的 URL,确实存在 URL 不存在(仍然通过正则表达式),并且出现错误像下面这样得到 returned:

PHP Warning:  DOMDocument::loadHTMLFile(http://www.ugcleague.com/team_page.cfm?clan_id=8831111118): failed to open stream: HTTP request failed! HTTP/1.1 500 Internal Server Error
 in /Users/loop/Code/laravel/app/Services/Verify/ScrapeUGC.php on line 49

Warning: DOMDocument::loadHTMLFile(http://www.ugcleague.com/team_page.cfm?clan_id=8831111118): failed to open stream: HTTP request failed! HTTP/1.1 500 Internal Server Error
 in /Users/loop/Code/laravel/app/Services/Verify/ScrapeUGC.php on line 49

Laravel 将链接到 Whoops, looks like something went wrong 页面。

这让用户感到困惑。我想 return 一个更具描述性的错误,也许 "this team does not exist."

有一个 php 函数可以用来禁用 libxml 错误。

libxml_use_internal_errors(true);

现在,当您处理完脚本后,您将需要获取使用...

生成的任何错误
$errors = libxml_get_errors();

那将是 return 一个数组,因此您现在可以使用...

检查它
if(count($errors) > 0) {
    echo 'This team does not exist';
} else {
    echo 'Successful';
}

// Be sure to clear errors
libxml_clear_errors();

您很可能需要遍历该数组并处理每个错误以确保它是您要查找的特定错误。当使用 DOMDocument 时,每次它发现它不喜欢关于无效 HTML/XML.

的东西时,你一定会得到一堆 notices/warnings

您可以在 Laravel app/Exceptions/Hnadler.php

中处理

注意:我查看了使用 PHP 中提供的 DOMException 处理程序的选项,但是您收到的错误消息并不是真正的 I/O 警告。

这就是 PHP 原生 DomException 的样子:

/**
 * DOM operations raise exceptions under particular circumstances, i.e.,
 * when an operation is impossible to perform for logical reasons.
 * @link http://php.net/manual/en/class.domexception.php
 */
class DOMException extends Exception  {

    /**
     * @var
     * (PHP 5)<br/>
     * An integer indicating the type of error generated
     * @link http://php.net/manual/en/class.domexception.php#domexception.props.code
     */
    public $code;
}

所以我想出了这个,因为我们不能使用 DomException 来指示这个错误,因为它不是异常,你可以在你的 app/Exceptions/Handler.php

中添加它
 <?php

 namespace App\Exceptions;

 use Exception;
 use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;


 class Handler extends ExceptionHandler
 {
      /**
      * A list of the exception types that should not be reported.
      *
      * @var array
      */
      protected $dontReport = [
         \Symfony\Component\HttpKernel\Exception\HttpException::class,
      ];

     /**
     * Report or log an exception.
     *
     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
     *
     * @param  \Exception  $e
     * @return void
     */
     public function report(Exception $e)
     {
         return parent::report($e);
     }

    /**
    * Render an exception into an HTTP response.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  \Exception  $e
    * @return \Illuminate\Http\Response
    */
    public function render($request, Exception $e)
    {

        $message = $e->getMessage();

        if (str_contains($message, 'DOMDocument::loadHTMLFile(): I/O warning')) {
             return redirect($request->fullUrl())->with('error', "This team does not exist");
        }


       //We could also handle DomException like so, but not Dom warning 
       if ($e instanceof \DomException){
            return redirect($request->fullUrl())->with('error', "Your friendly message here");
        }


     }
}

注意:修改 Handler.php 时要小心,如果您不知道自己在做什么,您可能会开始出现空白页面而不是 Laravel 错误。如果不确定,可以在某处备份。