在Zend Framework中处理记录表单的最佳方法

时间:2009-08-03 16:06:45

标签: php zend-framework forms

一旦你使用Tutorial中的示例构建的基本记录表单就可以了,你会发现你需要更专业的记录表格。例如。我不想在用户和管理区域中复制同一个表的记录表格。

1)是否有人使用某种机制(可能是继承)来减少几乎相似的管理员和用户表单的重复?这有点麻烦,有时你最好只做复制粘贴吗?

2)有没有人认为构建一些基本的Record类

是个好主意
  • 可以确定在此页面上的几个记录表单中,当前帖子专门针对此记录表格
  • 可以以某种有组织的方式区分编辑或删除按钮。

3)我目前的做法包括将所有表单配置代码(装饰器,验证,初始值)放入构造函数中,并将表单提交处理放入单独的ProcessSubmit()方法中以释放不必要代码的控制器。

所有上述内容都涉及一些预期的记录表格功能,我想知道是否有任何指南,这种稍微更先进的记录处理的良好样本应用程序或人们仍在重新启动方向盘。想知道你应该走多远,你应该停止这样的改进......

2 个答案:

答案 0 :(得分:2)

一些建议:

首先 - 在子类化表单时,使用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_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;
  }

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

答案 1 :(得分:1)

我创建了SimpleTable extends Zend_Db_TableSimpleForm extends Zend_Db_Form个类。这两个都假设您的表具有自动递增ID列。

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

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

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