3

前段时间,Matthew Weier O'Phinney 在他的博客上发表了这篇关于在 Zend Framework 1 中创建复合表单元素的文章。

我正在尝试在 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';
        }

    }

这个问题描述了将视图助手添加为可调用,但它已经被声明,因为我的自定义库(Si)已添加到“StandardAutoLoader”中。

4

2 回答 2

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 的翻译中还有更多错误,但与此问题无关。

于 2013-01-17T16:14:09.953 回答
0

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

StandardAutoloader唯一负责实际查找课程的工作。invokables里面的声明就在getViewHelperConfig()那里,所以框架知道当被调用Class时要加载什么。ViewHelper

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

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

ViewHelpersZend Framework 2在/Zend/Form/View/HelperConfig.php中为它自己做这件事

于 2013-01-17T14:52:26.933 回答