У меня есть две проблемы, связанные с Zend \ Form \ Annotation \ AnnotationBuilder.
Во-первых, я хочу сказать AnnotationBuilder создать Zend \ Form \ Fieldset, а не Zend \ Form \ Form (поскольку в документах говорится, что рекомендуется использовать наборы полей для ваших сущностей). Итак, мой класс сущности говорит @Annotation\Type("Fieldset")
и Fieldset создается, когда я вызываю createForm()
на AnnotationBuilder — пока все хорошо. Но я не смог заставить валидаторы работать с элементами fieldset. В качестве эксперимента у меня есть действие контроллера, выполняющее это:
$em = $this->serviceManager->get('entity-manager');
$builder = new \Zend\Form\Annotation\AnnotationBuilder($em);
$form = new \Zend\Form\Form('person-form');
$hydrator = new \DoctrineModule\Stdlib\Hydrator\DoctrineObject($em);
$form->setHydrator($hydrator);
$fieldset = $builder->createForm(\Application\Entity\Person::class);
$fieldset->setHydrator($hydrator)
->setObject(new \Application\Entity\Person())
->setUseAsBaseFieldset(true);
// more about this later....
$element = new \DoctrineModule\Form\Element\ObjectSelect('hat',
[
'object_manager' => $em,
'target_class' => 'Application\Entity\Hat',
'property' => 'name',
'label' => 'hat',
'display_empty_item' => true,
]);
$fieldset->add($element);
$form->add($fieldset);
$filter = $form->getInputFilter();
$filter->add([
'person' => [
'name' => 'hat',
'validators' =>[
[
'name' => 'Zend\Validator\NotEmpty',
'options' => [
'messages' => [
'isEmpty' => 'the "hat" is required'
],
],
],
],
],
]);
// so anyway...
$viewModel = new ViewModel(['form' => $form]);
$request = $this->getRequest();
if ($request->isPost()) {
$data = $request->getPost();
$person = new \Application\Entity\Person();
$form->bind($person);
$form->setData($data);
if (! $form->isValid()) {
echo "not valid ...messages? ";
\Zend\Debug\Debug::dump($fieldset->getMessages());
return $viewModel;
}
$em->persist($person);
$em->flush();
$this->flashMessenger()->addMessage("congratulations! you inserted an entity.");
return $this->redirect()->toRoute('home');
}
return $viewModel;
}
и что происходит, когда я отправляю форму ìsValid()
возвращает false, я получаю общее «значение является обязательным и не может быть пустым» для элемента «hat», который я добавил после факта, и ни один из валидаторов не работает с другими полями (в противном случае массив сообщений об ошибках пуст ). Итак, я хотел бы знать, как создать Fieldset вместо формы с помощью аннотаций и AnnotationBuilder. Обратите внимание, что когда я делаю все это с помощью формы, созданной аннотацией, а не с помощью Fieldset, все работает нормально.
Во-вторых, я хотел бы иметь возможность смешивать и сопоставлять элементы (а также фильтры и валидаторы), созданные с помощью аннотаций, с другими, добавляемыми на лету. Зачем? Что ж, идея иметь валидатор максимальной длины для строки, находящейся рядом с аннотацией Doctrine, которая определяет ширину столбца, имеет для меня смысл, плюс все другие преимущества этих аннотаций — я знаю, что не все без ума от них. Таким образом, элемент «Hat» в приведенном ниже примере является таким элементом, то есть элементом, который я хочу добавить после того, как форма была создана и инициализирована иным образом. И опять же, это работает с формой, а не с Fieldset. (На самом деле, я был бы рад добавить элемент с помощью аннотации, но это не представляется возможным сделать с экзотическими элементами формы, конструкторы которых имеют зависимости — вопрос на другой день.)
Для записи вот класс Entity в соответствующей части
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use Zend\Form\Annotation;
* @Annotation\Name("person")
* @Annotation\Type("Fieldset")
* //Annotation\Type("Form")
* @ORM\Entity @ORM\Table(name="people",uniqueConstraints={@ORM\UniqueConstraint(name="hat_email_idx",columns={"email","hat_id"})})
* @ORM\InheritanceType("JOINED")
*
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"person" = "Person", "interpreter"="Interpreter", "judge"="Judge"})
*/class Person
{
/**
* entity id
* @Annotation\Exclude()
* @ORM\Id @ORM\GeneratedValue @ORM\Column(type="smallint",options={"unsigned":true})
*/
protected $id;
/**
* the Person's email address.
*
* @ORM\Column(type="string",length=50,nullable=true)
*
* @var string
*/
protected $email;
/**
* the Person's last name.
*
* @Annotation\Options({"label":"last name"})
* @Annotation\Filter({"name":"StringTrim"})
* @Annotation\Validator({"name":"NotEmpty",
* "break_chain_on_failure": true,
* "options":{"messages":{"isEmpty":"last name is required"}
* }})
* @Annotation\Validator({
* "break_chain_on_failure": true,
* "name":"Application\Form\Validator\ProperName",
* "options" : {"type":"last"}
* })
* @Annotation\Validator({"name":"StringLength", "options":{"min":2, "max":50,
* "messages":{"stringLengthTooShort":"name must be at least 2 characters long",
* "stringLengthTooLong":"name exceeds maximum length of 50 characters"}}})
*
* @ORM\Column(type="string",length=50,nullable=false)
* @var string
*/
protected $lastname;
/**
* Everyone must where a hat in this life.
*
* @ORM\ManyToOne(targetEntity="Hat",fetch="EAGER")
* @ORM\JoinColumn(nullable=false)
*
* @var Hat
*/
protected $hat;
// etc etc omitted
}
Спасибо заранее.
Задача ещё не решена.
Других решений пока нет …