Jaimz
Jaimz

Reputation: 840

Routing one url to two controller actions based on authentication

I'm a bit new to Symfony, but I've got an easy to explain situation:

I've got a public home page, and a private home page. I'd like to have both of these accessible with the URL "/"

When a non-authenticated person visits the address www.example.com/ I'd like for them to be routed to PublicController::indexAction()

When an authenticated user visits the address www.example.com/ I'd like for them to be routed to Privatecontroller::indexAction()

Is this possible?

(symfony 2.7 btw)

Upvotes: 1

Views: 436

Answers (2)

Don Omondi
Don Omondi

Reputation: 946

Got a social network startup running on Symfony (always using latest versions) so naturally I encountered this challenge of showing different content on the homepage dependent on first, your loggedin or not status, and second if logged in different personalized content dependent on your logged in user id. Although the answer above works, I found it much better and performant to use twig to display which content because I could use the render_esi tag to use a reverse proxy cache and avoid not just database lookups but template generation and the whole request hitting Symfony.

For example

{# src/MyApp/AppBundle/Resources/views/Page/index.html.twig #}
{% extends 'MyAppAppBundle::layout.html.twig' %}
.....
    {% block body %}
        {% if not app.user %}
Code for non-logged in user
e.g. {{ render_esi(controller('MyAppAppBundle:Home:non_logged_in_user')) }}
        {% else %}
Code for logged in user
e.g {{ render_esi(controller('controller('MyAppAppBundle:Home:logged_in_user', { 'user': app.user.id })) }}
        {% endif %}
....
    {% endblock %}

Upvotes: 0

user4545769
user4545769

Reputation:

Definitely possible, although the details depend on what you're doing in each controller action. The easiest way would be to have:

class PublicController extends \Symfony\Bundle\FrameworkBundle\Controller\Controller
{
    public function indexAction()
    {
        if ($this->getUser() !== null) {
            return $this->forward('BundleName:PrivateController:index');
        }

        // do public controller details
    }
}

So by default everyone is sent to PublicController:indexAction which does a check to see if there is a logged in user (using the getUser method from Symfony's Controller class) and if there is, forward the request over to PrivateController:indexAction. If not, then it just shows the public action as expected. You could invert this if you're expecting more logged in than logged out users as there will be a performance penalty for forwarding (as Symfony will create and dispatch a subrequest).

The longer answer is understanding what you're doing in each controller that requires them to be separate and whether you could combine the functionality into a service or otherwise re-architect them. Without knowing more about your specific problem domain, the above seems like the best way forward.

Upvotes: 1

Related Questions