How can I set a 404 page in Phalcon to be displayed when a controller/action does not exist?
-
3I came to answer... but :) – twistedxtra Dec 28 '12 at 18:32
4 Answers
You can set the dispatcher to do that for you.
When you bootstrap your application you can do this ($di
is your DI factory):
use \Phalcon\Mvc\Dispatcher as PhDispatcher;
$di->set(
'dispatcher',
function() use ($di) {
$evManager = $di->getShared('eventsManager');
$evManager->attach(
"dispatch:beforeException",
function($event, $dispatcher, $exception)
{
switch ($exception->getCode()) {
case PhDispatcher::EXCEPTION_HANDLER_NOT_FOUND:
case PhDispatcher::EXCEPTION_ACTION_NOT_FOUND:
$dispatcher->forward(
array(
'controller' => 'error',
'action' => 'show404',
)
);
return false;
}
}
);
$dispatcher = new PhDispatcher();
$dispatcher->setEventsManager($evManager);
return $dispatcher;
},
true
);
Create an ErrorController
<?php
/**
* ErrorController
*/
class ErrorController extends \Phalcon\Mvc\Controller
{
public function show404Action()
{
$this->response->setStatusCode(404, 'Not Found');
$this->view->pick('404/404');
}
}
and a 404 view (/views/404/404.volt
)
<div align="center" id="fourohfour">
<div class="sub-content">
<strong>ERROR 404</strong>
<br />
<br />
You have tried to access a page which does not exist or has been moved.
<br />
<br />
Please click the links at the top navigation bar to
navigate to other parts of the site, or
if you wish to contact us, there is information in the About page.
<br />
<br />
[ERROR]
</div>
</div>

- 3
- 2

- 11,495
- 6
- 39
- 67
-
This was extremely helpful for me (almost exact copy, save for controller/action names). Thanks so much! – Trenton Jan 30 '14 at 16:33
-
and what if i wanna set 503 status page from some action in addition to 404 page? Can i set status code as parameter etc and read it from ErrorController? How can i do this ? – alexglue Nov 23 '14 at 14:02
-
1In order to actually return a custom error code as well as a custom page, you need to `return $response`, but before that, you need to render the view `view->start()->render("page", "action")->finish();`, and then `$response->setContent(view->getContent());` – Sebastian Mach Feb 16 '15 at 11:18
You can use routing to handle 404 not found page:
$router->notFound(array(
"controller" => "index",
"action" => "route404"
));
Ref: http://docs.phalconphp.com/en/latest/reference/routing.html#not-found-paths

- 661
- 1
- 13
- 26
-
1This will work only with this code: `$router = Phalcon\Mvc\Router(FALSE); // $defaultRoutes = false` – Stanislav Belichenko Apr 28 '17 at 14:19
The solution proposed by Dimopoulos doesn't work. It generates a cycling condition.
The Phalcon Router component has a default behavior providing a very simple routing that always expects an URI that matches the following pattern: /:controller/:action/:params. This is gonna cause many problems because Phalcon will search a controller that doesn't exist when the server receives a request for an URL that doesn't match any defined route.
So, first of all, you must disable this behavior. This can be done passing FALSE
during the Router instance creation, as follows:
$router = Phalcon\Mvc\Router(FALSE);
At this point you can use the solution proposed by @Nguyễn Trọng Bằng.
$router->notFound(
[
"namespace" => "MyNamespace\Controller"
"controller" => "index",
"action" => "route404"
]
);
It's important to note, if you are using a namespace the dispatcher will not be able to find the controller, unless you specify it, like I did above.
This is not only the easiest solution, but it is the only one that works.

- 3,635
- 2
- 25
- 27
-
If you disable by passing false to Router, the all other routs are cannot be found and all the page just go to 404 route. – vee Aug 27 '14 at 09:21
-
2@vee that's not true. That happens only if you don't define the routes: the mapping between a path and his relative controller/action. As I have written above, the Router has a default behavior to match /:controller/:action/:params, but you are free to define the association between your routes and their relative actions. Then you can disable the default behavior. Before to downvote read the documentation. – noun Aug 27 '14 at 14:36
-
I was read doc. and i have defined route and already test that this is not work. // Create the router $router = new \Phalcon\Mvc\Router(false); $router->add( '/index/page3/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/{pagename}', array( 'controller' => 'index', 'action' => 'page3', 'roll' => 1, 'track' => 2, ) ); $router->notFound( array( "controller" => "error", "action" => "e404" ) ); go to http://localhost/phalcon/ > page not found go to http://localhost/phalcon/index/page3 > page not found go to any page defined in route > page not found – vee Aug 27 '14 at 18:30
-
You are doing something wrong. Are you sure did you declared the controller in the same namespace? Is your e404 action executed when a route is not found? Try to define a simple route, like `$router->add('/', ['controller => 'index', 'action' => 'index']);` then create the `IndexController` class with a method called `indexAction()` that print something. Keep it simple and make it works, then you'll add complexity later. – noun Aug 27 '14 at 22:32
-
I don't understand what you mean by "cycling condition". What Dimopoulos provided worked just fine on our host. I wonder if you're perhaps having an issue with some setting on your server. – TheOneWhoSighs Nov 25 '14 at 18:52
-
@TheOneWhoSights are you using standard routing? Because I'm not and that code didn't work for me. Cycling condition means the forward to 404 page generates an infinite loop. At least on my server. Anyway, if you are building a complex app, you are not going to use the default behavior. The solution provided above works with any kind of URL, and it consists of just two lines of code. – noun Dec 08 '14 at 22:40
-
you're disabling all the routing functionality and want us to define a route for every controller/action we make ??? – Hakim Mar 26 '15 at 14:45
-
Of course, default routing is just for very simple projects. Any real project requires custom routes. – noun Mar 26 '15 at 18:47
You also can set the header in a errorController by using
class ErrorController extends ControllerBase
{
public function error404Action()
{
$this->response->setHeader('HTTP/1.0 404','Not Found');
// $this->response->setHeader(404, 'Not Found'); <- did not work
}
}
And before, in the controller, where an error occures, you can forward to this error-controller.
class IndexController extends ControllerBase
{
public function indexAction()
{
$id = (int)$this->getId($param);
if ($id > 0) {
// do you stuff
} else {
$this->dispatcher->forward(array(
'controller' => 'error', 'action' => 'error404')
);
}
}
}
That's a quick and dirty(?) way and is good, if you're getting content from a database and want to throw an error, if nothing was found.

- 135
- 1
- 8