Nel mio Symfony 2 app che ho 3 diversi ruoli utente che possono avere accesso a una parte di amministrazione backend:Associare una via a diversi controller a seconda dei ruoli utente
role_hierarchy:
ROLE_STAFF: ROLE_USER
ROLE_MODERATOR: ROLE_STAFF
ROLE_ADMIN: ROLE_MODERATOR
Per un percorso come http://example.org/admin/post/
, mi piacerebbe come la mia app per visualizzare informazioni diverse a seconda del ruolo dell'utente, che significa 3 controller vincolante su un solo route.
Qual è il modo migliore per gestire questo?
Stavo pensando di alcune soluzioni, ma nessuno sembra essere buono per me:
Un controller, e in ogni azione Ho appena prova ruolo utente:
<?php /** * @Route("/admin/post") */ class PostController extends Controller { /** * Lists all post entities. * * @Route("/", name="post_index") * @Template() * @Secure(roles="ROLE_STAFF") */ public function indexAction() { $user = $this->get('security.context')->getToken()->getUser(); if ($this->get('security.context')->isGranted('ROLE_STAFF')) { // Do ROLE_STAFF related stuff } else if ($this->get('security.context')->isGranted('ROLE_MODERATOR')) { // Do ROLE_MODERATOR related stuff } else if ($this->get('security.context')->isGranted('ROLE_ADMIN')) { // Do ROLE_ADMIN related stuff } return array('posts' => $posts); } }
Anche se che fa il lavoro, IMO ovviamente non è un buon progetto.
Uno BackendController che la spedizione a 3 diversi controller:
<?php /** * @Route("/admin/post") */ class PostBackendController extends Controller { /** * Lists all post entities. * * @Route("", name="admin_post_index") * @Template("AcmeBlogBundle:PostAdmin:index.html.twig") * @Secure(roles="ROLE_STAFF") */ public function indexAction() { if ($this->get('security.context')->isGranted('ROLE_STAFF')) { $response = $this->forward('AcmeBlogBundle:PostStaff:index'); } else if ($this->get('security.context')->isGranted('ROLE_MODERATOR')) { $response = $this->forward('AcmeBlogBundle:PostModerator:index'); } else if ($this->get('security.context')->isGranted('ROLE_ADMIN')) { $response = $this->forward('AcmeBlogBundle:PostAdmin:index'); } return $response; } }
Uguale al numero uno.
Ho provato a fare i controllori si estende ogni altri:
<?php /** * @Route("/admin/post") */ class PostStaffController extends Controller { /** * Lists all post entities. * * @Route("/", name="post_index") * @Template() * @Secure(roles="ROLE_STAFF") */ public function indexAction() { $user = $this->get('security.context')->getToken()->getUser(); // Do ROLE_STAFF related stuff return array('posts' => $posts); } } <?php /** * @Route("/admin/post") */ class PostModeratorController extends PostStaffController { /** * Lists all post entities. * * @Route("/", name="post_index") * @Template() * @Secure(roles="ROLE_MODERATOR") */ public function indexAction() { $user = $this->get('security.context')->getToken()->getUser(); // As PostModeratorController extends PostStaffController, // I can either use parent action or redefine it here return array('posts' => $posts); } } <?php /** * @Route("/admin/post") */ class PostAdminController extends PostModeratorController { /** * Lists all post entities. * * @Route("/", name="post_index") * @Template() * @Secure(roles="ROLE_ADMIN") */ public function indexAction() { $user = $this->get('security.context')->getToken()->getUser(); // Same applies here return array('posts' => $posts); } }
IMO è un disegno migliore, ma non riesco a fare funziona. Il sistema di routing si ferma sul primo controller che corrisponde. Mi piacerebbe farlo agire come re dello stile a cascata automaticamente (ad esempio se l'utente è personale, allora vai a PostStaffController, altrimenti se l'utente è moderatore vai su PostModeratorController, altrimenti vai su PostAdminController).
Aggiungi un listener a kernel.controller nel mio BlogBundle che farà lo stesso lavoro del numero 2?
Sto cercando il miglior design e la soluzione più flessibile ci sono possibilità che aggiungiamo più ruoli in futuro.
Sto affrontando la stessa identica situazione, hai trovato una buona soluzione? –
Tutte le soluzioni sono buone ma progettate male. Se affronti lo stesso problema, assicurati che non sia una cattiva idea della tua applicazione. Nel mio caso invece di fare questo ho creato 2 tipi di moduli diversi per la mia entità: "configurazione" e "personalizzazione". Quindi l'amministratore può accedere ai controller "di configurazione" e "personalizzazione" mentre lo staff e il moderatore possono accedere solo alla "personalizzazione". Non sono sicuro se è chiaro. Forse dovrei renderlo una risposta completa? – iamdto
Hai ragione, era un cattivo design. La mia soluzione era di separare le diverse aree dell'applicazione in diversi pacchetti in cui posso gestire i ruoli di conseguenza. Grazie. –