phphttp-redirectzend-framework2zfcuser

ZfcUser redirect dynamic url after login


I'm learning to develop a website with ZF2. I have downloaded 2 modules ZfcUser and BjyAuthorize. The configurations was fairly straight forward after i read the documentations. How ever i did not find any solution for the following situation:

Guest lands on a blog post (www.yourdomain.com/blog/541) -> BjyAuthorize will redirect guest to the login page -> after successful login redirect to www.yourdomian.com/blog/541

I have a solution for the redirection when a guest arriving for a restricted area:

public function onBootstrap(MvcEvent $e)
{
    $app = $e->getApplication();
    $sm = $app->getServiceManager();
    $app->getEventManager()->attach(
        'route',
        function($e) {
            $app = $e->getApplication();
            $routeMatch = $e->getRouteMatch();
            $sm = $app->getServiceManager();
            $auth = $sm->get('zfcuser_auth_service');
            if (!$auth->hasIdentity() && $routeMatch->getMatchedRouteName() != 'user/login'
                && $routeMatch->getMatchedRouteName() != 'zfcuser/login') {
                $response = $e->getResponse();
                $response->getHeaders()->addHeaderLine(
                    'Location',
                    $e->getRouter()->assemble(
                            array(),
                            array('name' => 'zfcuser/login')
                    )
                );
                $response->setStatusCode(302);
                return $response;
            }
        },
        -100
    );
}

But i don't know how should i extend this to solve the above explained action.

Any help is greatly appreciated.

UPDATE

My route:

'blog' => array(
            'type' => 'Segment',
            'options' => array(
                    'route'    => '/blog/:id',
                    'constraints' => array (
                            'id' => '[0-9]+'
                    ),
                    'defaults' => array(
                        'controller' => 'Application\Controller\Index',
                        'action'     => 'view',
                    ),
            ),
        ),

This is my Zfcuser config:

return array(
'zfcuser' => array(
    'password_cost' => 4,
    'login_after_registration' => true,
    'use_redirect_parameter_if_present' => true,
    'enable_display_name' => true
 )

);

After your updated code i see it should be worked this is what happening with the URL:

http://localhost:10088/BlogProject/user/login?redirect=/BlogProject/blog/1

But when i try to login i received this error:

Route with name "" not found

UPDATE 2

Zend\Mvc\Router\Exception\RuntimeException
File:
/usr/local/zend/var/apps/http/__default__/0/ProjectManager/1.0.0_46/vendor/zendframework/zendframework/library/Zend/Mvc/Router/Http/TreeRouteStack.php:317
Message:
Route with name "" not found

Stack trace:
#0   /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/Plugin/Url.php(99): Zend\Mvc\Router\Http\TreeRouteStack->assemble(Array, Array)
#1 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/Plugin/Redirect.php(48): Zend\Mvc\Controller\Plugin\Url->fromRoute('/BlogProject...', Array, Array, false)
#2 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zf-commons/zfc-user/src/ZfcUser/Controller/UserController.php(158): Zend\Mvc\Controller\Plugin\Redirect->toRoute('/BlogProject...')
#3 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractActionController.php(83): ZfcUser\Controller\UserController->authenticateAction()
#4 [internal function]: Zend\Mvc\Controller\AbstractActionController->onDispatch(Object(Zend\Mvc\MvcEvent))
#5 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(468): call_user_func(Array, Object(Zend\Mvc\MvcEvent))
#6 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(207): Zend\EventManager\EventManager->triggerListeners('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
#7 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php(117): Zend\EventManager\EventManager->trigger('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
#8 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/Plugin/Forward.php(138): Zend\Mvc\Controller\AbstractController->dispatch(Object(Zend\Http\PhpEnvironment\Request), Object(Zend\Http\PhpEnvironment\Response))
#9 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zf-commons/zfc-user/src/ZfcUser/Controller/UserController.php(106): Zend\Mvc\Controller\Plugin\Forward->dispatch('zfcuser', Array)
#10 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractActionController.php(83): ZfcUser\Controller\UserController->loginAction()
#11 [internal function]: Zend\Mvc\Controller\AbstractActionController->onDispatch(Object(Zend\Mvc\MvcEvent))
#12 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(468): call_user_func(Array, Object(Zend\Mvc\MvcEvent))
#13 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(207): Zend\EventManager\EventManager->triggerListeners('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
#14 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php(117): Zend\EventManager\EventManager->trigger('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
#15 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/Mvc/DispatchListener.php(114): Zend\Mvc\Controller\AbstractController->dispatch(Object(Zend\Http\PhpEnvironment\Request), Object(Zend\Http\PhpEnvironment\Response))
#16 [internal function]: Zend\Mvc\DispatchListener->onDispatch(Object(Zend\Mvc\MvcEvent))
#17 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(468): call_user_func(Array, Object(Zend\Mvc\MvcEvent))
#18 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(207): Zend\EventManager\EventManager->triggerListeners('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
#19 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/vendor/zendframework/zendframework/library/Zend/Mvc/Application.php(313): Zend\EventManager\EventManager->trigger('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
#20 /usr/local/zend/var/apps/http/__default__/0/BlogProject/1.0.0_46/public/index.php(12): Zend\Mvc\Application->run()
#21 {main}

This is my viewAction:

public function viewAction()
{
    $flashMsg = $this->flashMessenger();
    if($flashMsg->hasMessages()){
        $variables['success'] = $flashMsg->getMessages()[0];
        $flashMsg->clearMessages();
    }
    $variables['blogs'] = $this->mapper->getAllMyBlogs($this->zfcUserAuthentication()->getIdentity()->getId());
    $variables['contributedBlogs'] = $this->mapper->getAllMyContributedBlogs($this->zfcUserAuthentication()->getIdentity()->getId());
    $variables['activeBlog'] = $this->getEvent()->getRouteMatch()->getParam('id');
    $this->vm->setVariables($variables);
    $this->vm->setTemplate('application/index/index.phtml');
    return $this->vm;
}

SOLUTION

I've found the solution:

if ($this->getOptions()->getUseRedirectParameterIfPresent() && $redirect) {
        return $this->redirect()->toRoute($redirect);
    }

This one is has to be changed:

if ($this->getOptions()->getUseRedirectParameterIfPresent() && $redirect) {
        return $this->redirect()->toUrl($redirect);
    }

And your code will work totally fine. You can find it in UserController line 157.


Solution

  • You can take advantage of the use_redirect_parameter_if_present option implemented in ZfcUser. If it's set to true (which is by default), and you add a redirect parameter to the login route, it will automatically redirects you to this route once you're logged. Your function could be:

    $eventManager->attach( MvcEvent::EVENT_ROUTE, function( $e ) use ( $serviceManager ) {
        $routeMatch = $e->getRouteMatch();
    
        $auth = $serviceManager->get('zfcuser_auth_service');
        if (!$auth->hasIdentity() && $routeMatch->getMatchedRouteName() != 'user/login'
                && $routeMatch->getMatchedRouteName() != 'zfcuser/login') {
                //GENERATE THE URL FROM CURRENT ROUTE (YOUR blog ONE)
                $redirect = $e->getRouter()->assemble(
                    $routeMatch->getParams(),
                    array(
                        'name' => $routeMatch->getMatchedRouteName(),
                    )
                );
    
                $response = $e->getResponse();
                $response->getHeaders()->addHeaderLine(
                    'Location',
                    $e->getRouter()->assemble(
                        array(),
                        array(
                            'name' => 'zfcuser/login',
                            'query' => array( 'redirect' => $redirect )
                        )
                    )
                );
                $response->setStatusCode(302);
                return $response;
            }
    
        } );