2013-10-14 37 views
2

可以说我有发送电子邮件的一个基本的HTML表单:PHP MVC脂肪控制器VS高脂模型

<form action="contactSubmit" method="POST"> 
    <label for="name" class="italic">Name:</label> 
    <input type="text" name="name" value="" maxlength="20" required="required" autofocus="autofocus" /> 
    <label for="email" class="italic">E-mail:</label> 
    <input type="email" name="reply_to" value="" maxlength="255" required="required" /> 
    <label for="comments" class="italic">Comments:</label> 
    <textarea name="message" rows="10" cols="50" required="required"></textarea> 
    <br /> 
    <input type="submit" class="submit" value="Send" /> 
</form> 

目前所有的验证是在控制器完成:

// submit contact request 
public function contactSubmit() { 
    // process form if submitted 
    if ($this->formSubmit()) { 
     // validate input 
     $name = isset($_POST['name']) && $this->validate($_POST['name'], null, 20) ? $_POST['name'] : null; 
     $reply_to = isset($_POST['reply_to']) && $this->validate($_POST['reply_to'], 'email', 255) ? $_POST['reply_to'] : null; 
     $message = isset($_POST['message']) && $this->validate($_POST['message']) ? $_POST['message'] : null; 

     // proceed if required fields were validated 
     if (isset($name, $reply_to, $message)) { 
      $to = WEBMASTER; 
      $from = '[email protected]' . $_SERVER['SERVER_NAME']; 
      $reply_to = $name . ' <' . $reply_to . '>'; 
      $subject = $_SERVER['SERVER_NAME'] . ' - Contact Form'; 

      // send message 
      $mail = $this->model->build('mail'); 
      if ($mail->send($to, $from, $reply_to, $subject, $message)) { 
       $_SESSION['success'] = 'Your message was sent successfully.'; 
      } else { 
       // preserve input 
       $_SESSION['preserve'] = $_POST; 

       // highlight errors 
       $_SESSION['failed'] = 'The mail() function failed.'; 
      } 
     } else { 
      // preserve input 
      $_SESSION['preserve'] = $_POST; 

      // highlight errors 
      if (!isset($name)) { 
       $_SESSION['failed']['name'] = 'Please enter your name.'; 
      } 
      if (!isset($reply_to)) { 
       $_SESSION['failed']['reply_to'] = 'Please enter a valid e-mail.'; 
      } 
      if (!isset($message)) { 
       $_SESSION['failed']['message'] = 'Please enter your comments.'; 
      } 
     } 
    } 

    $this->view->redirect('contact'); 
} 

我想从“胖控制器”转向“胖控制器”,但是我不能为我的生活弄清楚如何将验证从前一个控制器完全移植到前面的模型中:

public function send($to, $from, $reply_to, $subject, $message) { 
    // generic headers 
    $headers = 'MIME-Version: 1.0' . PHP_EOL; 
    $headers .= 'From: ' . $from . PHP_EOL; // should belong to a domain on the server 
    $headers .= 'Reply-to: ' . $reply_to . PHP_EOL; 

    // send message 
    return mail($to, $subject, $message, $headers); 
} 

形式只有3个所需的字段,而模型的方法接受5.表单字段的描述是从输入的名称,这使得难以以自定义的错误消息,同时保持模型便携式用于其它应用使用不同。看起来,我所做的每一次尝试都变得非常胖,仍然没有达到与初始方法相同的灵活性。

可能有人请告诉我一个干净的方式从控制器移动验证的模型,同时仍保持自定义错误消息的灵活性,并保持模型的便携性在其他应用程序使用?

+0

[MVC Validation Advice]的可能重复(http://stackoverflow.com/questions/19351502/mvc-validation-advice) –

+0

验证的部分与业务逻辑相关,应在[域对象] (http://c2.com/cgi/wiki?DomainObject)。数据完整性检查应该通过存储抽象来处理。类似MVC体系结构中的控制器具有**没有任何**用于验证。此外,没有“胖模特”。模型不是一个类。 –

+1

@tereško当他说模型(实体,数据对象,命令对象,你在域层中拥有的任何对象)时,他指的是域对象。但是没有任何mvc框架真正教会程序员如何构建域图层。例如,Laravel在文档中为模型层提供了一种数据驱动的方式,而不是DDD。 –

回答

1

首先,你真的使用纯粹的面向对象?为什么要使用带外部数据的模型方法?该模型应该与它自己的属性一起工作。如果创建对象所需的数据无效,则不应该实例化模型对象。

您需要创建更多layeres将与模型通信。例如,您可以拥有一个可以处理此验证的modelFactories图层。比方说,你有一个用户模型,在你有一个UserFactory的modelFactories层。你可以在这里放置验证逻辑。如果创建用户模型所需的数据无效,则不要创建该模型。

更抽象的方式是添加更多layeres像dataTransferObjects层。在这里,您可以拥有将数据传输到模型或模型工厂的对象。再次,您可以将验证逻辑放在此处,然后可以使用modelFactory从UserDTO对象(用户数据传输对象)创建用户模型。

事情是,你不应该在没有准备好数据之前创建模型,就像验证它。这就是为什么一个模型应该与它自己的属性一起工作,并且不会在外部数据中正确传递(只传递数据来初始化对象)。

您应该阅读更多关于领域驱动设计和设计模式。

所以这样你的模型逗留分离,并且可以在其他应用程序重用。

+0

所以你说脂肪控制器方法没有错?因为这正是我正在做的,所以在实例化模型之前验证数据。 –

+1

是的我在说控制器侧的验证比模型更好。但最好的办法是通过添加更多的layeres来重构您的应用程序,如上所述。当然这也取决于:)如果它是一个小应用程序(并且不需要扩展)不要过度构建它。 –

1

我说不应该胖。处理HTML表单时,我认为拥有一个Form对象(如CommentForm)具有自己的字段级别验证的字段对象(例如,EmailField extends Field)是最干净的。

如果表单验证,那么你肯定有干净的数据。该表单还可以创建并返回各种模型,这些模型本身也可以在成员级别进行验证。但没有什么是脂肪......每一点只需要知道立即关心他们的东西。

控制器看起来是这样的:

if ($form->validate($request->post())) { 
    // grab the email model from the form 
    $email = $form->getEmail(); 

    // assume $mailTransport implements some mailer interface 
    if ($mailTransport->send($email) == true) { 
    // sent email 
    return $response->redirect('success'); 
    } 
    else { 
    // something unexpected happened 
    $view->flashError('Unable to send email'); 
    } 
} 

$view->form = $form; 

每个控制器处理最终看起来非常相似,很干净。这些模型对HTML表单一无所知。这是一个反复重复的简单模式。

有很多方法可以做到这一点;以上只是我最喜欢的通用解决方案。