フォーム、フィールドセット、および入力フィルターの抽象クラスを使用して構造体を設定しました。 InputFiltersが作成され、FieldsetFactoryによってフィールドセットに設定されている間、フォームとフィールドセットの工場を持っているZF2/Doctrine2 - フィールドセットが検証されず、データは常に有効です
は私が持っている問題はInputFilters フォームのためにロードされあるが、これらに使用されていないということです(オプションに沿って通過するMutableCreationOptionsInterface
を使用しています)データを検証します。すべての入力は有効として受け入れられます。
などです。name
プロパティを持つCountry
エンティティを持っています。国名は少なくとも3文字、最大255文字でなければなりません。名前が「ab」のときは有効です。
誰かがを尋ねる前に:エラーがスローされていない、データは単に有効なものとして受け入れられています。
私は過ぎ去った数日間、私が間違いを犯した場所を見つけようとしていたが、見つけられなかった。
また、かなりのコードがあります。私はそれが私が関係していると思うものに限定しましたが、もっと必要なものがあればもっと多くあります。
module.config.php
'form_elements' => [
'factories' => [
CountryForm::class => CountryFormFactory::class,
CountryFieldset::class => CountryFieldsetFactory::class,
],
],
)
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
}
Country.phpを、私は型チェック、にdocblockの多くを削除したとタイプは、コード行/読み出し時間を制限するヒント
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
- ベースのフィールドセット として CountryForm.phpにより上記で使用$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: - 10
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
を使用します
class CountryFieldset extends AbstractFieldset
{
public function init()
{
parent::init();
$this->add([
'name' => 'name',
'required' => true,
'type' => Text::class,
'options' => [
'label' => _('Name'),
],
]);
// Other properties
}
}
AbstractFieldset。INPUTFILTERがFIELDSET
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;
}
}
ONTO設定されているHERE IN 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
}
C - 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 ountryFieldsetInputFilter.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 - ラスト1! :)
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
上に作成されます。これは、CountryInputFilter
で事前にロードされるCountryFieldset
(CountryFieldsetFactory
)を使用します。
データの検証に関しては、すべてが有効であると認められます。例えば。 - 国名「ab」は有効ですが、StringLength
バリデータは'min' => 3,
がオプションとして定義されています。
あなたが提供した設定でそれを変更することも問題ではないと仮定しています: ''input_filters' => ['factories' => [[ – Nukeface
@Nukefaceはい他の設定| serviceManagerインスタンスと同じように動作します。 – Kwido
私は、モジュール構成ではなく独自のクラスを持っています。 Factoryクラスを使って自分のアプリケーションを正しく修正したと思いますが、Formに登録されているInputFilterを見ていますが、名前はありません。例えば、 '$ form'オブジェクト(CountryForm)では、 : 'fil '(ここではキーはありません)' =>(CountryFieldsetInputFilter)=> [フィルタはここ]、]、]、 '。 'CountryFormFactory'はあなたの例とまったく同じです(Fieldset名を追加する可能性をチェックしましたが、' setInputFilter() 'ではできません)。 FieldsetFactoryも独自のクラスでは同じですが、 – Nukeface