【问题标题】:PHP exception and user messagePHP 异常和用户消息
【发布时间】:2011-10-15 15:57:42
【问题描述】:

我有一个项目对象。 用户可以为其分配一个工作对象。

99% 的情况下,项目对象都设置了所有正确的字段。 在某些情况下,项目缺少一个字段。

为了将工作人员分配给项目,该项目必须设置所有必填字段。

为了解决这个问题,我抛出这样的异常:(这里不要试图寻找模式,真实的例子更复杂)

if ($project->startDate == false ) { throw new Exception("缺少项目 ID 的 startDate 属性:$id"); } if ($project->finishDate == false) { throw new Exception("缺少项目 id 的 finishDate 属性:$id"); } if ($project->startDate > $project->finishDate) { throw new Exception("项目 id 的开始日期无效:$id"); }

问题是我每次都需要向用户显示一条自定义消息。例如,如果抛出第一个错误,用户应该会看到:“请设置项目开始日期”等等。

我该怎么做?

【问题讨论】:

    标签: php exception


    【解决方案1】:

    只需在 try .. catch 中定义您自己的异常类和整个代码:

    class FormException extends Exception {
       private var $userMessage;
       public function __construct($message, $userMessage) {
         parent::__construct($message);
         $this->userMessage = $userMessage;
       }
       public function getUserMessage() {return $this->userMessage;}
    }
    
    try {
      // Whole code goes here, probably a function call
      throw new FormException("Missing startDate attribute for project id: $id",
                              'Please setup the project start date');
    } catch (FormException $e) {
      echo $e->getUserMessage();
      error_log($e->getMessage());
    }
    

    顺便说一句,如果您想在字符串中包含变量内容,请使用双引号 ("id: $id") 或连接 ('id: ' . $id)。

    【讨论】:

    • 我已经抛出异常。问题是我需要为每种情况显示不同的东西。我也无法更改消息,因为我会将其记录到 error_log,并且我需要技术信息。
    • @danip 很抱歉,但这段代码完全符合您的描述。它显示您创建异常对象的参数。如果您想记录错误,只需调用error_log 而不是echo
    • 我的问题有点抽象:如何抛出技术错误消息(可以在错误日志中使用)以及如何针对每种情况为用户提供不同的友好消息。
    • @danip 哦,你应该在问题中强调这一点。更新的版本解决了您的问题吗?
    【解决方案2】:

    试试这个:

    try
    {
      $Message = '';
      if ($project->startDate == false ) {
        $Message = "Please setup the project start date\n";
        throw new Exception("Missing startDate attribute for project id: $id");
       }
    
    
       if ($project->finishDate == false ) {
         $Message = "Please setup the project finish date\n";
         throw new Exception("Missing finishDate attribute for project id: $id");
       }
    
       if ($project->approved == false ) {
         $Message = "Please setup the project approved field\n";
         throw new Exception("Missing approved attribute for project id: $id");
       }
    }
    catch(Exception $Ex)
    {
       // Log in some way you like the $Ex-getMessage();
       echo nl2br($Message);
    }
    

    【讨论】:

    • 错误信息是针对用户的技术。我需要为每种情况显示不同的友好用户消息,并使用异常消息进行日志记录。
    • 完成日期怎么样?回声会说开始日期
    • @danip 这不是真的,因为 $Message 只有在您启动异常的情况下才会回显。在所有情况下,你都会回应一些东西。
    • 是的,你是对的,我错过了。我想这就是我需要的。但是如果我必须将逻辑包装在一个函数中呢?
    • 所以 try/catch 块只会有这样的东西: try { $project->SetWorker();} catch (Exception $objEx) { } 。如何获取用户消息?
    【解决方案3】:

    在您的项目类中,创建一个新方法,可能称为getErrorMessage

    该函数应该进行检查(不需要在项目之外有具体的验证方式或为项目创建验证对象)。那么:

    if ($message = $project->getErrorMessage())
    {
        throw new Exception(sprintf('%s (project id: %d)', $message, $id));
    }
    

    如果您出于设计原因决定不抛出异常,这仍然有用。

    您可以使用验证器对象获得更大的灵活性,该对象可以自然地提供比单一方法更详细的信息。所以这可能是更好的做法:

    class ProjectValidator
    {
        private $project;
        private $errors;
        public function __construct($project)
        {
            $this->project = $project;
        }
        public function isValid()
        {
            // run your checks, add errors to the array as appropriate.
    
            $errors = array();
    
            if (!$this->project->startDate)
            {
                $errors[] = 'Missing startDate attribute';
            }
    
            if (!$this->project->finishDate)
            {
               $errors[] = 'Missing finishDate attribute';
            }
    
            if (!$this->project->approved)
            {
                $errors[] = 'Missing approved attribute';
            }
    
            $this->errors = $errors;
    
            return (bool) count($this->errors);
        }
        public function getErrors()
        {
            return $this->errors;
        }
    }
    
    $validator = new ProjectValidator($project);
    if (!$validator->isValid())
    {
        // throw an exception or do whatever you want in case it's not valid
    
        $errors = $validator->getMessages();
        $message = sprintf("Project id: %d has the following %d error(s):\n", $id, count($errors));        
        foreach($errors as $index => $error)
        {
            $message .= sprintf("%d. %s\n", $index+1, $error);
        }
    
        throw new Exception($message);
    }
    

    【讨论】:

    • 您的解决方案很有趣。但我正在寻找一个通用的解决方案。类似于自定义异常类。为每个对象(我有超过 100 个)创建验证器似乎有点多。
    • 您可以使用继承和参数来概括验证器(例如,一个验证器可以验证您的所有对象,只需检查类然后),采用a look into symfony2 for a good example 的实际设计。当然,您也可以执行自定义异常类。但是,我很确定在您的场景中您不需要多个自己的 Exception 类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多