如何使用字段集,验证器,策略和“元素集合”在ZF2中创建表单

时间:2014-07-28 06:54:42

标签: php forms zend-framework zend-framework2

我花了一个星期的时间来了解如何使用fieldset和元素集合在Zend Framework 2中创建表单,以便使用正确的验证器和良好的字段策略。

我正在尝试在Open Source Project中创建一个EAV(实体,属性,值)结构,但我对验证器和策略有一些困难。

我正在我的软件中创建产品管理,其中表格的字段在attributes表中描述

ProductForm是:

namespace ProductAdmin\Form;
use Product\Entity\Product;

use Zend\Form\Annotation\InputFilter;

use Zend\InputFilter\Input;

use Zend\Form\Form;
use Zend\Stdlib\Hydrator\ClassMethods;
use Base\Hydrator\Strategy\DateTimeStrategy;
use Zend\Stdlib\Hydrator;

class ProductForm extends Form
{

    public function init ()
    {
        $hydrator = new ClassMethods();
        // $hydrator->addStrategy('createdat', new DateTimeStrategy()); This is just an old strategy test for the first form field level.

        $this->setAttribute('method', 'post');
        $this->setHydrator($hydrator)->setObject(new \Product\Entity\Product());

        $this->add(array('type' => 'hidden', 'name' => 'type_id'));
        $this->add(array('type' => 'hidden', 'name' => 'attribute_set_id'));

        $this->add(
                array('name' => 'submit', 
                        'attributes' => array('type' => 'submit', 
                                'class' => 'btn btn-success', 
                                'value' => _('Save'))));
        $this->add(
                array('name' => 'id', 
                        'attributes' => array('type' => 'hidden')));
    }

    /**
     * Prepare the attribute form
     *
     * @param $attributes array           
     * @return \ProductAdmin\Form\ProductForm
     */
    public function createAttributesElements (array $attributes)
    {
        $customHydrator = new Hydrator\ClassMethods();
        $parentFilter = new \Zend\InputFilter\InputFilter();
        $filterChain = new \Zend\Filter\FilterChain();
        $fieldset = new \Zend\Form\Fieldset('attributes');
        $fieldset->setFormFactory($this->getFormFactory()); // thanks to jurians #zftalk irc
        $fieldInput = null;

        $inputFilter = new \Zend\InputFilter\InputFilter();
        foreach ($attributes as $attribute) {
            $dateformat = "";
            $name = $attribute->getName();
            $label = $attribute->getLabel() ? $attribute->getLabel() : "-";
            $input = $attribute->getInput() ? $attribute->getInput() : "text";
            $type = $attribute->getType() ? $attribute->getType() : "string";
            $isRequired = $attribute->getIsRequired();
            $sourceModel = $attribute->getSourceModel();
            $filters = $attribute->getFilters();
            $cssStyles = $attribute->getCss();

            $filterChain->attachByName('null'); // set as default

            $typeSource = !empty($sourceModel) ? $sourceModel : $input;

            // Handle the dates
            if(!empty($type) && $type == "datetime"){
                $customHydrator->addStrategy($name, new DateTimeStrategy());
                $typeSource = 'Zend\Form\Element\DateTime';
                $dateformat = "d/m/Y";
            }

            $fieldset->add(
                      array('type' => $typeSource, 
                            'name' => $name, 
                            'attributes' => array(
                                        'id' => $name,
                                        'class' => 'form-control ' . $cssStyles,
                                    ), 
                            'options' => array('label' => _($label), 'format' => $dateformat)
                        )
            );

            $fieldInput = new \Zend\InputFilter\Input($name);
            $fieldInput->setRequired($isRequired);

            // handle the filters preferences of the attribute
            if(!empty($filters)){
                $filters = json_decode($filters, true);
                foreach ($filters as $filter){
                    $filterChain->attachByName($filter); 
                }
            }

            $fieldInput->setFilterChain($filterChain);
            $inputFilter->add($fieldInput);

        }

        $fieldset->setHydrator($customHydrator);
        $this->add($fieldset);
        $parentFilter->add($inputFilter, 'attributes'); // thanks to GeeH #zftalk irc
        $this->setInputFilter($parentFilter);

        return $this;
    }
}

这是策略类:     

class DateTimeStrategy extends DefaultStrategy
{

    /**
     * Convert the database date field in the specific date format 
     * 
     * @see Zend\Stdlib\Hydrator\Strategy.StrategyInterface::extract()
     */
    public function extract ($value)
    {
        $date = new \DateTime();

        // Check the date in this format Y-m-d H:i:s
        $validator = new \Zend\Validator\Date(array (
                'format' => 'Y-m-d H:i:s',
                'locale' => 'it'
        ));

        if ($validator->isValid($value)) {
            $thedate = $date->createFromFormat('Y-m-d H:i:s', $value);
            $value = $thedate->format('d/m/Y H:i:s');
        }

        // Check the date in this format Y-m-d
        $validator = new \Zend\Validator\Date(array (
                'format' => 'Y-m-d',
                'locale' => 'it'
        ));

        if ($validator->isValid($value)) {
            $thedate = $date->createFromFormat('Y-m-d', $value);
            $value = $thedate->format('d/m/Y');
        }

        $pos = strpos($value, "-00");

        if($pos !== false){
            $thedate = $date->createFromFormat('Y-m-00', $value);
            $value = $thedate->format('m/Y');
        }

        return $value;
    }

    /**
     * Convert the date format from the post data array to the database format value
     * 
     * @see Zend\Stdlib\Hydrator\Strategy.StrategyInterface::hydrate()
     */
    public function hydrate ($value)
    {
        if (is_string($value) && "" === $value) {
            $value = null;
        } elseif (is_string($value)) {
            $date = new \DateTime();
            $validator = new \Zend\Validator\Date(array ( 
                    'format' => 'd/m/Y', 
                    'locale' => 'it'
            ));
            if ($validator->isValid($value)) {
                $thedate = $date->createFromFormat('d/m/Y', $value);
                $value = $thedate->format('Y-m-d');
            }

            if(strlen($value) == 7){
                $thedate = $date->createFromFormat('m/Y', $value);
                if($thedate){
                    $value = $thedate->format('Y-m-00');
                }
            }
        }

        return $value;
    }
}

当我将Validator附加到Datetime字段,然后我发布表单中输入的数据时,结果如下:

object(Product\Entity\Product)[917]
  public 'id' => string '2' (length=1)
  public 'uid' => null
  public 'type_id' => string '1' (length=1)
  public 'attribute_set_id' => string '1' (length=1)
  public 'attributes' => 
    array (size=12)
      'description' => string 'test' (length=4)
      'metadescription' => null
      'metakeyword' => null
      'name' => string 'hosting' (length=7)
      'news_from_date' => string '29/06/2014' (length=10)
      'news_to_date' => null
      'price' => string '10.5' (length=4)
      'short_description' => string 'test' (length=4)
      'sku' => string 'hst-01' (length=6)
      'special_price' => null
      'status' => string '1' (length=1)
      'urlkey' => string 'hosting' (length=7)
  public 'createdat' => null
  public 'updatedat' => null

如您所见,日期已发布时格式不正确,可以插入到db表中。正确的日期格式必须是yyyy-mm-dd。

这是已编译的表单,其中呈现了所有属性。 enter image description here

我的错误在哪里?

0 个答案:

没有答案