Можете ли вы помочь мне исправить обработку сообщения об исключении / ошибке в моем скрипте архитектуры управления? - PullRequest
0 голосов
/ 24 сентября 2010

Можете ли вы помочь мне исправить обработку сообщения об исключении / ошибке в моем скрипте архитектуры управления?

Во-первых, позвольте мне опубликовать реальный сценарий ...

Примечание: некоторые отступы кода немного сбиты, но я не уверен, как это исправить. Я прошу прощения.

</p> <pre><code>class FrontController extends ActionController { //Declaring variable(s) private static $instance; protected $controller; //Class construct method public function __construct() {} //Starts new instance of this class with a singleton pattern public static function getInstance() { if(!self::$instance) { self::$instance = new self(); } return self::$instance; } public function dispatch($throwExceptions = false) { /* Checks for the GET variables $module and $action, and, if present, * strips them down with a regular expression function with a white * list of allowed characters, removing anything that is not a letter, * number, underscore or hyphen. */ $regex = '/[^-_A-z0-9]+/'; $module = isset($_GET['module']) ? preg_replace($regex, '', $_GET['module']) : 'home'; $action = isset($_GET['action']) ? preg_replace($regex, '', $_GET['action']) : 'frontpage'; /* Generates Actions class filename (example: HomeActions) and path to * that class (example: home/HomeActions.php), checks if $file is a * valid file, and then, if so, requires that file. */ $class = ucfirst($module) . 'Actions'; $file = $this->pageDir . '/' . $module . '/' . $class . '.php'; if (!is_file($file)) { throw new FrontControllerException('Page not found!'); } require_once $file; /* Creates a new instance of the Actions class (example: $controller * = new HomeActions();), and passes the registry variable to the * ActionController class. */ $controller = new $class(); $controller->setRegistry($this->registry); try { //Trys the setModule method in the ActionController class $controller->setModule($module); /* The ActionController dispatchAction method checks if the method * exists, then runs the displayView function in the * ActionController class. */ $controller->dispatchAction($action); } catch(Exception $error) { /* An exception has occurred, and will be displayed if * $throwExceptions is set to true. */ if($throwExceptions) { echo $error->errorMessage($error); //Full exception echoed } else { echo $error->errorMessage(null); //Simple error messaged echoed } } } } abstract class ActionController { //Declaring variable(s) protected $registry; protected $module; protected $registryItems = array(); //Class construct method public function __construct(){} public function setRegistry($registry) { //Sets the registry object $this->registry = $registry; /* Once the registry is loaded, the controller root directory path is * set from the registry. This path is needed for the controller * classes to work properly. */ $this->setPageDir(); } //Sets the controller root directory from the value stored in the registry public function setPageDir() { $this->pageDir = $this->registry->get('pageDir'); } //Sets the module public function setModule($module) { $this->module = $module; } //Gets the module public function getModule() { return $this->module; } /* Checks for actionMethod in the Actions class (example: doFrontpage() * within home/HomeActions.php) with the method_exists function and, if * present, the actionMethod and displayView functions are executed. */ public function dispatchAction($action) { $actionMethod = 'do' . ucfirst($action); if (!method_exists($this, $actionMethod)) { throw new FrontControllerException('Page not found!'); } $this->$actionMethod(); $this->displayView($action); } public function displayView($action) { if (!is_file($this->pageDir . '/' . $this->getModule() . '/' . $action . 'View.php')) { throw new FrontControllerException('Page not found!'); } //Sets $this->actionView to the path of the action View file $this->actionView = $this->pageDir . '/' . $this->getModule() . '/' . $action . 'View.php'; //Sets path of the action View file into the registry $this->registry->set('actionView', $this->actionView); //Includes template file within which the action View file is included require_once $this->pageDir . '/default.tpl'; } } class Registry { //Declaring variables private $store; //Class constructor public function __construct() {} //Sets registry variable public function set($label, $object) { $this->store[$label] = $object; } //Gets registry variable public function get($label) { if(isset($this->store[$label])) { return $this->store[$label]; } return false; } //Adds outside array of registry values to $this->store array public function addRegistryArray($registryItems) { foreach ($registryItems as $key => $value) { $this->set($key, $value); } } //Returns registry array public function getRegistryArray() { return $this->store; } } class FrontControllerException extends Exception { public function errorMessage($error) { //If throwExceptions is true, then the full exception is returned. $errorMessage = isset($error) ? $error : $this->getMessage(); return $errorMessage; } }

Теперь проблема ... Если я введу URL с несуществующим модулем (в следующем примере "BLAH") ...

<a href="http://example.com/index.php?module=BLAH&action=frontpage" rel="nofollow">http://example.com/index.php?module=BLAH&action=frontpage</a>

... Я получаю не просто сообщение об ошибке "Страница не найдена!" но следующее сообщение об ошибке ...

Fatal error: Uncaught exception 'FrontControllerException' with message 'Page not found!' in /web/example.com/library/php/ControlArchitecture.php:45 Stack trace: #0 /web/example.com/index.php(30): FrontController->dispatch(false) #1 {main} thrown in /web/example.com/library/php/ControlArchitecture.php on line 45

Любые идеи о том, почему я просто не получаю "Страница не найдена!" сообщение (вместо необработанного исключения)? Любые идеи о том, как исправить это поведение?

Еще раз спасибо!

1 Ответ

0 голосов
/ 24 сентября 2010

Сообщение об ошибке на самом деле говорит само за себя.

Если аргумент FrontController->dispatch() методов имеет значение true или false, то исключение все равно будет выдано .. (если есть какая-то магия фреймворка , пожалуйста, дайте нам знать какой фреймворк вы используете)

Поэтому убедитесь, что вы ловите исключение, когда вы его называете:

/* ... */

  try {
    FrontController->dispatch(false);
  } catch (Exception $ex) {
    echo "Eception caught: " . $ex.getMessage();
  }

/* ... */

Обновление:

Здесь вы можете прочитать об исключениях в PHP и о том, как их перехватить.

О несуществующей проблеме модуля:

$regex  = '/[^-_A-z0-9]+/';
$module = isset($_GET['module']) ? preg_replace($regex, '', $_GET['module']) : 'home';
$action = isset($_GET['action']) ? preg_replace($regex, '', $_GET['action']) : 'frontpage';

$class = ucfirst($module) . 'Actions';
$file  = $this->pageDir . '/' . $module . '/' . $class . '.php';

if (!is_file($file)) {
    throw new FrontControllerException('Page not found!');
}

IF-Statement только проверяет, существует ли файл модуля (Pattern: ModuleActions.php) в этом случае BLAHActions.php или нет.Как только оно сгенерирует исключение, ваш вызов будет отменен, и он не будет обработан обработан .(Это означает, что он даже не будет продолжать проверять параметр Action)

О несуществующей проблеме действия:

Насколько я понимаю из опубликованного кода, следующий метод:

public function dispatchAction($action) {
    $actionMethod = 'do' . ucfirst($action);
    if (!method_exists($this, $actionMethod)) {
        throw new FrontControllerException('Page not found!');
    }
    $this->$actionMethod();
    $this->displayView($action);
}

делает вызовы требуемого действия (Pattern: doSomething), в этом случае doFrontPage даже не вызывается, потому что ваш код заранее вызывает исключение.

Вызов несуществующего действия делаетне выбрасывайте необработанное исключение, потому что это handled в вашем методе FrontController-> dispatch () сразу после проверки модуля:

try {
    //Trys the setModule method in the ActionController class
    $controller->setModule($module);

    /* The ActionController dispatchAction method checks if the method
     * exists, then runs the displayView function in the
     * ActionController class.
     */    
    $controller->dispatchAction($action);
}
catch(Exception $error) {

    /* An exception has occurred, and will be displayed if
     * $throwExceptions is set to true.
     */
    if($throwExceptions) {
        echo $error->errorMessage($error); //Full exception echoed
    } else {
        echo $error->errorMessage(null); //Simple error messaged echoed
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...