Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Display specified view if not logged on
  • I am looking for what I hope will be a simple code fragment recipe. I have a controller that requires the user to be logged in for all accessible methods (actions). If the user is not logged in, then I would like to display a specific view asking the user to log in. I do not want to redirect to a login page - I would like to leave the user on the URL they landed on, but just present a message and a login link (I'm using SAML, so the fewer layers of redirect, the less confusing and less likely it is for the user to end up far from the page they wanted to access). Any hints? Thanks, -- Jason
  • Use a base controller that extends Controller_Template. Add a router() method to that base controller. In that method, check if someone is logged in, and if not, switch the template to your login view, and call the action that powers it (deal's with the login) which is also defined in the base controller. If someone is logged in, call the action originally requested. Make sure that all controllers that need this behaviour extend the base controller.
  • Thanks. So would it be something like this:
    class Controller_MyStuff extends Controller_Template
    
        public function router($method, $params)
        {
            if (!logged_in()) {
                // Not logged in.
                $this->template->title = 'Not logged in';
                $this->template->content = View::forge('mycontroller/not_logged_in');
            } else {
                // Logged in - carry on
                return call_user_func_array(array($this, 'action_' . $method), $params);
            }
        }
    
        ...
    }
    

    This does appear to work for me, but the "call_user_func_array" and the "action_" concatenation don't seem as elegant as I have become accustomed to in Fuel, so have a hunch there is a better way.
  • No, this is how it should work. You need to use call_user_func_array() because you want to pass the params unaltered.
  • Harro Verton wrote on Tuesday 20th of March 2012:
    No, this is how it should work.

    Cool. I thought maybe the parameters were elsewhere in the controller class, and the original method could be called up with a simple parent::router() or something. Just searching Google, people do say that call_user_func_array() is not very fast, especially from PHP 5.3.3, but I expect it is a trivial issue for my site. If this is the way, then I'll go for this. Thanks for your help. Edit: I assume router() does not have a parent that needs to be called, the controller router() being an optional last-in-line? I'll probably move this method to a parent class, and that would allow a generic way to use it in multiple controllers, but also allow a property to be set up to support exceptions, i.e. lists of methods that do not require the user to be logged in. Edit2: Actually, the above code does not quite work as expected. It will also attempt to call a user function that does not exist, if I access the a non-existent action method mycontroller/foobar. Rather than calling up the function directly, the router really needs some way to say, "do what you would have done if I were not here". I really can't see how to do that yet, but will dig into the Controller_Template to see if there are any clues there.
  • Looking through the core, the router() method is handles in core/classes/request.php execute(). If the controller has a router() method, then that method completely replaces the normal routing to the action_* methods. So, once the router() method is defined in a controller, you are on your own - there is no fall-back to what would have been executed if the controller router was not there, and no way to call up a fallback. I'm using a version of Fuel a few months old, so maybe things have changed, but this is something I need to bear in mind.
  • Having a parent router isn't a bad idea, but that will add some overhead while not a lot of people would need this. So it is not part of the default Controller or Controller_Template. It is better to create a layered base controller structure, like we have done in our Depot project (check the repo on github), where we have a global base controller that deals with site wide stuff, and other base controllers for specific functions that extend this base controller. The final application controller in turn extend the specific base controller. Add that generic router() method to your generic base class, and have it deal with checking if the method exists, calling it, or throwing a HTTPExeception.
  • Cool - I check it out. :-) Edit: checked it out - I like the approach, and have implemented it myself now. Thanks. For this application I only have one level of user (a user or not a user), so there is no admin logins, which makes things easier. My application links to a CRM and the users exist only on the CRM, or in a Fuel session if logged in - there are not local copies of the user, so I am not able to use any of the off-the-shelf authentication packages for Fuel (they all - without exception - assume that users will exist in the local database, and so all rely on database-oriented models to work). Anyway, that's for another discussion.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion