Best way to handle menu not found exception?
I'm currently refactoring the menu class in our PHP CMS, and am currently trying to work out the best way to handle the issue where someone tries to create a menu (by passing in the title of the menu (we have main, footer, utility etc menus), but the menu isn't in the database.
If they try to create a menu object with a menu that can be found then there's no problem, I can return the object as requested. If th开发者_如何学编程ey try to create one that isn't found though, I'm currently throwing an exception (which causes an email to be sent), then creating a blank menu object and returning that. The call to output the menu then works without error, but outputs nothing.
(I've done the above by setting it up so a static method of the menu class is called to create a menu object, which can then handle throwing an exception if necessary and return either the requested menu object, or a blank one).
Hopefully all that makes sense! Is this the best method to take? Or is there a more elegant solution?
Chris
Edit:
Here's the static function which is called to create a menu:
static function makeMenu($id,$breakDepth=1){
// try to create Menu
try {
$menu = new Menu($id, $breakDepth);
}
catch (no_menu_found_exception $e) {
// if we failed to find it, an email should have been sent, and create a blank menu so rest of site works without error
$menu = new Menu("");
}
return $menu;
}
and here's the constructor:
function __construct($id,$breakDepth=1){
$this->treeObject = Doctrine_Core::getTable('CmsMenuItemNew')->getTree();
if ($id == "") {
// if ID supplied is empty, return an empty menu object
$this->rootNode = null;
$this->name = $id;
return;
}
if (is_numeric($id)) {
// check it exists?
$this->rootNode = $id;
$node = Doctrine_Core::getTable('CmsMenuItemNew')->findByDQL("menuid = '".$id."'")->getFirst();
$this->name = $node->menutitle;
if ($this->name == "") $this->rootNode = null;
return;
} else {
$this->name = $id;
// find the menu ID for the supplied name
$table = Doctrine_Core::getTable('CmsMenuItemNew');
$table->setOption("orderBy", "level");
$this->rootNode = $table->findByDQL("menutitle = '$id'")->getFirst()->menuid;
// rootNode with supplied name not found, so look for a branch in the main menu
$this->breakDepth = $breakDepth;
if ($this->rootNode === null) {
throw new no_menu_found_exception("Menu not found: ".$id);
}
}
}
as mentioned - its still in development, so not completely finished yet.
Building a blank object is a nice thing. The right design pattern for that is called SpecialObjects. To be complete your code should return a MenuNotFound object which have the same interface as MenuObject. Then the way this MenuNotFound objects reacts to the interface entry points is up to you. This avoid checks on the type of object returned and permits chaining.
For the Exception I personnaly prefer Exception which are only real problems. But in your case if you want to get a mail the exception is not a bad idea, maybe this exception or mail handling could be done in the MenuNotFound init.
精彩评论