We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

404 page for each module

I have multi module app, one module built on the annotations routing. I need special notFound page for it. I can set uniq 404 for other modules, but how I can do it for Annotation-routing module? Now errors handle by default module, but It is not satisfy me



4.0k

If route does not exist, router can't handle request and then overwrites with notFound parameters. Dispatcher does not know which module must be loaded. Try to use dispacher EventManager

edited Jul '15

This is my router

<?php

/*============================= API ====================================*/
$router->add("/api", array(
    'module' => 'api'
))->setName('api');

$apiRoutes = [
    '/' => 'Index',
    '/users' => 'Users'
];

foreach($apiRoutes as $route => $className){
    $router->addModuleResource('api', 'MyPackage\API\Controllers\\' . $className, '/api' . $route);
}

/*============================= Pub ====================================*/
$router->add('/confirm/{code}/{email}', array(
    'controller' => 'user_control',
    'action' => 'confirmEmail'
));

$router->add('/signup', array(
    'controller' => 'session',
    'action' => 'signup'
))->setName('signup');

$router->add('/reset-password/{code}/{email}', array(
    'controller' => 'user_control',
    'action' => 'resetPassword'
));

/*============================= Admin ====================================*/
$router->add("/admin", array(
    'module' => 'admin'
));

$router->add(
    "/admin/:controller",
    array(
        'module' => 'admin',
        "controller" => 1
    )
);
$router->add(
    "/admin/:controller/:action/",
    array(
        'module' => 'admin',
        "controller" => 1,
        "action"     => 2
    )
);
$router->add(
    "/admin/:controller/:action/:params",
    array(
        'module' => 'admin',
        "controller" => 1,
        "action"     => 2,
        "params"     => 3,
    )
);

In every module I have

$di['dispatcher'] = function() {
            $eventsManager = new \Phalcon\Events\Manager();
            $eventsManager->attach("dispatch:beforeException", function($event, $dispatcher, $exception) {
                //Handle 404 exceptions
                if ($exception instanceof \Phalcon\Mvc\Dispatcher\Exception) {
                    $dispatcher->forward(array(
                        'controller' => 'index',
                        'action' => 'show404'
                    ));
                    return false;
                }
                ...

This works for Pub and Admin module. Is any way for doing this in API module? It is critical issue for me



4.0k
edited Jul '15

Maybe it's workaround, but... :)

$router = new \Phalcon\Mvc\Router(false);

$eventManager = new \Phalcon\Events\Manager();
$eventManager->attach('router:beforeCheckRoutes', function($event, \Phalcon\Mvc\Router $router) {

    switch(true) {
        case (strpos($router->getRewriteUri(), '/api', 0) === 0):
            $router->notFound(
                array(
                    'module'     => 'api',
                    'controller' => 'index',
                    'action'     => 'show404'
                )
            );
            break;
    }
});

Create a router or router annotation object with false parameter

Thank you for a tip, I solved my issue. I now it's not really right way, but it just works. I added another method showApi404 in Pub module, b/c I can't forward request between modules (Pub module dispatcher still handle 404 exceptions). It might be http redirect, but I don't want this

$di['dispatcher'] = function() {
            $eventsManager = new \Phalcon\Events\Manager();
            $eventsManager->attach("dispatch:beforeException", function($event, $dispatcher, $exception) {

                // Handle api 404
                $router = $dispatcher->getDi()->get('router');
                if (strpos($router->getRewriteUri(), '/api/', 0) === 0){
                    $dispatcher->forward(array(
                        'controller' => 'index',
                        'action' => 'showApi404'
                    ));
                    return false;
                }
                ...