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

Micro notFound

I've set up a Micro app to function as a CMS. So there will be potentially infinite possible routes, that I want to all direct to my Index handler.

I've set up my index.php file like so:

$App = new \Phalcon\Mvc\Micro;
$App->setDI($DI);
$App->notFound(function(){
    $Index = new \Handler\Index();
    $Index->handle();
});

$App->handle();

When I go to www.site.com/dev/, which is the homepage, everything works fine. handle() gets called. However, when I go to a sub-page like www.site.com/dev/blah, I get Fatal error: Uncaught Phalcon\Mvc\Micro\Exception: Matched route doesn't have an associated handler. Well I haven't set up any routes, so everything should be going to the notFound handler.

What am I missing?

edited May '18
$app->notFound(
    function () use ($app) {
        $app->response->setStatusCode(404);
        $message = 'This is crazy, but this page was not found!';
        $app->response->setContent($message);
        !$app->response->isSent() && $app->response->send();
        exit;
    }
);

https://docs.phalcon.io/en/latest/application-micro#routing-handlers-not-found

I think there is some predefined routes. You can clear them:

$di->get('router')->clear();

I posted this on StackOverflow, and there was a comment there about catch-all routes, so I went that direction instead:

$App = new \Phalcon\Mvc\Micro;
$App->setDI($DI);
$App->get(
    '(.*)',
    function() use($App){
        $Index = new \Handler\Index($App);
        $Index->handle();
    }
);
edited May '18

That shouldn't be neccecary (handling wildcard pattern routes).

// Not found handler
$app->notFound(function () { ErrorHandler::stopMiddleware(404); });

My error handler class / static method stopMiddleware looks like this:

static final function stopMiddleware(int $status = 401, string $msg = 'STOP RUN.', $code = 0x0a){

       //Resolve last used DI from static context
       static::$di = \Phalcon\Di::getDefault();

       //resolve shared service from static context into local scope
       $response = static::$di->getShared('response');

       //set requested status code and response content (in my case for API I'm using JSON)
       $response->setStatusCode($status);
       $response->setJsonContent(['Status' => $status, 'Type' => 'ACCESS_DENIED', 'Error' => $msg, 'Code' => $code], JSON_NUMERIC_CHECK);
       $response->setContentLength(strlen($response->getContent())); //Calculate Content-Length header

        //flush output to the client
       !$response->isSent() && $response->send();

    //returning false will stop execution
    return false;
    }

Router should be configured like this:

    $di->setShared('router', function (){
    // Phalcon\Mvc\Router has a default behavior that provides a very simple routing that always expects a URI that matches the following pattern: /:controller/:action/:params

        $router = new \Phalcon\Mvc\Router(false); //Create the router without default routes

        //we're using Front Page Controller pattern in relation from nginx -> Phalcon
        $router->setUriSource($router::URI_SOURCE_SERVER_REQUEST_URI); // Use $_SERVER['REQUEST_URI']

        //Set whether router must remove the extra slashes in the handled routes
        $router->removeExtraSlashes(true);

    return $router;
});

P.S. It is recommended to handle your routes via MicroCollection.

I'm sure your method has lots of advantages. But it seems simpler to just use everything out of the box and simply add a route.

I'm not really looking to make this a super robust system - it's just a simple CMS to write documentation for another application I'm building.

In that case your handler is valid for GET routes only. What about POST etc?

You should consider via method then: https://docs.phalcon.io/en/latest/application-micro#routing-verbs-map

Thanks for that. I haven't gotten to other, POST routes yet, but I'll keep an eye out - thanks for the tip.