What is the most effective way to use DoctrineModule\Validator\NoObjectExists
validator in a Zend Form that is used for editing also? Because when I use the same Form for saving edited values, this validates the Object existence and flags form is invalid.
Asked
Active
Viewed 4,957 times
4

Wilt
- 41,477
- 12
- 152
- 203

Sreejith Chozhiyath
- 249
- 3
- 6
-
see my answer here http://stackoverflow.com/questions/20680700/zf2-inputfilter-doctrine-noobjectexists-editing-object-does-not-validate#answer-29318872 – blackbishop Mar 28 '15 at 16:05
3 Answers
6
Few weeks ago I resolved the same problem using a helper method in my custom filter. I am not sure if this is the correct approach but it works.
- Write a custom inputfilter extending
Zend\InputFilter\InputFilter
. - Add your generic filters and validators at
init()
method of filter. - Write a helper method in the input filter which appends doctrine's existence validator to current validator chain like below.
- Add existence validator to your filter instance when creating new object, use generic filter instance when editing.
So,
<?php
/**
* Baz filter
*/
class BazFilter extends Zend\InputFilter\InputFilter
{
/**
* This method will be triggered automatically when you retrive baz filter via inputfiltermanager.
*/
public function init()
{
// Define your input names, types, validators and filters as arrays
$this->add(array(
'name' => 'code',
'required' => true,
'validators' => array(),
'filters' => array()
));
$this->add( array(...) );
$this->add( array(...) );
// ...
}
/**
* Appends doctrine's noobjectexists validator to validator chain only when required.
*
* @access public
* @param \Doctrine\ORM\EntityRepository $repository
* @return \Zend\InputFilter\InputFilter
*/
public function appendExistenceValidator(\Doctrine\ORM\EntityRepository $repository)
{
$validatorSignature = array(
'name' => 'code',
'validators' => array(
array(
'name' => 'DoctrineModule\Validator\NoObjectExists',
'options' => array(
'object_repository' => $repository,
'fields' => 'code',
'messages' => array( NoObjectExists::ERROR_OBJECT_FOUND => "This object with code already exists in database." )
)
)
)
);
$validator = $this->getFactory()->createInput( $validatorSignature );
$this->add($validator);
return $this;
}
}
Finally, append this inputfilter to your form when editing:
// $form = your form instance
// $filter = Bazfilter instance
$form->setData($postData)->setInputFilter( $filter );
if( $form->isValid() === false ) {
// ...
}
When creating:
// $filter = bazfilter instance
$repository = $entityManager->getRepository('Your\Entity\Name');
$filter->appendExistenceValidator( $repository ); // <-- Notice this line
$form->setData($postData)->setInputFilter( $filter );
if( $form->isValid() === false ) {
// ...
}
-
2So, since you edit i.e. an user, you could give him i.e. an allready existing e-mail... – Dennis D. Feb 05 '14 at 12:56
1
You can't use NoObjectExists in an easy way, you should use UniqueObject instead:

Tadej
- 379
- 4
- 12
-
-
Wouldn't it invalidate the new form. Because there is no unique record for the field in the database? – CoCoMo Nov 26 '14 at 04:59
0
I tried using DoctrineModule\Validator\NoObjectExists in form and it prevents updates which keep the unique field(s) unchanged. As @Tadej mentioned - use UniqueObject. Here is an example form:
class ExampleForm extends Form implements InputFilterProviderInterface
{
/**
* @var EntityManager
*/
private $entityManager;
/**
* @var Repository
*/
private $repository;
/**
* ExampleForm constructor.
*
* @param EntityManager $entityManager
* @param Repository $repository
*/
public function __construct(EntityManager $entityManager, Repository $repository)
{
$this->entityManager = $entityManager;
$this->repository = $repository;
$this->add(
[
'type' => Text::class,
'name' => 'name',
'options' => [
'label' => _('Name *')
],
'attributes' => [
'class' => 'form-control',
],
]
);
}
/**
* @return array
*/
public function getInputFilterSpecification()
{
return [
'name' => [
'required' => true,
'filters' => [
],
'validators' => [
[
'name' => UniqueObject::class,
'options' => [
'object_manager' => $this->entityManager,
'object_repository' => $this->repository,
'fields' => ['name'],
'use_context' => true,
'messages' => [
UniqueObject::ERROR_OBJECT_NOT_UNIQUE => "Name '%value%' is already in use",
]
]
]
]
],
];
}
}
Note the use of 'use_context' option - it must be used if field is not primary key. 'messages' is optional.

Andon Totev
- 204
- 2
- 3