【问题标题】:Custom 404 in Laravel 4.2 with Layout带有布局的 Laravel 4.2 中的自定义 404
【发布时间】:2014-12-17 06:10:55
【问题描述】:

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

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。也许它有助于更​​多地了解我目前的状态。

【问题讨论】:

  • 如果$news 为空,是否要显示另一个视图?
  • @Marwelln 我们已经有了更长的对话here,但仍然没有解决方案。
  • Response::view('layouts.errors', ['content' => View::make('errors.404')], 404) 将使用布局文件并将$content 变量设置为errors.404 的内容。
  • 它会抛出 Call to undefined function view() 错误。如果我将其更改为Response::view('layouts.master', ['content' => View::make('errors.missing')], 404);,则错误将为Error in exception handler: Undefined variable: shared (View:master.blade.php)

标签: php layout laravel-4 error-handling


【解决方案1】:

这是我的方法。只需将以下代码添加到/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);
});

【讨论】:

    【解决方案2】:

    您可以通过在 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版本@

    【讨论】:

    • 谢谢,但您的解决方案(与许多其他解决方案一样)没有使用 404 的布局。它可以工作,但不像我想要的那样。我有一个布局(每个视图的布局中的页眉、页脚等),BaseController 中的内容,我想从 ErrorController 中抛出带有 404 HTTP 状态代码的 404 页面,就像我在上面的 Gist 示例中显示的那样。
    【解决方案3】:

    我无法告诉您这是否是最佳方法或被认为是最佳实践,但和您一样,我很沮丧,并找到了使用 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');
        }
    }
    

    希望对你有帮助!

    【讨论】:

      【解决方案4】:

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

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

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

      例如;

      @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(或其他)的新标头创建视图/布局/errors.blade.php。

      希望对您有所帮助。

      【讨论】:

        【解决方案5】:

        我在这个问题上摸不着头脑,这是解决方案:

        在 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]);
        });
        

        (注意:上面的 sn-p 仅在调试模式为 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")-&gt;callAction("error", ['code'=&gt;404]);(将 404 替换为您想要的任何错误代码)

        【讨论】:

          【解决方案6】:

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

          【讨论】:

          【解决方案7】:

          好的,这就是你实现目标的方法(根据需要进行修改)。

          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() 或制作()。话虽如此,您需要使用 http_response_code(404) 手动设置响应代码。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-01-25
            • 2017-06-24
            • 1970-01-01
            • 1970-01-01
            • 2019-08-07
            • 1970-01-01
            • 2011-07-28
            • 2018-06-05
            相关资源
            最近更新 更多