簡體   English   中英

模型現在正在執行數據/表單驗證。 如何將用戶友好的錯誤消息返回到視圖?

[英]Model now doing data/form validation. How to return user friendly error messages to the view?

從今天開始,我開始在模型層而不是控制器中驗證表單數據。 我將盡可能縮短代碼段。

這是我的User域對象中的一個方法( setLastName()方法基本相同)

public function setFirstName($firstName) {

    if(!$firstName) throw new \InvalidArgumentException('Some message');
    if( strlen($firstName) < 2  || strlen($firstName) > 20 ) throw new \LengthException('Some message');
    if(preg_match('/[^a-zA-Z\'.-\s]/', $firstName)) throw new FormatException('Some message');

    $this->firstName = $firstName;
}

在我的控制器中,我有這樣的東西

$userService = $this->serviceFactory->build('User');

try {
    $userService->register('John', 'M');
} 
catch(\InvalidArgumentException $ex) {

}
catch(\LengthException $ex) {

}
catch(etc etc)

在我的UserService方法register()我有類似

$user->setFirstName($firstName);
$user->setLastName($lastName);

運行setFirstName()方法時,它將成功設置提供的名字。 setLastName()方法將拋出一個LengthException因為它太短了。

那就是我想要的,但是當返回到服務層然后到控制器時,我抓住了它,我知道拋出了LengthException ,但是我無法向用戶提供諸如“提供的姓氏太短”的正確消息”,因為我不知道該異常是針對哪個字段拋出的,僅是異常的類型。

我該如何解決? 謝謝。

視圖實例應從模型層請求信息。 控制器不負責傳遞信息。

這也意味着您強迫性地使用導致抽象層泄漏的異常是完全沒有意義的。 “錯誤”只是模型層的一種狀態。 這是一種預期的情況,並非例外。

MVC中的控制器負責更改模型層的狀態和(很少)更改當前視圖實例的狀態。 他們不應從服務中收到任何反饋。

為什么不返回有用的錯誤消息 ,而不是返回某些消息 ,例如“提供的名字太短” 然后可以將其返回給用戶。

另外,您可以看到擴展例外時可以指定其他信息,例如數字代碼-您當然可以使用它。

或者當然,您可以為不同的情況創建Exception的子類,但是最終可能會產生數百個Exception子類,這當然很麻煩。

我也有同樣的問題。 我認為大多數說所有驗證都應該在模型中完成的人自己從來沒有開發過完整的PHP MVC應用程序,只知道書籍和理論。 從來沒有人看到有關該主題的代碼。

無論如何,我想到了一個可能的解決方案。 您如何看待以下代碼:

// Controller

$user = User::make(
    $_POST['lastname'], $_POST['firstname'], 
    $_POST['gender'], [...]
);
if(is_array($user)) {
    // store the errors in a view variable and forward, or store in session and redirect
    $_SESSION['errors'] = $user;
    $this->_redirect('add');
    exit;
}

// Model

public static make($lastname, $firstname, $gender, [...]) {
    $errors = array();
    if(/* test firstname */) $errors[] = 'model_error_firstname';
    if(/* test lastname */) $errors[] = 'model_error_lastname';
    if(!empty($errors)) return $errors;

    return new User($lastname, $firstname, $gender, [...]);
}

該模型將具有靜態函數,該函數將在出錯時返回帶有錯誤的數組,或者在驗證正常的情況下返回新的模型對象。

在您的控制器中,您測試是否返回了數組。

也許我會將User的構造函數設置為私有,因為如果直接用該構造函數構建用戶,則將跳過所有驗證。 但這並不意味着它成為一個Singleton。

也許我還要在將表單域傳遞給模型之前對表單域進行清理並使其安全。

諸如model_error_xyz之類的鍵將在帶有適當文本的翻譯文件中找到。

更新:

實際上,我認為您可以從構造函數中拋出一個自定義異常,該異常包含一個消息數組。 但是我之所以沒有提出這個建議,是因為它導致了一半構造的對象,至少在Java中如此,但是嘿,PHP不是Java ...

您還必須驗證每個setter函數:(在模型實例中進行驗證似乎很麻煩。

任何想法都歡迎。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM