Laravel 4.2中的自定义404与布局

问题描述 投票:3回答:7

我的页面使用全局布局,并且有许多视图使用自己的控制器使用此布局。从控制器操作调用的视图如下:

class NewsController extends BaseController {

  protected $layout = 'layouts.master';

  public function index()
  {
    $news = News::getNewsAll();

    $this->layout->content = View::make('news.index', array(
        'news' => $news
    ));
  }
}

我想以相同的方式创建自定义404页面,因为我需要嵌套自定义404设计的常规页面布局。有可能吗?问题是我无法从控制器将HTTP状态代码设置为404,所以它只是一个软404。我知道正确的方法是从Response::view('errors.404', array(), 404)filter.php发送App::missing(),但是我不能在那里设置布局,只是视图还不够。或者我错了,有可能以某种方式?

谢谢!

更新:我已经用我在项目中使用的文件为这个问题创建了一个Gist。也许有助于更多地理解我目前的状态。

php layout laravel-4 error-handling
7个回答
7
投票

这是我的方法。只需将以下代码添加到/app/start/global.php文件即可

App::missing(function($exception)
{
    $layout = \View::make('layouts.error');
    $layout->content = \View::make('views.errors.404');
    return Response::make($layout, 404);
});

5
投票

您可以通过在global.php上添加类似的内容来创建必要的错误视图。

App::error(function(Exception $exception, $code)
{
    $pathInfo = Request::getPathInfo();
    $message = $exception->getMessage() ?: 'Exception';
    Log::error("$code - $message @ $pathInfo\r\n$exception");

    if (Config::get('app.debug')) {
        return;
    }

    switch ($code)
    {
        case 403:
            return Response::view( 'error/403', compact('message'), 403);

        case 500:
            return Response::view('error/500', compact('message'), 500);

        default:
            return Response::view('error/404', compact('message'), $code);
    }
});

您还可以查看一些可用的laravel-starter-kit软件包,并检查它们是如何做的。这是我的laravel-admin-template版本


1
投票

我不能告诉你这是最好的方法还是被认为是最佳实践但是和你一样我很沮丧并且在Illuminate \ Routing \ Controller中使用callAction方法找到了另一种解决方案。

应用程序/启动/ global.php

App::missing(function($exception)
{
    return App::make("ErrorController")->callAction("missing", []);
});

应用程序/控制器/ ErrorController.php

<?php

class ErrorController extends BaseController {

    protected $layout = 'layouts.master';

    public function missing()
    {
        $this->layout->content = View::make('errors.missing');
    }
}

希望能帮助到你!


1
投票

我知道我迟到了,但由于这个问题仍未得到答复,并且在查询的搜索结果中排名相对较高,“异常处理程序中的Laravel 404错误”。只是因为这个SO页面仍然是一个常见问题而且没有标记解决方案我想为许多用户添加更多信息和另一种可能的解决方案。

当你按照这里和其他地方提供的方法并使用app / start / global.php文件来实现App:error()时,应该注意base_controller在这个文件之后被实例化,所以你可能会传入普通视图的任何变量文件(例如$ user)未设置。如果您正在扩展的模板中引用了这些变量中的任何一个,则会出现错误。

如果您重新访问视图文件并检查是否使用isset()设置变量并通过设置默认值来处理false条件,您仍然可以扩展模板。

例如;

@yield('styles')
<style type="text/css">
body{
    background-color: {{ $user->settings->bg_color }};
}
</style>

以上将抛出报告的错误,因为在执行此操作时没有$ user对象。通常的异常处理程序会提供更多详细信息,但是为了实际显示404页面而禁用该功能,因此您几乎无需继续操作。但是,如果使用isset()或empty(),则可以使用案例。

<style type="text/css">
body{
    @if(isset($user))
        background-color: {{ $user->settings->bg_color }};
    @else
        background-color: #FFCCFF;
    @endif
}
</style>

如果您的顶级布局或头文件中有许多引用,这个简单的解决方案就无济于事。您可能需要将@extends从核心布局更改为自定义布局。例如。景色/布局/ errors.blade.php。

然后在你的404.blade.php中你会做这样的事情

@extends('layouts.errors')

并使用不依赖于$ user(或其他)的新标头创建views / layouts / errors.blade.php。

希望有所帮助。


1
投票

我在这个问题上抓了一下,这是解决方案:

在app / start / global.php中:

App::error(function(Exception $exception, $code) {
    if ($exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException) {
      Log::error('NotFoundHttpException Route: ' . Request::url() );
    }

    Log::error($exception);

    // HTML output on staging and production only
    if (!Config::get('app.debug'))
        return App::make("ErrorsController")->callAction("error", ['code'=>$code]);
});

(注意:以上代码段仅在调试模式为true的环境中显示这些自定义错误页面。在相应的app.php文件中设置各种环境的调试模式:http://laravel.com/docs/4.2/configuration#environment-configuration

在app / controllers / ErrorsController.php中:

protected $layout = "layouts.main";

/*
|--------------------------------------------------------------------------
| Errors Controller
|--------------------------------------------------------------------------
*/

public function error($code) {
    switch ($code) {
        case 404:
            $this->layout->content = View::make('errors.404');
        break;

        default:
            $this->layout->content = View::make('errors.500');
        break;
    }
}

}

(注意:protected $ layout =“layouts.main”;指的是我的主布局,名为'main'。你的主布局可能被命名为其他东西,例如'master'。)

最后,创建app / views / errors / 404.blade.php和app / views / errors / 500.blade.php,并在那里放置您想要的任何HTML错误页面。它将自动包装在layouts.main中!

缺少页面和500个内部错误现在将自动显示自定义错误页面和布局。您可以通过调用以下命令从任何控制器手动调用错误页面:return App::make("ErrorsController")->callAction("error", ['code'=>404]);(用您想要的任何错误代码替换404)


1
投票

404.blade.php的顶部,您可以扩展您的主布局@extends('layouts.master')


0
投票

好的,这就是你如何实现你所追求的目标(根据需要进行修改)。

App::error(function(Symfony\Component\HttpKernel\Exception\NotFoundHttpException $exception, $code) use ($path, $referer, $ip)
{
    // Log the exception
    Log::error($exception);

    // This is a custom model that logs the 404 in the database (so I can manage redirects etc within my app)
    ErrorPage::create(['destination_page' => $path, 'referer' => $referer, 'ip' => $ip]);

    // Return a response for the master layout
    $layout = Response::view('layouts.frontend');

    // Instantiate your error controller and run the required action/method, make sure to return a response from the action
    $view = App::make('Namespace\Controllers\Frontend\ErrorsController')->notFound();

    // Merge data from both views from the responses into a single array
    $data = array_merge($layout->original->getData(), $view->original->getData());

    // There appears to be a bug (at least in Laravel 4.2.11) where,
    // the response will always return a 200 HTTP status code, so
    // set the status code here.
    http_response_code(404);

    // Return your custom 404 error response view and pass the required data and status code.
    // Make sure your error view extends your master layout.
    return Response::view('404', $data, 404);
});

所以,基本上我们在这里做的是返回主布局和自定义404 /错误视图的响应,然后从这些响应的视图对象中检索数据,将数据组合到单个数组中,然后返回响应并传递我们的自定义404 /错误视图,数据和HTTP状态代码。

注意:似乎存在一个错误(至少在Laravel 4.2.11中),无论您传递给view()还是make(),响应将始终返回200 HTTP状态代码。据说你需要使用http_response_code手动设置响应代码(404)。

© www.soinside.com 2019 - 2024. All rights reserved.