我的页面使用全局布局,许多视图都有自己的控制器使用这种布局。控制器动作调用的视图如下:
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。我知道正确的方法是在App::missing()
中从filter.php
发送Response::view('errors.404', array(), 404)
,但我不能仅在视图中设置布局,这是不够的。还是我错了,而且这是可能的?
谢谢!
更新:我已经用我在项目中使用的文件为这个问题创建了一个Gist。也许了解我目前的状态更有帮助。
这是我的方法。只需将以下代码添加到/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);
});
您可以通过在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入门套件包,看看它们是如何做到这一点的。这是我的laravel管理模板版本
我不能告诉你这是最好的方法还是被认为是最好的实践,但和你一样,我很沮丧,在Illuminate''Routing''Controller中使用callAction方法找到了另一种解决方案。
app/start/global.php
App::missing(function($exception)
{
return App::make("ErrorController")->callAction("missing", []);
});
app/controllers/ErrorController.php
<?php
class ErrorController extends BaseController {
protected $layout = 'layouts.master';
public function missing()
{
$this->layout->content = View::make('errors.missing');
}
}
希望它能有所帮助!
我知道我迟到了,但由于这个问题仍然没有得到回答,并且在查询的搜索结果中排名相对较高,"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从核心布局更改为自定义布局。例如,视图/布局/错误。叶片.php。
然后在你的404.blade.php中,你会做这样的
@extends('layouts.errors')
并使用不依赖$user(或其他)的新标题创建视图/layouts/errors.blade.php。
希望能有所帮助。
我在这个问题上挠头了一会儿,下面是解决方案:
In-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-配置)
In-app/controller/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)
在404.blade.php
的顶部,您可以扩展主布局@extends('layouts.master')
。
好吧,这就是实现目标的方法(根据需要进行修改)。
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/error视图返回一个响应,然后从这些响应的视图对象中检索数据,将数据组合到一个数组中,然后返回一个回应,并传递我们的自定义404/eerror视图、数据和HTTP状态代码。
注意:出现了一个错误(至少在Laravel 4.2.11中),无论您传递给view()或make()什么,响应都将始终返回200 HTTP状态代码。话虽如此,您需要使用http_response_code手动设置响应代码(404)。