Zend表格:我如何让自己的意志屈从?

我已经多次阅读手册,我已经search了Google提供的关于这个主题的post,甚至还买了几本和ZF打交道的书。 现在,为什么我还是困惑?

我可以使用Zend_Form创build一个表单来validation和正常工作。 我无法做到这一点的forms,看起来就像我希望看到我想要的错误信息。 我想要自定义button,我想要时髦的布局,我想插入表单中的文本等。

有没有人有一个简单的方法来实现这些东西? 让我感觉像框架的东西是节省我的时间,而不是花费? 我可以放弃Zend Form …制作自己的表单,让它的行为碰到一个页面来validation和处理发布的数据,我可以尽可能快地做到这一点,但我真的想“得到”,并能够使用它,因为它显然是有意的。

有什么build议? 任何简单的“如何”为自定义button,时髦的布局和基本(或更先进,因为有大量的基本教程,跳过了更难的问题)“完成任务”与zendforms?

巴雷特·康拉德的build议是我所build议的。 另外,请记住,您不需要使用表单对象来呈现您的表单。

你可以做的一件事就是在你的视图脚本中创build一个与表单类名称相同的表单。

您的HTML表单:

<form action="/login/" method="post"> <fieldset> <label for="username">Username:</label> <input type="text" size="10" name="username" /> <label for="password">Password:</label> <input type="password" size="10" name="password" /> <input type="submit" /> </fieldset> </form> 

你的class:

 class LoginForm extends Zend_Form { public function init() { $username = $this->createElement('text','username'); $username->setRequired(true); $this->addElement($username); $password = $this->createElement('password','password'); $password->setRequired(true); $this->addElement($password); } } 

你的表单类反映了你的HTML表单,你的类中的每个元素都有自己的validation器和需求。 回到你的行动中,你可以创build一个你的表单类的实例,并validation你的表单/ get vars:

 $form = new LoginForm(); if ($this->_request->isPost()) { if ($form->isValid($this->_request->getParams())) { // do whatever you need to do } else { $this->view->errors = $form->getMessages(); } } 

您可以使用此方法在一个组中显示窗体顶部的错误消息。

这是一个基本的例子,但它可以让你完全控制表单的performance,而不用花时间去学习使用装饰器。 在我看来,Zend_Form的大部分优势在于validation和过滤属性。 这给了你这个力量。 这样的解决scheme的主要缺点是,您的视图脚本HTML表单可能会失去与您的表单类同步。

例如,在视图中分别渲染每个元素

 <!-- view script here --> <form method="POST"> Name: <?php echo $this->myForm->getElement('name')->render(); ?> some other text between the fields Birthdate: <?php echo $this->myForm->getElement('birthdate')->render(); ?> <input type="submit" /> </form> 

这保持了使用Zend_Form视图助手(即在validation失败时显示错误消息并维护表单字段的值)的能力,但是可以给你完全的定制能力。

如果你想进一步,然后closures各个表单元素的默认装饰器,然后附上自己的进一步定制使用什么标签(即错误消息和标签)或根本不使用装饰器比呈现表单元素本身),然后手动编写所有周围的HTML。 在表单级别和视图级别完成自定义function,而不会失去Zend_Form的好处。

Matthew Weier O'Phinney开始了一系列有关Zend_Form装饰器的博客文章:

  1. 最简单的Zend_Form装饰器
  2. 从内到外:如何对装饰器进行层次化
  3. 单独渲染Zend_Form装饰器
  4. 创build复合元素

目前我们已经有了比旧的组件更加复杂的新的Zend\Form ,而且更加可控,封装和强大。 所以,我下面所说的不适用。 新的组件是恕我直言,一个巨大的改善,因为它…

  • …让你完全控制你想要呈现你的表单的方式,你需要写更多的视图代码,但这是值得的
  • …最大限度地将数据,逻辑和视图分开
  • …使用HTML5表单元素
  • …给你很多select你想如何把你的forms,如水合,注释等

关于Zend_Form的旧答案

我可能无法帮助,因为我有完全相同的问题。 我认为Zend_Form装饰器是强大的,但迄今为止,迄今为止我所见过的程序员友好和不直观的ZF片段,而且我在各个项目中使用了ZF的主要部分。

这就是说,我只能从我的经验中得到一些提示:

  • filter很容易使用,而不使用窗体
  • 大部分(如果不是全部)你想要实现的东西都是在装饰器的帮助下完成的
  • 我从小表单开始,一点一点地添加东西,但是我在某些表单中没有得到一些东西,因为结果是基于试错法(主要是装饰器)
  • 我从Zend邮件列表中获得了我在networking上无法find的信息

从相关的问题到右边,显然Zend_Form缺乏全面的文档,尤其是在非直观的情况下。 我真的很想看到ZF的工作人员就像我喜欢Zend Framework一样。

所以这个答案可能只是让你知道你不是唯一有这个问题的人。


或者你也可以使用绝地的技巧

补充说的是:

不要害怕装饰者,如果你决定坚持使用Zend_Form,你将会使用它们。 一旦你“明白了”就很简单,不幸的是,文档很薄弱,玩这个游戏几乎是唯一的途径。

ViewScript和ViewHelper装饰器给你很多的力量。

不要害怕挖掘存在的不同装饰器的源代码,看看它们是如何做的(我比较了原始的装饰器和dojo的装饰器)。

我认为肖恩所暗示的是,你不需要调用form-> render,你可以在你的viewscript中使用这样的东西。

  <someHtmlThingy name="blah" value="<?php echo $this->formInstance->getElement('whatever')->getValue(); ?>" /> 

我曾经在一个项目(Zend_Form之前)中构build了一组validation器,并使用了标准的观察logging。 这是一个更多的工作(pipe道的错误消息等),但不是过度的Zend_Form创build元素相比。

如果你只是想在你的表单元素之前或之后添加任意标记而不使用ViewScript装饰器,你可以使用我的AnyMarkup装饰器: http ://www.zfsnippets.com/snippets/view/id/62

例如,下面是如何在包装标签中添加一个图像的input字段(需要包括用于自动加载的path才能正确设置):

 $ form-> addElement('text','my_field',array(
   'label'=>'input信息:',
   'decorators'=>数组(
     “视图助手”,
    数组('AnyMarkup',数组
       'markup'=>'<span class =“imgwrapper”>'。
         '<img src =“info.png”alt =“信息图标”/> </ span>'),
       'placement'=>'prepend'
     )
     'HtmlTag',
     '标签'
   )
 );

跳过表单装饰器(IE浏览器 – 打印表单的各个元素,而不是仅仅依靠表单的标准视图助手来处理所有事情)是一种重新获得控制权的方法。

另一个select是简单地手动编写你的表单,只使用ZF来处理validation和过滤。

不幸的是,更复杂的问题被忽略,因为没有真正的具体目的或目标,真的很难写一个例子或如何做。 我花了一些时间帮助另一位开发者,他们想要修改隐藏元素的显示方式 ,但是他的案例非常具体,所以更容易深入到具体的细节。

大多数更复杂的任务真的归结为扩展特定字段types的默认助手。 例如,我有一个项目,我希望在提交表单之后将所有types的“错误”应用于所有未通过validation的字段,而不是写出validation错误文本:

 <label for="field">Label:</label> <input type="text" name="field" id="field" class="error"> 

这是一个相当复杂的过程,因为默认情况下,实际的表单元素不可用于视图助手,所以助手不能检查元素是否有validation错误。 所以我去了下面的过程:

  1. 我不得不为每个字段types创build一个客户视图助手,我想应用“错误”类。 在这里,我formXXX()formXXX()方法,并添加一个检查来查看元素是否有错误。 此外,我添加了一个setElement()方法,装饰器可以调用该方法来设置元素的一个实例,以便我的帮手可以检查错误。
  2. 接下来,我不得不重写默认的Zend_Form_Decorator_ViewHelper 。 在这个例子中,我访问了视图并实例化了表单元素types的帮助器,并检查了我在视图助手中创build的setElement()方法的存在性,如果它存在,就设置它。 通过这样做,我可以扩展一些表单元素types而不是其他的而不破坏整个脚本。
  3. 在我的每个表单的init()函数中,我必须添加一个新的元素前缀path( addElementPrefixPath('My_Form_Decorator'), 'path/to/decorator') )指向我的新表单装饰器。
  4. 最后,我必须添加助手path到我的应用程序,以便Zend框架可以find我已经在第一个项目符号创build的助手: addHelperPath('/path/to/helpers', 'My_View_Helper');

你可以看到为什么编写复杂的教程真的需要现实世界的问题。 关于build立这些助手或复杂的装饰scheme的重要部分是,所有这一切都让人烦恼,它可以让你很容易地创build很多forms,坚持相同的devisescheme,并修改他们的输出统一非常迅速,如果改变需要制作。 但是另一方面,如果你觉得自己花了大量的时间去思考如何做一件简单的工作,那么为了一种forms的好处,我可以跳过它!

如果您希望获得更具体的帮助,我将非常乐意提供帮助。 只是提出另一个问题(或更新这一个),我会尽我所能帮助。

whycantitbemorethan25c上面提到了它们,但是ViewScripts为渲染表单提供了非常细致的控制。 Zend_Form是快速的,所以它假定像标准装饰器一样的许多默认值,并将它们添加到表单对象中的方式sorting。 使用ViewScript,您可以跳过这一部分,然后将所有元素放在正常的HTML中。

不要完全忽略装饰者的概念。 即使稍后在ViewScript中使用它们,也可以对各个元素进行样式设置。 例如,您可以像其他人所build议的那样将它们用于错误消息。

如果你有非常复杂的forms,有多个数据点类似的行动(想想有一个用户列表的活动/不活跃button和每个删除button),你应该考虑Zend_Form_SubForm 。 子窗体可以像使用正常forms一样使用ViewScript,如果您使用ViewScript将窗体级联到带有子窗体的ViewScript,那么您将得到包含很好的逻辑和演示,而不仅仅是一个简单的窗体。

我写了一些子类到Zend_Form和装饰器,使它在<table>中布局表单。 它甚至有一些特殊的技巧来做一些事情,比如让多个提交button显示在同一行上。

花了整整一天的时间来搞定它的工作。 它是针对Zend 1.5.1编写的,所以不知道它是否可以与当前版本一起工作,但是如果您有兴趣,我可以在某处上传源代码。

这似乎是Zend Forms非常常见的投诉。

(我知道我会被CSS纯粹主义者用表格来布局表格,虽然我同意CSS对大多数情况来说都更好,但是我还没有看到使用CSS的好表单布局就像一个丑陋的混血儿,用表格的forms在我需要的每一个浏览器上都“工作”。

编辑:好的,说到丑陋的克鲁日,我已经把我的代码生成github中的表格zend表单。 去这里看看吧。 (因为gaoshan88问了。)

回答这里。 希望它会帮助你。 我经历了大量的信息,直到find它。

 <table> <tr> <td>Page name: *</td> <td><?php echo $this->pageForm->header_title;?></td> </tr> <tr> <td>H1 tag: *</td> <td><?php echo $this->pageForm->h1_tag;?></td> </tr> <tr> <td>Page URL: *</td> <td><?php echo $this->pageForm->url;?></td> </tr> <tr> <td>Meta Description: </td> <td><?php echo $this->pageForm->meta_description;?></td> </tr> <tr> <td>Meta Keywords: </td> <td><?php echo $this->pageForm->meta_keywords;?></td> </tr> <tr> <td>Short Description: *</td> <td><?php echo $this->pageForm->short_description;?></td> </tr> <tr> <td colspan="2"><a href="<?php echo $this->websiteUrl;?>backend_template/list?placeValuesBeforeTB_=savedValues&TB_iframe=true&height=200&width=300&modal=true" title="add a caption to title attribute / or leave blank" class="thickbox">Open iFrame Modal</a></td> <td> <a href="<?php echo $this->websiteUrl;?>backend_template/list?placeValuesBeforeTB_=savedValues&TB_iframe=true&height=200&width=300&modal=true" onclick="javascript:getDataFromAddPage()" title="Select Template For Page" class="thickbox" > TEST FORM </a> </td> </tr> <tr> <td>Featured: </td> <td><?php echo $this->pageForm->featured;?></td> </tr> <tr> <td>Mark as 404: </td> <td><?php echo $this->pageForm->is_404page;?></td> </tr> <tr> <td>Show in Navigation Menu: </td> <td><?php echo $this->pageForm->in_navmain;?></td> </tr> <tr> <td>Show in Static Menu:</td> <td><?php echo $this->pageForm->in_navstatic;?></td> </tr> <tr> <td><?php echo $this->pageForm->submit;?></td> <td><?php echo $this->pageForm->button_close;?></td> </tr> </table> 

您现在可能已经解决了这个问题,但我一直在做一些工作,需要一个类似的解决scheme。

形状配合> getSubform( '子窗体'); 
 foreach($ subform as $ key => $ value){
 / /一些标记和自定义代码在这里
    打印$值;
 / /一些标记和自定义代码在这里

 }
 ?>

在foreach循环中,可以添加表格标记。 如果您已经适当地为表格行命名了键,则它们应与表单键相匹配。 你甚至可以使用一个通过键来抓取适当的子表单的循环,或者甚至可以使用一个按键的元素。 你可以跳过foreach循环,如果你知道键,只要说print $ subform ['somekey']; 假设你设置主窗体说$ form-> setIsArray(true); (不确定是否最后一部分是绝对必要的,但对于复杂的forms,应该像这样设置。

我删除了默认的装饰器,所以我可以完全控制每个元素内的打印。 Zend_Form应该有一个内置的方法来抓取个别元素更容易一点..但我认为这工作得很好。

希望对某人有帮助!

肖恩McSomething的第一个build议是我的方式去。 我一直认为做<?php echo $this->form ?>来渲染表单太神奇了。 我会更进一步,并通过$element->renderDecorator()魔术方法渲染个别装饰器而不是个别元素。 这样,您将不必担心您定义装饰器的顺序。 你只需要他们在那里,你将不必添加这些讨厌的,不直观的HtmlTag装饰器。 我做了一个关于这个的博客文章 。

我不确定Zend是否已经有了这个function,但是一个快速的解决scheme是扩展这个类,让它接受一个html模板。

例如:

 <?php $form = new zend_form_whatever($field_list + $validators + $template); echo $form; ?> 

模板:

 <form id="my_custom_form"> <label>{label.email}</label> {input.email} <span class="red">{error.email}</span> <div> {label.password} {error.password} {input.password} </div> <div class="purple">{input.submit}<div> </form>