ZF2 - 创建自定义表单视图助手

时间:2013-01-17 14:15:28

标签: php zend-framework2

不久前,Matthew Weier O'Phinney在他的博客上发表了关于在Zend Framework 1中创建复合表单元素的文章。{/ p>

我正在尝试在Zend Framewor 2中为我的自定义库创建相同的元素,但在渲染表单时我遇到了查找表单视图助手的问题。

这是我的元素(DateSegmented.php):

<?php

namespace Si\Form\Element;

use Zend\Form\Element;
use Zend\ModuleManager\Feature\ViewHelperProviderInterface;

class DateSegmented extends Element implements ViewHelperProviderInterface
{

    public function getViewHelperConfig(){
          return array( 'type' => '\Si\Form\View\Helper\DateSegment' );
     }

    protected $_dateFormat = '%year%-%month%-%day%';
    protected $_day;
    protected $_month;
    protected $_year;

    /**
     * Seed attributes
     *
     * @var array
     */
    protected $attributes = array(
        'type' => 'datesegmented',
    );

    public function setDay($value)
    {
        $this->_day = (int) $value;
        return $this;
    }

    public function getDay()
    {
        return $this->_day;
    }

    public function setMonth($value)
    {
        $this->_month = (int) $value;
        return $this;
    }

    public function getMonth()
    {
        return $this->_month;
    }

    public function setYear($value)
    {
        $this->_year = (int) $value;
        return $this;
    }

    public function getYear()
    {
        return $this->_year;
    }

    public function setValue($value)
    {
        if (is_int($value)) {
            $this->setDay(date('d', $value))
                 ->setMonth(date('m', $value))
                 ->setYear(date('Y', $value));
        } elseif (is_string($value)) {
            $date = strtotime($value);
            $this->setDay(date('d', $date))
                 ->setMonth(date('m', $date))
                 ->setYear(date('Y', $date));
        } elseif (is_array($value)
            && (isset($value['day']) 
                && isset($value['month']) 
                && isset($value['year'])
            )
        ) {
            $this->setDay($value['day'])
                 ->setMonth($value['month'])
                 ->setYear($value['year']);
        } else {
            throw new Exception('Invalid date value provided');
        }

        return $this;
    }

    public function getValue()
    {
        return str_replace(
            array('%year%', '%month%', '%day%'),
            array($this->getYear(), $this->getMonth(), $this->getDay()),
            $this->_dateFormat
        );
    }
}

这是我的表单视图助手:

<?php

    namespace Si\Form\View\Helper;

    use Zend\Form\ElementInterface;
    use Si\Form\Element\DateSegmented as DateSegmented;
    use Zend\Form\Exception;

    class DateSegmented extends FormInput
    {
        /**
         * Render a form <input> element from the provided $element
         *
         * @param  ElementInterface $element
         * @throws Exception\InvalidArgumentException
         * @throws Exception\DomainException
         * @return string
         */
        public function render(ElementInterface $element)
        {
            $content = "";

            if (!$element instanceof DateSegmented) {
                throw new Exception\InvalidArgumentException(sprintf(
                    '%s requires that the element is of type Si\Form\Input\DateSegmented',
                    __METHOD__
                ));
            }

            $name = $element->getName();
            if (empty($name) && $name !== 0) {
                throw new Exception\DomainException(sprintf(
                    '%s requires that the element has an assigned name; none discovered',
                    __METHOD__
                ));
            }

            $view = $element->getView();
            if (!$view instanceof \Zend\View\View) {
                // using view helpers, so do nothing if no view present
                return $content;
            }

            $day   = $element->getDay();
            $month = $element->getMonth();
            $year  = $element->getYear();
            $name  = $element->getFullyQualifiedName();

            $params = array(
                'size'      => 2,
                'maxlength' => 2,
            );
            $yearParams = array(
                'size'      => 4,
                'maxlength' => 4,
            );

            $markup = $view->formText($name . '[day]', $day, $params)
                    . ' / ' . $view->formText($name . '[month]', $month, $params)
                    . ' / ' . $view->formText($name . '[year]', $year, $yearParams);

            switch ($this->getPlacement()) {
                case self::PREPEND:
                    return $markup . $this->getSeparator() . $content;
                case self::APPEND:
                default:
                    return $content . $this->getSeparator() . $markup;
            }

            $attributes            = $element->getAttributes();
            $attributes['name']    = $name;
            $attributes['type']    = $this->getInputType();
            $attributes['value']   = $element->getCheckedValue();
            $closingBracket        = $this->getInlineClosingBracket();

            if ($element->isChecked()) {
                $attributes['checked'] = 'checked';
            }

            $rendered = sprintf(
                '<input %s%s',
                $this->createAttributesString($attributes),
                $closingBracket
            );

            if ($element->useHiddenElement()) {
                $hiddenAttributes = array(
                    'name'  => $attributes['name'],
                    'value' => $element->getUncheckedValue(),
                );

                $rendered = sprintf(
                    '<input type="hidden" %s%s',
                    $this->createAttributesString($hiddenAttributes),
                    $closingBracket
                ) . $rendered;
            }

            return $rendered;
        }

        /**
         * Return input type
         *
         * @return string
         */
        protected function getInputType()
        {
            return 'datesegmented';
        }

    }

this描述了将视图助手添加为可调用的,但它已经被声明,因为我的自定义库(Si)已添加到'StandardAutoLoader'。

2 个答案:

答案 0 :(得分:1)

好的,最终想出了这个。

将Zend / Form / View / HelperConfig.php复制到自定义库中的相同位置。调整内容以反映您的视图助手。

将以下内容添加到Module.php

中的事件或引导程序中
$app = $e->getApplication();
$serviceManager = $app->getServiceManager();
$phpRenderer = $serviceManager->get('ViewRenderer');

$plugins = $phpRenderer->getHelperPluginManager();
$config  = new \Si\Form\View\HelperConfig;
$config->configureServiceManager($plugins);

使用您的自定义命名空间更新'Si'命名空间。

“类已经存在”错误实际上是我视图帮助文件顶部的包含错误。我已将其更新为:

use Zend\Form\View\Helper\FormElement;

use Zend\Form\Element;
use Zend\Form\ElementInterface;
use Zend\Form\Exception;

由于重复的类名,我还将instanceof语句更新为绝对位置:

if (!$element instanceof \Si\Form\Element\DateSegmented) {

从ZF1到2的翻译还有其他错误,但它们与此问题无关。

答案 1 :(得分:0)

我理解您的代码的方式是:您正在创建新的Form\Element以及新的Form\View\Helper。在这种情况下,您需要以下信息:

StandardAutoloader只负责实际查找类。 invokables内的getViewHelperConfig()声明就在那里,因此框架知道调用Class时要加载的ViewHelper

在你的情况下,你这样做:

public function getViewHelperConfig() 
{
    return array(
        'invokables' => array(
            'dateSegmented' => 'Si\Form\View\Helper\DateSegmented'
        )
    );
}

Zend Framework 2为/Zend/Form/View/HelperConfig.php

内部的ViewHelpers做了此事