4

今のところ、検証グループの使用に成功しましたが、検証グループとネストされたマップされたエンティティに行き詰まっています。

簡単な例で問題を説明します。

マイ エンティティ: アドレス、ダメージ、アプライアンス

/**
 * @ORM\Entity()
 */
class Address extends ...
{
    /**
     * @var string
     * @ORM\Column(type="string", name="postcode", nullable=true)
     * @Assert\NotBlank(
     *     groups={
     *     "damage_responsible_address",
     *     "appliance_repairer_address",
     *     })
     */
    private $postcode;

    ...


/**
 * @ORM\Entity()
 */
class Damage extends ...
{
    /**
     * @var boolean
     * @ORM\Column(type="boolean", name="responsible", nullable=true)
     * @Assert\NotBlank(groups={"damage"})
     */
    private $responsible;

    /**
     * @ORM\OneToOne(targetEntity="Address", cascade={"persist","remove"})
     * @ORM\JoinColumn(name="responsible_address_id", referencedColumnName="id")
     * @Assert\Valid()
     */
    private $responsibleAddress;

    /**
     * @ORM\ManyToMany(targetEntity="Appliance", orphanRemoval=true, cascade={"persist", "remove"})
     * @ORM\JoinTable(name="coronadirect_cuzo_home_damage_appliances",
     *      joinColumns={@ORM\JoinColumn(name="damage_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="appliance_id", referencedColumnName="id")}
     *      )
     */
    private $appliances;

    ...


/**
 * @ORM\Entity()
 */
class Appliance extends ...
{
    /**
     * @var boolean
     * @ORM\Column(type="boolean", name="to_repair", nullable=true)
     * @Assert\NotBlank(groups={"appliance"})
     */
    private $toRepair;

     /**
     * @ORM\OneToOne(targetEntity="Address", cascade={"persist","remove"})
     * @ORM\JoinColumn(name="repairer_address_id", referencedColumnName="id")
     * @Assert\Valid()
     */
    private $repairAddress;

    ...

フォームを定義するには、AddressType、DamageType、および ApplianceType を使用します。

class DamageType extends ...
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
         $builder->add('appliances', 'collection', array(
            'type' => 'home_damage_appliance_type',
            'allow_add' => true,
            'allow_delete' => true,
            'prototype' => true,
            'options' => array(
                'cascade_validation' => true,
            )
        ));

        $builder->add('responsible', 'choice', array(
            'choices' => $this->getYesNoChoiceArray(),
            'expanded' => true,
            'multiple' => false,
        ));

        $builder->add('responsibleAddress', 'address_type', array(
            'required' => true
        ));

        ...
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
                'data_class' => 'Damage',
                'cascade_validation' => true,
                'validation_groups' =>
                    function(FormInterface $form) {

                        $groups = array('damage');

                        if ($form->getData()->getResponsible() == true) {
                            $groups[] = 'damage_responsible_address';
                        }

                        return $groups;
                    }
        ));
    }

フォームで責任者が true に設定されている場合、damage_responsible_address グループを追加しています。そうでなければ、アドレスを検証したくありません。

class ApplianceType extends ...
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder->add('toRepair', 'choice', array(
            'choices' => $this->getYesNoChoiceArray(),
            'expanded' => true,
            'multiple' => false,
        ));

        $builder->add('repairAddress', 'address_type', array(
            'required' => true
        ));

        ...
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
                'data_class' => 'Appliannce',
                'cascade_validation' => true,
                'validation_groups' =>
                    function(FormInterface $form) {

                        $groups = array('appliance');

                        if ($form->getData()->getToRepair() == true) {
                            $groups[] = 'appliance_repairer_address';
                        }

                        return $groups;
                    }
        ));
    }

前と同じように、toRepair が true の場合、アドレスを検証します。

何が問題なのですか?

損害の責任が true で、アプライアンス toRepair が false の場合、フォームは責任のあるアドレスで検証エラーを返しますが、アプライアンスのアドレスでも検証エラーを返します。

逆の場合も同様です。アプライアンス アドレスが無効な場合 (toRepar が true)、responsibleAddress も無効です (responsible が false であっても)。

住所検証グループは、定義されているフォームを調べませんが、フォーム内のすべての住所項目に添付するだけです。

フォーム専用の検証グループを定義することはできますか?

Doctrine と Symfony 2.3.6 を使用しています。

4

3 に答える 3

1

問題は、symfony が検証グループにOR ロジックを使用していることです。したがって、グループの1つを適用して形成すると、どちらの場合も住所が検証されます。

グループを親エンティティに移動しても、問題は解決しませんか?

/**
 * @ORM\Entity()
 */
class Damage extends ...
{
    /**
     * @ORM\OneToOne(targetEntity="Address", cascade={"persist","remove"})
     * @ORM\JoinColumn(name="responsible_address_id", referencedColumnName="id")
     * @Assert\Valid(
     *     groups={
     *     "damage_responsible_address"
     *     })
     * )
     */
    private $responsibleAddress;
}
于 2014-01-24T06:45:00.160 に答える
1

斜体は一般的なケース、太字はこの質問の特定のケースです。

住所検証グループは、定義されているフォームを調べませんが、フォーム内のすべての住所項目に添付するだけです。

True、validation_groupDamageType のコールバックはvalidation_groupすべてのフォームに対して設定され、使用するとcascade_validation、フォームに含まれるすべての埋め込み AddressType に対して設定されます。担当アドレスだけに設定したいということを理解する必要はありません。

一般に、親フォームのコールバックを介して検証グループを設定し、カスケード検証を true に設定すると、すべての子フォームがこの検証グループに対して検証されます。子ごとに異なる検証グループを設定したい場合は、検証グループのコールバックを子フォームタイプに配置する必要があります。

各 Address Form に対して呼び出されるように、検証コールバックを AddressType に配置する必要があります。もちろん、そうするためには、各 Address エンティティがその所有者を認識している必要があります。

検証コールバックの代替はGroup Sequence Providerです。ただし、いずれの場合でも、Damage ではなく各 Address エンティティに検証グループを設定する必要があるため、アドレスはその所有者を認識している必要があります。

于 2014-01-28T22:16:12.070 に答える