I wanted to throw in flame words like "pervasive" or "overuse" just to stir the pot a bit, but I want to express ahead of time that I'm assuming there's a good reason for this. On to my point: Is there some particular reason why SilverStripe prefers to use user_error() instead of throwing exceptions?
My assumption (benefit of the doubt) is that this is to ensure that execution can still continue without halting per se. Instead, the standard practice would be to simply return some default/empty value from the current method to prevent further execution locally without propagating that too far.
However, this gets in the way of my ability to properly (or cleanly, I guess) handle errors when they occur. What if we just did a better job with exception handling and ensured we had a more solid process of wrapping particularly error prone operations with try{}/catch() blocks? See here for what you end up having to do in order to compensate for the fact that errors may occur but may not be catchable:
https://github.com/patricknelson/silverstripe-migrations/blob/master/code/MigrateTask.php#L74
One solution to this may be to use something akin to "withExceptions()" wrapper which allows more programmatic control and capture over the errors that are triggered in SilverStripe. I have written this into my own adaptation of the SilverStripe framework so I can have fine grained control over any possible unexpected errors which may occur during various automated tasks (such as cron or deployment). It looks a bit like this, as a slight modification of the above, and uses closures in order to help isolate and maintain state properly:
Maybe others will find this useful. What do you guys think? Could this be integrated more into SilverStripe at large or should it be just a module? Furthermore, should SilverStripe do more to use Exceptions either exclusively (with heavy use of try/catch blocks) or optionally as a generic placeholder (abstraction) via configuration in place of straight up use of the user_error() function?
- Patrick