2013-10-13 86 views
0

我目前正在驗證輸入,並在「脂肪控制器」如下返回錯誤:MVC驗證諮詢

class SomeController 
{ 
    public function register() 
    { 
     // validate input 
     $username = isset($_POST['username']) && strlen($_POST['username']) <= 20 ? $_POST['username'] : null; 

     // proceed if validation passed 
     if (isset($username)) { 
      $user = $this->model->build('user'); 
      if ($user->insert($username)) { 
       $_SESSION['success'] = 'User created!'; 
      } else { 
       $_SESSION['error'] = 'Could not register user.'; 
      } 
     } else { 
      $_SESSION['failed']['username'] = 'Your username cannot be greater than 20 characters.'; 
     } 

     // load appropriate view here 
    } 
} 

class SomeModel 
{ 
    public function insert($username) 
    { 
     // sql for insertion 
     // ... 

     return $result; 
    } 
} 

雖然這個作品,是很容易爲我實現,我明白,這是由於不正確驗證所屬的模型,我試圖用「肥模式」如下更正:

class SomeController 
{ 
    public function register() 
    { 
     $user = $this->model->build('user'); 
     $user->insert($_POST['username']); 

     // load appropriate view here 
     // ... 
    } 
} 

class SomeModel 
{ 
    public function insert($username) 
    { 
     // validate input 
     $error = false; 
     $username = trim($username) != '' && strlen($username) <= 20 ? $username : null; 

     // proceed if validation passed 
     if (isset($username)) { 
      // sql for insertion 
      // ... 

      $_SESSION['success'] = 'User created!'; 
     } else { 
      // store error in session 
      $error = true; 
      $_SESSION['error']['username'] = 'Your username cannot be greater than 20 characters '; 
     } 

     return $error ? false : true; 
    } 
} 

我看到這裏的問題是,該模型被認爲是便攜式的,因爲它永遠不應該需要改變。但是如果對$username的長度的要求發生變化,那麼顯然我將不得不改變我的模型。

我覺得這可能是一個很常見的問題,但我還沒有找到一個直截了當的答案。如果沒有實現任何額外的「層」,「映射器」或任何其他令人困惑的術語,那麼如何修改提供的示例僞代碼以正確處理此事務呢? (例如,驗證輸入,如果驗證失敗則返回錯誤)?

+1

如果您想要一個簡單的一類解決方案,那麼它取決於您的RDBMS選擇。在oracle或postgresql中,你可以在表的'username'字段上設置'CONSTRAINT'。違反數據庫中的數據完整性會引發異常。不幸的是,我不確定是否有任何簡單的方法在mysql中執行相同的操作。這就是說,我必須問一件事:你到底聽說過「模型不應該改變」的地方?因爲那是BS。 –

回答

6

沒有實施任何額外的「層」,「映射器」或任何

你應該考慮的「模式」是一個應用層,而不是一個單獨的類。術語「層」可以被認爲是引用MV切片三明治的簡單方法。所以爲了實現你想要的靈活性,你需要來創建它。

可以做出許多明確的分離。我會考慮有三個抽象:服務,數據映射器和實體。

服務將暴露給控制器並執行請求的服務

// some controller 
function register() { 
    $service = $this->getUserService(); 
    $user = $service->register($_POST['first_name'], $_POST['last_name']); 
    if ($user instanceof \My\Entity\User) { 
    // set user in view 
    } else { 
    // redirect to error 
    } 
} 

所以任務一次完成,控制器現在是啞巴寄存器中無論發生什麼事,所有它想知道的是如何解決相應的結果。如果有用戶對象,則成功,否則會出錯。

服務類本身將封裝所提供的服務:

// class UserService.php 
function register($firstname, $lastname) { 
    // validate arguments 
    if ($this->isValidUsername(.... 
    $userMapper = $this->getUserMapper(); 
    $user = new My\Entity\User(); 
    $user->setFirstName($firstname); 
    $user->setLastName($lastname); 
    return $userMapper-save($user); 
    } 
    return false; 
} 

我們處理的參數驗證,並創建新的用戶,把它傳遞給數據映射器將執行「實際保存「抽象數據庫操作。

// UserMapper 
function save($user) { 
    // save $user to db 
    $sql = 'INSERT INTO .... 

return true; 
} 
+0

所以基本上你只用控制器來控制應用層?這意味着表單驗證應該由應用程序層來處理? (檢查名稱,唯一性,接受的條款等)。這意味着Controller只會傳遞表單的數據,對嗎? –

1

我不確定你會認爲是一個不需要的「層」或「映射器」。這是一個有趣的問題,我的第一個問題是,你可以只包含一個配置文件,爲你的用戶名長度定義一個常量。我的第二個,但是你可以有一些模型擴展一個類或實現一個接口,其中你的值將被設置爲屬性或常量。我懷疑你已經想到了這些,並且正在避開它們;這是你避免「層」和「映射器」是什麼意思你好像是被這些校長在這段代碼指導:

  • 避免「幻數」
  • KISS
  • 組成了繼承
  • 瘦控制器和/或脂肪模型

那麼,你運行php5.4 +?也許定義一個特徵,可以在這個和其他模型中使用,定義應用程序中的用戶名長度和其他可更改的值。或者,也許這也是一個「層」的大部分?