Custom 404 в Laravel 4.2 с компоновкой

Моя страница использует глобальный макет, и есть много представлений с собственными контроллерами, которые используют этот макет. Представление вызывается из действия контроллера следующим образом:

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() но я не могу установить макет там только вид, который не достаточно. Или я не прав и возможно как-то?

Спасибо!

Обновить:
Я создал Суть для этой проблемы с файлами, которые я использую в проекте. Может быть, это поможет мне лучше понять мое текущее состояние.

3

Решение

Это мой подход. Просто добавьте следующий код в /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);
});
7

Другие решения

Вы можете добиться цели, добавив что-то подобное в 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-админ-шаблон

5

Я не могу сказать вам, является ли это наилучшим подходом или считается наилучшей практикой, но, как и вы, я был разочарован и нашел альтернативное решение, используя метод callAction в Illuminate \ Routing \ Controller.

приложение / старт / 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

Я знаю, что опаздываю на вечеринку, но поскольку этот вопрос остается без ответа и занимает сравнительно высокое место в результатах поиска по запросу «Ошибка 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')

И создайте views / layouts / errors.blade.php с новыми заголовками, не зависящими от $ user (или чего бы то ни было).

Надеюсь, это поможет.

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

(НОТА: Приведенный выше фрагмент кода отображает эти пользовательские страницы ошибок только в тех средах, где установлен режим отладки. Установите режим отладки в различных средах в соответствующем файле 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»; ссылается на мой основной макет, который называется «основной». Ваш основной макет может быть назван как-то еще, например, «мастер».)

Наконец, создайте app / views / errors / 404.blade.php и app / views / errors / 500.blade.php и поместите туда любой HTML-код для страниц с ошибками. Он будет автоматически обёрнут в макеты.

Недостающие страницы и 500 внутренних ошибок теперь будут автоматически отображать пользовательские страницы ошибок, с макетом. Вы можете вручную вызвать страницу ошибки с любого контроллера, вызвав:
return App::make("ErrorsController")->callAction("error", ['code'=>404]); (замените 404 на любой код ошибки)

1

На вершине 404.blade.php Вы можете расширить свой основной макет @extends('layouts.master'),

1

ОК, это то, как вы можете достичь того, что вы хотите (изменить по мере необходимости).

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 /, данные и код состояния HTTP.

НОТА: Кажется, есть ошибка (по крайней мере, в Laravel 4.2.11), когда ответ всегда будет возвращать код состояния HTTP 200, независимо от того, что вы передаете в view () или make (). С учетом сказанного вам необходимо вручную установить код ответа, используя http_response_code (404).

0
По вопросам рекламы [email protected]