Php 如何在Zend框架中创建模块化MVC组件
我在Zend Framework应用程序中创建模块化可重用组件时遇到问题。在本例中,我不是指Zend框架模块,而是指如果您愿意的话,具有可重用MVC widgety功能的能力。我遇到的问题对我的实现来说可能非常特殊,但如果有人能给我指出正确的方向,我完全乐意将它扔掉,重新开始。无论如何,细节和代码将有望更好地解释事情,即使我所做的不是最好的方式,它也应该显示我试图实现的目标: 一个简单的例子是邮件列表注册表单。我想在使用不同控制器的站点的几个页面上包括这一点,这在如何处理数据和返回相关消息方面提出了一些问题。我不想做以下任何一项,因为它们真的很臭:Php 如何在Zend框架中创建模块化MVC组件,php,model-view-controller,zend-framework,Php,Model View Controller,Zend Framework,我在Zend Framework应用程序中创建模块化可重用组件时遇到问题。在本例中,我不是指Zend框架模块,而是指如果您愿意的话,具有可重用MVC widgety功能的能力。我遇到的问题对我的实现来说可能非常特殊,但如果有人能给我指出正确的方向,我完全乐意将它扔掉,重新开始。无论如何,细节和代码将有望更好地解释事情,即使我所做的不是最好的方式,它也应该显示我试图实现的目标: 一个简单的例子是邮件列表注册表单。我想在使用不同控制器的站点的几个页面上包括这一点,这在如何处理数据和返回相关消息方面提
<?php
class MailingListController extends Zend_Controller_Action {
public function insertAction() {
$request = $this->getRequest();
$returnTo = $request->getParam('return_to');
if(!$request->isPost() || (!isset($returnTo) || empty($returnTo))) {
$this->_redirect('/');
}
$mailingList = new Model_MailingList();
$form = new Form_MailingList();
$returnTo = explode('/', $returnTo);
if($form->isValid($_POST)) {
$emailAddress = $form->getValue('email_address');
$mailingList->addEmailAddress($emailAddress);
$this->view->mailingListMessages = $mailingList->getMessages();
$this->view->mailingListForm = "";
}
else {
$this->view->mailingListForm = $form;
}
$this->_forward($returnTo[2], $returnTo[1], $returnTo[0]);
}
}
<?php
class MailingListController extends Zend_Controller_Action {
public function insertAction() {
$request = $this->getRequest();
$returnTo = $request->getParam('return_to');
if(!$request->isPost() || (!isset($returnTo) || empty($returnTo))) {
$this->_redirect('/');
}
$mailingList = new Model_MailingList();
$form = new Form_MailingList();
if($form->isValid($_POST)) {
$emailAddress = $form->getValue('email_address');
$mailingList->addEmailAddress($emailAddress);
}
else {
$mailingList->setFormErrors($form->getMessages());
}
$redirect = rtrim($request->getBaseUrl(), '/') . $returnTo;
$this->_redirect($redirect);
}
}
我认为你的做法与我的做法非常接近。如果您将希望在页面中显示Zend_表单错误消息的要求放在一边,那么您要做的是:
- 视图帮助器只显示表单(不需要将表单对象或消息作为参数)
- 表单会像现在一样提交给其他控制器
- 成功后,邮件列表控制器将重定向(而不是转发)回返回URL
- 邮件列表控制器自行重新显示表单,并在失败时显示错误
这使得一切变得更简单,唯一的问题是,如果存在任何验证错误,那么用户将丢失其上下文,并获得一个带有表单的普通旧页面,而不是它们所在的位置。然后,您可以通过将表单更改为通过提交来解决此问题(现在或以后)。而使用Ajax,并通过渲染错误。JS。但是这将是一个相当大的工作量。使用ajax似乎是一个最佳的方法。查看操作助手仅用于邮件表单的第一次加载
控制器
class MailingListController extends Zend_Controller_Action {
public function insertAction() {
$request = $this->getRequest();
$form = new Form_MailingList();
if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
$mailingList = new Model_MailingList();
$emailAddress = $form->getValue('email_address');
$mailingList->addEmailAddress($emailAddress);
$form = $mailingList->getMessages();
}
}
$this->view->form = $form;
}
}
class Zend_View_Helper_MailingList extends Zend_View_Helper_Abstract {
public function mailingList() {
$this->view->headScript()->appendFile('/js/mailing-list.js');
return '<div id="mailing-list-wrap">' . $this->view->action('insert', 'mailing-list') . '</div>';
}
}
查看脚本insert.phtml
<?php echo $this->form; ?>
查看帮助程序
class MailingListController extends Zend_Controller_Action {
public function insertAction() {
$request = $this->getRequest();
$form = new Form_MailingList();
if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
$mailingList = new Model_MailingList();
$emailAddress = $form->getValue('email_address');
$mailingList->addEmailAddress($emailAddress);
$form = $mailingList->getMessages();
}
}
$this->view->form = $form;
}
}
class Zend_View_Helper_MailingList extends Zend_View_Helper_Abstract {
public function mailingList() {
$this->view->headScript()->appendFile('/js/mailing-list.js');
return '<div id="mailing-list-wrap">' . $this->view->action('insert', 'mailing-list') . '</div>';
}
}
好的,我想出了一个让我感到高兴的解决方案,解决了我所面临的一些问题。希望这能帮助那些面临类似问题的人。现在唯一的缺点是我在视图辅助对象中引用模型。我知道这不是松散耦合,但我以前见过好几次这样做,在中甚至建议使用它,以避免使用“action”视图帮助器(这将创建一个新的MVC调度循环)。总的来说,我认为干燥和封装是值得的,可能还有其他合适的行话
为了能够使用从MailingListController返回的重定向,但维护来自模型的消息和任何表单验证错误,我需要将它们存储在会话中。对于消息,我通常会使用FlashMessenger操作助手,但由于在视图助手中获取此信息不是最佳做法,因此它不会处理我的表单错误,而且它真正做的只是将内容保存到会话中,这是不必要的。我可以在Model_MailingList中实现我自己的会话存储,我也可以将其用于表单错误。然后,我可以在重定向后用错误重新填充表单,并打印出任何相关消息。不管怎样,代码如下:
控制器:
<?php
class MailingListController extends Zend_Controller_Action {
public function insertAction() {
$request = $this->getRequest();
$returnTo = $request->getParam('return_to');
if(!$request->isPost() || (!isset($returnTo) || empty($returnTo))) {
$this->_redirect('/');
}
$mailingList = new Model_MailingList();
$form = new Form_MailingList();
$returnTo = explode('/', $returnTo);
if($form->isValid($_POST)) {
$emailAddress = $form->getValue('email_address');
$mailingList->addEmailAddress($emailAddress);
$this->view->mailingListMessages = $mailingList->getMessages();
$this->view->mailingListForm = "";
}
else {
$this->view->mailingListForm = $form;
}
$this->_forward($returnTo[2], $returnTo[1], $returnTo[0]);
}
}
<?php
class MailingListController extends Zend_Controller_Action {
public function insertAction() {
$request = $this->getRequest();
$returnTo = $request->getParam('return_to');
if(!$request->isPost() || (!isset($returnTo) || empty($returnTo))) {
$this->_redirect('/');
}
$mailingList = new Model_MailingList();
$form = new Form_MailingList();
if($form->isValid($_POST)) {
$emailAddress = $form->getValue('email_address');
$mailingList->addEmailAddress($emailAddress);
}
else {
$mailingList->setFormErrors($form->getMessages());
}
$redirect = rtrim($request->getBaseUrl(), '/') . $returnTo;
$this->_redirect($redirect);
}
}
我意识到我所面临的许多问题都是由一系列非常特殊的情况造成的,但希望这能在某种程度上帮助其他人
干杯,
Alex因此我发现您可以在视图助手中找到一个动作助手。您可以这样静态地执行:Zend\u Controller\u Action\u HelperBroker::getStaticHelper('flashMessenger')。但这感觉不是很MVC。我确信一定有更好的方法?所以我已经阅读了更多关于动作堆栈和动作助手的内容。两者都提供了解决此问题的潜在方法,但都会产生大量不必要的开销,甚至可能在ZF的未来版本中被删除。我发现本文很有用,并且似乎表明我正在以正确的方式编写一个操作帮助器,以处理视图帮助器中不应该存在的部分。有人有什么想法吗?谢谢,很高兴知道我在正确的轨道上。不过,确认错误和消息很重要,我非常喜欢
<?php
class Model_MailingList extends Thinkjam_Model_DbAbstract {
private $_session;
public function __construct() {
$this->_session = new Zend_Session_Namespace(__CLASS__);
}
public function setFormErrors($errors) {
$this->_session->formErrors = $errors;
}
public function getFormErrors() {
$errors = array();
if(isset($this->_session->formErrors)) {
$errors = $this->_session->formErrors;
unset($this->_session->formErrors);
}
return $errors;
}
// override addMessage and getMessages
protected function addMessage($message) {
if(!isset($this->_session->messages)) {
$this->_session->messages = array();
}
$this->_session->messages[] = $message;
}
public function getMessages() {
if(isset($this->_session->messages)) {
$this->_messages = $this->_session->messages;
unset($this->_session->messages);
}
return $this->_messages;
}
…
public function addEmailAddress($emailAddress) {
...
// I call this if db insert was successful:
$this->addMessage("Thank you. You have been successfully added to the mailing list.")
}
}
<?php
class Zend_View_Helper_MailingList extends Zend_View_Helper_Abstract {
private $_mailingList;
public function MailingList() {
$this->_mailingList = new Model_MailingList();
return $this;
}
public function getForm() {
$request = Zend_Controller_Front::getInstance()->getRequest();
$currentPage = '/' . $request->getModuleName() . '/' . $request->getControllerName() . '/' . $request->getActionName();
$form = new Form_MailingList();
$form->setAction('/mailing-list/insert');
$form->setCurrentPage($currentPage);
$form->setErrors($this->_mailingList->getFormErrors());
$html = '<div class="mailingList"><h2>Join Our Mailing List</h2>' . $form;
$html .= $this->view->messenger($this->_mailingList->getMessages());
$html .= '</div>';
return $html;
}
}
<?php
class Form_MailingList extends Thinkjam_Form_Abstract {
...
public function setErrors(array $errors) {
foreach($errors as $key => $value) {
$this->getElement($key)->setErrors($value);
}
}
}
<?=$this->MailingList()->getForm();?>