будет передан на завод (например,
дал структуру, используя Абстрактные классы для Forms, Fieldsets и InputFilters. Формы и Наборы полей имеют Фабрики, в то время как InputFilters создаются и устанавливаются на Наборы полей FieldsetFactory (используетMutableCreationOptionsInterface
передать варианты)
У меня проблема в том, что InputFiltersявляются загружены для формы, но не используются для проверки данных. Все входные данные принимаются как действительные.
Например. у меня естьCountry
Сущность сname
имущество. Название страны должно содержать не менее 3 символов и не более 255. Если имя «ab», оно считается действительным.
Прежде чем кто-то спросит: нет ошибки, данные просто принимаются как действительные.
Я ломал голову над этим в течение последних нескольких дней, пытаясь найти, где я совершил ошибку, но не могу ее найти.
Кроме того, есть довольно много кода. Я ограничил это тем, что считаю уместным, хотя: если вам нужно больше, будет больше. Я удалил много проверок типов, docblocks и подсказок типа, чтобы ограничить строки кода / время чтения;)
module.config.php
'form_elements' => [
'factories' => [
CountryForm::class => CountryFormFactory::class,
CountryFieldset::class => CountryFieldsetFactory::class,
],
],
Country.php
class Country extends AbstractEntity // Creates $id + getter/setter
{
/**
* @var string
* @ORM\Column(name="name", type="string", length=255, nullable=false)
*/
protected $name;
// Other properties
// Getters/setters
}
CountryController.php - Расширяет AbstractActionController
public function editAction() // Here to show the params used to call function
{
return parent::editAction(
Country::class,
CountryForm::class,
[
'name' => 'country',
'options' => []
],
'id',
'admin/countries/view',
'admin/countries',
['id']
);
}
AbstractActionController.php - (здесь идет не так) - ИспользуетсяCountryController # editAction ()
public function editAction (
$emEntity,
$formName,
$formOptions,
$idProperty,
$route,
$errorRoute, array
$routeParams = []
) {
//Check if form is set
$id = $this->params()->fromRoute($idProperty, null);
/** @var AbstractEntity $entity */
$entity = $this->getEntityManager()->getRepository($emEntity)->find($id);
/** @var AbstractForm $form */
$form = $this->getFormElementManager()->get($formName, (is_null($formOptions) ? [] : $formOptions));
$form->bind($entity);
/** @var Request $request */
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) { // HERE IS WHERE IT GOES WRONG -> ALL IS TRUE
try {
$this->getEntityManager()->flush();
} catch (\Exception $e) {
//Print errors & return (removed, unnecessary)
}
return $this->redirectToRoute($route, $this->getRouteParams($entity, $routeParams));
}
}
return [
'form' => $form,
'validationMessages' => $form->getMessages() ?: '',
];
}
CountryForm.php
class CountryForm extends AbstractForm
{
// This one added for SO, does nothing but call parent#__construct, which would happen anyway
public function __construct($name = null, array $options)
{
parent::__construct($name, $options);
}
public function init()
{
//Call parent initializer.
parent::init();
$this->add([
'name' => 'country',
'type' => CountryFieldset::class,
'options' => [
'use_as_base_fieldset' => true,
],
]);
}
}
CountryFormFactory.php
class CountryFormFactory extends AbstractFormFactory
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$serviceManager = $serviceLocator->getServiceLocator();
/** @var EntityManager $entityManager */
$entityManager = $serviceManager->get('Doctrine\ORM\EntityManager');
$form = new CountryForm($this->name, $this->options);
$form->setObjectManager($entityManager);
$form->setTranslator($serviceManager->get('translator'));
return $form;
}
}
AbstractFormFactory.php - используетMutableCreationOptionsInterface
получить параметры от вызова функции Controller:$form = $this->getFormElementManager()->get($formName, (is_null($formOptions) ? [] : $formOptions))
abstract class AbstractFormFactory implements FactoryInterface, MutableCreationOptionsInterface
{
protected $name;
protected $options;
/**
* @param array $options
*/
public function setCreationOptions(array $options)
{
// Check presence of required "name" (string) parameter in $options
$this->name = $options['name'];
// Check presence of required "options" (array) parameter in $options
$this->options = $options['options'];
}
}
CountryFieldset.php - Используется вышеCountryForm.php в качестве базового набора полей
class CountryFieldset extends AbstractFieldset
{
public function init()
{
parent::init();
$this->add([
'name' => 'name',
'required' => true,
'type' => Text::class,
'options' => [
'label' => _('Name'),
],
]);
// Other properties
}
}
AbstractFieldset.php
abstract class AbstractFieldset extends Fieldset
{
use InputFilterAwareTrait;
use TranslatorAwareTrait;
protected $entityManager;
public function __construct(EntityManager $entityManager, $name)
{
parent::__construct($name);
$this->setEntityManager($entityManager);
}
public function init()
{
$this->add([
'name' => 'id',
'type' => Hidden::class,
]);
}
// Getters/setters for $entityManager
}
CountryFieldsetFactory.php - ЗДЕСЬ ВХОДНОЙ ФИЛЬТР НАСТРОЕН НА ПОЛЕ
class CountryFieldsetFactory extends AbstractFieldsetFactory
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
parent::createService($serviceLocator);
/** @var CountryRepository $entityRepository */
$entityRepository = $this->getEntityManager()->getRepository(Country::class);
$fieldset = new CountryFieldset($this->getEntityManager(), $this->name);
$fieldset->setHydrator(new DoctrineObject($this->getServiceManager()->get('doctrine.entitymanager.orm_default'), false));
$fieldset->setObject(new Country());
$fieldset->setTranslator($this->getTranslator());
// HERE THE INPUTFILTER IS SET ONTO THE FIELDSET THAT WAS JUST CREATED
$fieldset->setInputFilter(
$this->getServiceManager()->get('InputFilterManager')->get(
CountryInputFilter::class,
[ // These are the options read by the MutableCreationOptionsInterface
'object_manager' => $this->getEntityManager(),
'object_repository' => $entityRepository,
'translator' => $this->getTranslator(),
]
)
);
return $fieldset;
}
}
AbstractFieldsetFactory.php
abstract class AbstractFieldsetFactory implements FactoryInterface, MutableCreationOptionsInterface
{
protected $serviceManager;
protected $entityManager;
protected $translator;
protected $name;
public function setCreationOptions(array $options)
{
$this->name = $options['name'];
}
public function createService(ServiceLocatorInterface $serviceLocator)
{
/** @var ServiceLocator $serviceManager */
$this->serviceManager = $serviceLocator->getServiceLocator();
/** @var EntityManager $entityManager */
$this->entityManager = $this->getServiceManager()->get('Doctrine\ORM\EntityManager');
/** @var Translator $translator */
$this->translator = $this->getServiceManager()->get('translator');
}
// Getters/setters for properties
}
CountryFieldsetInputFilter.php
class CountryInputFilter extends AbstractInputFilter
{
public function init()
{
parent::init();
$this->add([
'name' => 'name',
'required' => true,
'filters' => [
['name' => StringTrim::class],
['name' => StripTags::class],
],
'validators' => [
[
'name' => StringLength::class,
'options' => [
'min' => 3, // This is just completely ignored
'max' => 255,
],
],
],
]);
// More adding
}
}
AbstractFieldsetInputFilter.php - Последний! :)
abstract class AbstractInputFilter extends InputFilter
{
use TranslatorAwareTrait;
protected $repository;
protected $objectManager;
public function __construct(array $options)
{
// Check if ObjectManager|EntityManager for InputFilter is set
$this->setObjectManager($options['object_manager']);
// Check if EntityRepository instance for InputFilter is set
$this->setRepository($options['object_repository']);
// Check for presence of translator so as to translate return messages
$this->setTranslator($options['translator']);
}
public function init()
{
$this->add([
'name' => 'id',
'required' => false,
'filters' => [
['name' => ToInt::class],
],
'validators' => [
['name' => IsInt::class],
],
]);
}
//Getters/setters for properties
}
Любая помощь будет очень цениться. Надеюсь, вы не слишком перегружены приведенным выше кодом. Но я занимался этой проблемой около 3-4 дней назад и не сталкивался с тем, что происходит не так.
Подводить итоги:
В приведенном вышеCountryForm
создано. Он используетCountryFieldset
который загружается предварительно (вCountryFieldsetFactory
) сCountryInputFilter
.
Когда дело доходит до проверки данных, все считается действительным. Например. - Название страны "ab" действительно, хотяStringLength
валидатор имеет'min' => 3,
определяется как опция.