我花了一个星期的时间来了解如何使用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。
这是已编译的表单,其中呈现了所有属性。
我的错误在哪里?