A quick thought which I need to explore some more, but I thought I’d write it down. (it is worrying when you can’t sleep for thoughts of PHP authentication, front controllers, and PEAR error handlers)

All of the examples of custom PEAR error handlers I’ve ever see (of which Ludoo’s is the clearest) all show using them for a better pretty print. Some talk about having them do logging, or fire off an email. But is anyone using them to implement application logic?

Front controllers are a lovely design pattern for web apps, but a number of people have argued they aren’t suited to PHP (and PHP is not suited to them). Which is a shame, because they’re really useful for a number of task. One of those is enforcing proper credentials, and dealing with authentication/authorization failures intelligently.

Seems like you could get the intelligent dispatching aspect of a front controller, without having to front load your authorization knowledge or give up your page centric development model.

At the beginning of your script you have some check like:


$user = $auth->valid_user();
if (not $user) {
   $this->throwError('Unknown user', AUTH_FAILURE_UNKNOWN, array( 'referer' => 'my_script.php') );
}
elseif (not $user->can_do_foo() ) {
   $this->throwError("I'm sorry but you don't have permission to foo", AUTH_FAILURE_INSUFFICIENT_PERMS );
}

… meanwhile over in auth.php


define('AUTH<em>FAILURE</em>UNKNOWN', 1001);
define('AUTH<em>FAILURE</em>INSUFFICIENT<em>PERMS', 1002);
...
function valid</em>user {
...check cookies, session vars, whatever....
}

… and then the error handler does something like … ```

function errorHandler($err) { if ( $err->getCode == AUTH_FAILURE_UNKNOWN ) { … take user to login page, …. then send them back to attempted action using ‘referer’ var } elseif ( $err->getCode == AUTH_FAILURE_INSUFFICIENT_PERMS ) { … maybe take them to a warning page? … or merely return the error for inline display } else { return, print, die, whatever works for your app } }


Did you notice the hand waving? (“Its all hand waving Kellan!”, yes but some it more then most) How do we “take the user” somewhere? And ensure that the proper flow of the app is maintained? After all these aren’t real exceptions, flow isn’t going to terminate here. There are two solutions.

If you’ve been good, I mean **really** good, and you know that you haven’t sent any data back to the user yet (this includes blank lines that somehow got sucked in by your cascading includes) then you can use header(“Location: $login*page”) to redirect the user. An example of when you might have been this good is when you’ve mandated that all content is generated by template files, after all the logic has completed, and even then.*

Another option which I just realized tonight, which got me started writing all this, and is of course obvious, but I hadn’t thought of it is to simple do something like

elseif ( $err->getCode == AUTHFAILUREINSUFFICIENTPERMS ) { include(‘you-dont-have-that-kind-access.php’); exit; } ```

I tend to think of PHP’s exit, which a synonym for die() in terms of Perl’s die, which is used to flag untoward circumstances, but in fact PHP apps can exit without it being an indication of anything the matter. You can argue that all this error handling, and indirection increase the “magic factor” of your script, but for my money I think this would be a huge win in terms of readability, and centralization of logic without requiring one to buy into to an entire MVC framework.