我正在使用可重复使用的管理模块;负责处理身份验证和ACL。该模块附带一个基本控制器,实现的任何其他模块都可以继承。所以这个控制器是Cp\AdminController
并且不可访问,但是被所有其他控制器继承。
我有一个默认/家庭控制器Cp\HomeController
,它有几个动作;登录,注销和忘记/重置密码。目前我正在研究Cp\HomeController::indexAction
。在这种方法中,我只需执行以下操作:
// ... controller logic ...
public function indexAction()
{
if ($this->getAuth()->hasIdentity()) {
# XXX: This is the authorised view/dashboard.
} else {
# XXX: This is the unauthorised view; login page.
$loginForm = new Form\Login();
# XXX: validation, and login form handling here.
return array(
'form' => $loginForm
);
}
}
// ... controller logic ...
此处的问题是,Cp\HomeController
默认使用./module/Cp/view/cp/home/index.phtml
模板;看起来像是:
<h1>Authorisation Required</h1>
<section id="admin-login">
<?= $form ?>
</section>
我已使用自己的表单类Zend\Form
扩展./module/Cp/src/Cp/Form.php
,然后由任何表单类扩展。 _请记住,我会将这个类移到应用程序中,以便它完全解耦并完全可重用。
<?php
// @file: ./module/Cp/src/Cp/Form.php
namespace Cp;
use Zend\Form\Form as ZendForm;
use Zend\Form\Fieldset;
use Zend\InputFilter\Input;
use Zend\InputFilter\InputFilter;
use Zend\View\Model\ViewModel;
use Zend\View\Renderer\PhpRenderer;
use Zend\View\Resolver;
class Form extends ZendForm
{
/**
* Define the form template path.
* @var String
*/
protected $__templatePath;
/**
* Define the view variables.
* @var Array
*/
protected $__viewVariables = array();
/**
* Set the view variable.
* @param String $key The index for the variable.
* @param Mixed $value The value for the view variable.
* @return Cp\Form
*/
public function set($key, $value)
{
$this->__viewVariables[$key] = $value;
return $this;
}
/**
* Set the template path.
* @param String $path The path for the template file.
* @return Cp\Form
*/
public function setTemplatePath($path)
{
$this->__templatePath = $path;
return $this;
}
/**
* When the object is buffered in output, we're going to generate the view
* and render it.
* @return String
*/
public function __toString()
{
// Define our template file as form for resolver to map.
$map = new Resolver\TemplateMapResolver(array(
'form' => $this->__templatePath
));
// Define the render instance responsible for rendering the form.
$renderer = new PhpRenderer();
$renderer->setResolver(new Resolver\TemplateMapResolver($map));
// The form view model will generate the form; parsing the vars to it.
$view = new ViewModel();
$view->setVariable('form', $this);
$view->setTemplate('form');
foreach ($this->__viewVariables as $key => $value) {
if (! property_exists($view, $key)) {
$view->setVariable($key, $value);
}
}
return $renderer->render($view);
}
}
我继承了这个表单类,以便创建我的登录表单,一个标准的电子邮件地址和密码字段,可以在任何可能进行身份验证的地方重复使用。
<?php
namespace Cp\Form;
use Zend\Form\Element;
class Login extends \Cp\Form
{
public function __construct($name = 'Login', $action)
{
// Parse the form name to our parent constructor.
parent::__construct($name);
// Override default template, defining our form view.
$this->setTemplatePath(MODULE_DIR . 'Cp/view/cp/form/login.phtml');
// Create our form elements, and validation requirements.
$email = new Element\Email('email');
$email->setLabel('E-mail Address');
$password = new Element\Password('password');
$password->setLabel('Password');
$submit = new Element\Submit('login');
$this->setAttribute('action', $action)
->setAttribute('method', 'post')
->setAttribute('autocomplete', 'autocomplete')
->add($email)
->add($password)
->add($submit);
}
}
继承的__toString
方法将采用已定义的表单视图,并对其进行渲染。 这个是我的问题所在,我的问题就出现了。在视图中(见下文)我试图通过使用框架创建表单,而无需对HTML元素进行硬编码。由于可以扩展和修改Cp\Form\Login
类,使用不同的字段或其他字段,可选的或强制的,或者有条件的。
有没有办法快速,让Zend生成以下HTML?不使用部分视图或书写<input type="<?= ... ?>" name="<?= ... ?>" />
。这是因为可以在控制器内定义或覆盖属性,因此,此时属性是未知的;并且应该具有灵活性。
<section class="authentication-form">
<h2>Authentication Required</h2>
<!-- How-to: Generate the <form> tag and all it's attributes. -->
<?= $form->openTag() ?>
<? if ($ipAllowed): ?>
<p>Please choose an account to log in through.</p>
<fieldset>
<?= $form->get('email') ?>
</fieldset>
<? else: ?>
<p>Please log in using your e-mail address and password.</p>
<fieldset>
<?= $form->get('email') ?>
<?= $form->get('password') ?>
</fieldset>
<? endif ?>
<div class="action">
<!-- How-To: Generate the <input type="submit" name="" ... attributes ... />
<?= $form->get('login') ?>
</div>
<!-- How-To: Generate the form close tag.
<?= $form->closeTag() ?>
</section>
希望这比以前更清楚。
答案 0 :(得分:4)
我不确定你的实际问题是什么。你能明确指出吗?
Zend\Form
的设计使它不会自我呈现,而是由视图助手呈现:
<?php
echo $this->form()->openTag($this->form);
echo $this->formCollection($this->form);
echo $this->form()->closeTag($this->form);
你当然可以写一个为你做这个的视图助手。
或者,你可以编写一个视图助手,它接受一个元素列表来渲染和编写一个像这样的视图助手:
<?php
namespace MyModule\View\Helper;
use Zend\View\Helper\AbstractHelper;
class RenderForm extends AbstractHelper
{
public function __invoke($fieldsToRender, $form)
{
$html = $this->view->form()->openTag($form) . PHP_EOL;
foreach ($fieldsToRender as $fieldName) {
$element = $form->get($fieldName);
$html .= $this->view->formRow($element) . PHP_EOL;
}
$html .= $this->view->form()->closeTag($form) . PHP_EOL;
return $html;
}
}
然后,您在视图脚本中只需要调用renderForm()
。
答案 1 :(得分:0)
使用Rob的响应,我构建了自己的帮助器来将不同的字段呈现为文本(示例是Foundation 5行):
namespace MyApp\View\Helper;
use Zend\Form\View\Helper\FormRow;
use Zend\Form\ElementInterface;
class RenderForm extends AbstractHelper
{
public function __invoke( ElementInterface $element )
{
$html = '';
$value = '';
$attributes = $element->getAttributes();
$type = $attributes['type'];
$label = $element->getLabel();
if( $type == 'text' or $type == 'textarea' or $type == 'datetime' or $type == 'hidden'){
$value = $element->getValue();
}
if( $type == 'select' ){
$selectedValue = $element->getValue();
if( is_bool( $selectedValue ) ){
$selectedValue = (int) $selectedValue;
}
$options = $element->getValueOptions();
$values = '';
foreach( $options as $value => $option ){
if( (!empty($value) or $value == 0) and $value === $selectedValue ){
$values .= $option . '<br />';
}
}
$value = $values;
}
if( $type == 'multi_checkbox' ){
$selectedOptions = $element->getValue();
$options = $element->getValueOptions();
$values = '';
foreach( $options as $option ){
$optionValue = $option[ 'value' ];
if( in_array( $optionValue, $selectedOptions ) ){
$values .= $option[ 'label' ]. '<br />';
}
}
$value = $values;
}
if( $value == ''){
$value = 'N/A';
}
$html .= '<div class="row">
<div class="small-12 column">
<div class="row">
<div class="small-3 columns"><label class="right inline" for="tag_id">' . $label . '</label></div>
<div class="small-9 columns left" style="padding-top:10px">' . $value . '</div>
</div>
</div>
</div>';
return $html;
}
}