Routing in a listener class not going as I want it to be

I’ve this listener class

class LoginListener implements ListenerAggregateInterface
{
    /** @var array */
    protected $listeners;

    /** @var LoginService $loginService */
    protected LoginService $loginService;

    /**
     * LoginListener constructor.
     * @param LoginService $loginService
     */
    public function __construct(LoginService $loginService)
    {
        $this->loginService = $loginService;
    }

    /**
     * @inheritDoc
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $this->listeners[] = $events->attach(MvcEvent::EVENT_ROUTE, [$this, "userHasAuthentication"], 1000);
    }

    /**
     * @inheritDoc
     */
    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            if ($events->detach($listener)) {
                unset($this->listeners[$index]);
            }
        }
    }

    /**
     * @param MvcEvent $e
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function userHasAuthentication(MvcEvent $e)
    {
        $routeMatch = $e->getApplication()
            ->getServiceManager()
            ->get("HttpRouter")
            ->match($e->getRequest());

        if ($routeMatch) {
            $controllerName = explode("\\", $routeMatch->getParam("controller"))[2];
            $actionName = $routeMatch->getParam("action");
            $actionName = str_replace("-", "", lcfirst(ucwords($actionName, "-")));
            $moduleName = explode("\\", $routeMatch->getParam("controller"))[0];
            if ($controllerName !== "UserController"
                && $actionName !== "login"
                && $actionName !== "logout"
            ) {
                $result = $this->getLoginService()
                    ->filterAccess($moduleName, $controllerName, $actionName, $taskName = "*");

                if ($result == LoginService::AUTH_REQUIRED) {
                    $routeMatch->setParam("controller", UserController::class);
                    $routeMatch->setParam("action", "login");
                }

                if ($result == LoginService::ACCESS_DENIED) {
                    $routeMatch->setParam("controller", UserController::class);
                    $routeMatch->setParam("action", "unauthorized");
                    $e->getResponse()
                        ->setStatusCode(401);
                }
            }
        }
    }

    /**
     * @return LoginService
     */
    public function getLoginService(): LoginService
    {
        return $this->loginService;
    }

    /**
     * @param LoginService $loginService
     * @return LoginListener
     */
    public function setLoginService(LoginService $loginService): self
    {
        $this->loginService = $loginService;

        return $this;
    }
}

All works as per the code except below. When I go to http://localhost/dashboard (The route I created in MVC app)
[matchedRouteName:protected] => dashboard
This is always dashboard , due to which instead of routing to unauthorized action of Controller\UserController::class it routes to dashboard action of Controller\IndexController::class .
If I use the below code
$routeMatch->setMatchedRouteName( "user/actions" );
It keeps suffixing it to original matchedRouteName i.e. dashboard which sometimes becomes something like
[matchedRouteName:protected] => user/actions/user/actions/user/actions/user/actions/dashboard

Try for the priority something smaller than 1.

(Unfortunately, I can’t remember exactly!)

I recheck the route event and you must set value smaller than 1, in your case add a minus sign:

$this->listeners[] = $events->attach(MvcEvent::EVENT_ROUTE, [$this, "userHasAuthentication"], -1000);

You can replace:

with

$routeMatch = $e->getRouteMatch();

I tried reducing the priority to -1000 but that alone didn’t work. However this last suggestion from you along with lowering the priority did the trick. :clap:

$routeMatch = $e->getRouteMatch();

Thanks :pray:

I’m still new to Laminas so can you spare some time to brief me what’s the difference between the two approaches?