I don't know if it work but you could create an ErrorsController with a method (es. erroraction) that return a view in a layout as you want.
App::missing(function($exception)
{
return Redirect::action('ErrorController@erroraction');
});
Currently I'm using the
return Redirect::to('404')
but the issue is the HTTP status code... because in this case the page won't drop 404 (because of redirect) as a standard for missing page rather than it will be 200 after the 303 (redirect)...
ok, in App::missing try to call directly controller action:
App::make("ErrorController")->erroraction();
No luck... :(
Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_ERROR)
Call to a member function filter() on a non-object
Controller instantiated from App::missing doesn't inherit nothing from BaseController or the base Controller class.
Tried with App::make and in the old way (new ErrorController();) with the same results.
In my case $this->layout was simple a string so I cannot call content property on it. This because my controller doesn't inherit setupLayout method from BaseController. Your problem seems to be similar. It could be a bug.
Thanks anyway! It's a sad news... :( I'll raise it on Laravel Github.
ehhh... I've raised it on Git but they closed the issue with "Ask on the forums/irc. We can't answer those questions here." message... So I have no idea where and how could I ask for more help. Any idea? Thanks!
I've created a Gist with code examples what I use. Maybe it helps more to easily understand how I use it.
However you can pass to Redirect::action as third parameter http status code 404. http://laravel.com/api/4.2/Illuminate/Routing/Redirector.html#method_action
Yes, I can pass the code (at Redirect::to() as well) but in that case I get this error message:
Error in exception handler: The HTTP status code is not a redirect ("404" given).
So unfortunately it doesn't work either. :/
You can do the trick by adding something like this on global.php and create the necessary error views.
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);
}
});
You can also check some laravel-starter-kit packages available around and check how they do stuffs like that. Here is my version of laravel starter kit
@yajra Again... your solution (like many others') is not using the layout for 404. It works but not like how I want. I have a layout (header, footer, etc. in layout for every view), stuff in BaseController and I want to throw the 404 page with 404 HTTP Status code from ErrorController like I showed above in my Gist example.
Take a look at Illuminate\Routing\Controller, in particular at callAction, it calls setupLayout before action execution.
This is what i tried:
on app/start/global.php
App::missing(function($e){
return App::make("OopsController")->callAction("wrongurl", []);
});
on app/controllers/OopsController.php
<?php
class OopsController extends BaseController{
protected $layout = "layouts.error";
public function wrongurl(){
$this->layout->content = View::make("error.missing");
}
}
And it seems to work.
@longilineo Weird... it throws error 500 (Internal Server Error) and with this error:
Call to a member function filter() on a non-object
In the meantime I did some research about this issue and seems like I'm not the only one who ran into it...
can't recreate your problem, post some more code.
I have something like this on a 4.2 project (my project data replaced & simplified)...
App::missing(function(\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $exception) {
View::share(['somedata' => 'yep', 'moredata' => 'hi']);
return Response::view('exceptions.notfound', [], 404);
});
The share method passes in the same extra data I have in my 'base' controller. As this data is no different on the view side as me including it from the controller, I believe this solution can be modified to get the desired results. If you move all the required extra data to a helper function (or few) and call that in both controller and error response, that should save duplicating complex functionality.
@longilineo @sgrayme I've created a basic Laravel project with the controllers and with basic logic just for this test... you can check it here: https://github.com/SasSam/l42-custom404-layout
@IanSirkit As you can see above, we tried many options... but the latest (which is still not working) is:
https://github.com/SasSam/l42-custom404-layout/blob/master/app/start/global.php
App::missing(function($e){
return App::make("ErrorController")->callAction("missing", []);
});
Or do I misunderstand your question?
The problem is that filter are defined by routing that you are bypassing calling directly controller's action. I don't know any other way to use controller to handle HttpNotFoundException without using a redirect (to avoid false http status). So I can only suggest to not use filter. Sincerely I don't understand why you are using filter in that way in BaseController. As I can see you are sharing for all views an object with a title property empty. There is some particular reason for doing that in a filter? Why don't just use templating to achieve the same goal?
Hi Folks,
This is how I am achieving what everyone is after, as in, getting the required data from a master layout, along with any data from your custom error view (404), then returning a response with a HTTP status code fo 404.
App::error(function(Symfony\Component\HttpKernel\Exception\NotFoundHttpException $exception, $code) use ($path, $referer, $ip)
{
Log::error($exception);
ErrorPage::create(['destination_page' => $path, 'referer' => $referer, 'ip' => $ip]);
$layout = Response::view('layouts.frontend');
$view = App::make('PurpleGriffon\Controllers\Frontend\ErrorsController')->notFound();
$data = array_merge($layout->original->getData(), $view->original->getData());
return Response::view('404', $data, 404);
});
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community