Php 在Zend框架中处理记录表单的最佳方法

Php 在Zend框架中处理记录表单的最佳方法,php,zend-framework,forms,Php,Zend Framework,Forms,一旦你们对根据教程中的示例构建的基本记录表单感到满意,你们就会意识到你们需要更专业的记录表单设计。例如,我不想在用户和管理区域复制同一个表的记录表单 1) 是否有人使用某种机制(可能是继承)来减少几乎相似的管理和用户表单的重复?这是不是很累人,或者有时候你最好直接用拷贝粘贴 2) 有人认为建立一些基本的记录类是个好主意吗 这可以确定在这个页面上的几个记录表单中,当前的帖子是专门针对这个记录表单的 以某种有组织的方式区分“编辑”按钮和“删除”按钮的单击 3) 我目前的做法包括将所有表单配置代码

一旦你们对根据教程中的示例构建的基本记录表单感到满意,你们就会意识到你们需要更专业的记录表单设计。例如,我不想在用户和管理区域复制同一个表的记录表单

1) 是否有人使用某种机制(可能是继承)来减少几乎相似的管理和用户表单的重复?这是不是很累人,或者有时候你最好直接用拷贝粘贴

2) 有人认为建立一些基本的记录类是个好主意吗

  • 这可以确定在这个页面上的几个记录表单中,当前的帖子是专门针对这个记录表单的
  • 以某种有组织的方式区分“编辑”按钮和“删除”按钮的单击
3) 我目前的做法包括将所有表单配置代码(装饰器、验证、初始值)放入构造函数,并将表单提交处理放入单独的ProcessSubmit()方法中,以释放控制器中不必要的代码

以上所有内容都涉及到一些预期的记录表单功能,我想知道是否有任何指导原则,对于这种稍微更高级的记录处理,是否有好的示例应用程序,或者人们仍在重新发明轮子。想知道你应该走多远,你应该在哪里停下来做这些改进…

几点建议:

首先-在对表单进行子类化时,使用
init()
函数而不是构造函数来添加元素。init()函数在设置传递给类的参数后执行

第二,您可以设置一个“选项”来启用管理功能,而不是对表单进行子类化:

class My_Record_Form extends Zend_Form {
    protected $_record = null;
    public function setRecord($record) {
      $this->_record = $record;
    }

    public function getRecord() {
      if ($this->_record === null || (!$this->_record instanceOf My_Record)) {
        throw new Exception("Record not set - or not the right type");
      }
      return $this->_record;
    }

    protected $_admin = false;
    public function setAdmin($admin) {
      $this->_admin = $admin;
    }

    public function getAdmin() { return $this->_admin; }

    public function init() {
      $record = $this->getRecord();

      $this->addElement(......);
      $this->addElement(......);
      $this->addElement(......);

      if ($this->getAdmin()) {
        $this->addElement(.....);
      }

      $this->setDefaults($record->toArray());
    }

    public function process(array $data) {
      if ($this->isValid($data)) {
        $record = $this->getRecord();
        if (isset($this->delete) && $this->delete->getValue()) {
          // delete button was clicked
          $record->delete();
          return true;
        }
        $record->setFromArray($this->getValues());
        $record->save();
        return true;
      }
    }
}
然后在控制器中,您可以执行以下操作:

$form = new My_Record_Form(array(
  'record'=>$record, 
  'admin'=>My_Auth::getInstance()->hasPermission($record, 'admin')
));
制作一个My_Record_Admin_表单来处理管理员的事情并没有什么“错误”——但是我发现这个方法将所有“Record Form”代码保存在一个地方,并且更易于维护

回答第2节:我的代码中的编辑表单是从模型的函数返回的:
$record->getEditForm()
控制器代码最终看起来有点像这样:

  protected $_domain = null;
  protected function _getDomain($allowNew = false)
  {
    if ($this->_domain)
    {
      return $this->view->domain = $this->_domain;
    } else {
      $id = $this->_request->getParam('id');
      if (($id == 'new' || $id=='') && $allowNew)
      {
        MW_Auth::getInstance()->requirePrivilege($this->_table, 'create');
        $domain = $this->_table->createRow();
      } else {
        $domain = $this->_table->find($id)->current();
        if (!$domain) throw new MW_Controller_404Exception('Domain not found');      
      }
      return $this->view->domain = $this->_domain = $domain;
    }
  }

  public function editAction()
  {
    $domain = $this->_getDomain(true);

    MW_Auth::getInstance()->requirePrivilege($domain,'edit');
    $form = $domain->getEditForm();

    if ($this->_request->isPost() && $form->process($this->_request->getPost()))
    {
      if ($form->delete && $form->delete->getValue())
      {
        return $this->_redirect($this->view->url(array(
          'controller'=>'domain', 
          'action'=>'index',
        ), null, true));
      } else {
        return $this->_redirect($this->view->url(array(
          'controller'=>'domain', 
          'action'=>'view',
          'id'=>$form->getDomain()->id,
        ), null, true));        
      }
    }    
    $this->view->form = $form;
  }

例如,在URI/domain/edit/id/10中传递记录的实际id。如果要在一个页面上放置多个表单,则应确保将表单的“action”属性设置为指向特定于该表单的操作。

我创建了一个
SimpleTable Extendes Zend_Db_Table
SimpleForm Extendes Zend_Db_form
类。这两种方法都假定表具有自动递增的ID列

SimpleTable
有一个
saveForm(SimpleForm$form)
函数,它使用动态绑定将表单元素名称与记录的列相匹配。我还包括一个可重写的
saveFormCustom($form)
,用于任何特殊处理

SimpleForm
有一个抽象的
setup()
,必须重写它才能设置表单。我使用
init()
进行初始设置(例如添加隐藏的ID字段)

但是,老实说,我真的不喜欢使用
Zend_Form
对象,我觉得应该在视图中处理它,而不是在模型或控制器中