【问题标题】:Constraint validation is lost after entity inheritance实体继承后约束验证丢失
【发布时间】:2017-03-29 01:21:34
【问题描述】:

我正在使用一个实体,而这个实体继承自另一个实体。除了一件事,一切都很好。似乎基础实体字段上的服务器端验证“丢失”了。

继承类:

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * TicketBase
 * @ORM\MappedSuperclass
 */
class TicketBase
{
    /**
     * @var string
     *
     * @ORM\Column(name="title", type="string", length=255)
     * @Assert\NotBlank()
     */
    private $title;

    /* other fields */

然后:

use AppBundle\Repository\TicketRepository;
use Doctrine\ORM\Mapping as ORM;

/**
 * Ticket
 *
 * @ORM\Table(name="cheval_ticket")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\TicketRepository")
 */
class Ticket extends TicketBase
{
   /* only specific fields here */

之后,我可以在 Ticket 实体中使用我的任何 TicketBase 字段没有问题,但是当我在 Ticket 上创建表单时,我在 Ticket::title 上没有服务器端验证,因此如果出现完整性约束违规标题为空。

我是否遗漏了一些东西来让我的验证工作?

谢谢

编辑:

控制器动作:

/**
 * @Route("/tickets/{uniqid}/{contactId}", name="contact_tickets")
 */
public function ticketsAction(Request $request, $contactId = null, $uniqid = null)
{
    $em = $this->getDoctrine()->getManager();
    $contact = $em->getRepository("AppBundle:Contact")
            ->findOneBy(array(
        'id' => $contactId,
        'uniqid' => $uniqid
    ));

    if ($contact === null) {
        return $this->go('contact_index');
    }

    $form = $this
            ->createForm(ContactTicketsType::class, $contact, ['method' => 'POST'])
            ->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $this->setTicketsPrice($contact);
        $this->setTicketsNbJours($contact);
        $this->save($contact);
        $this->setTicketsCodeId($contact);
        return $this->go('payement_index', [
                    'contactId' => $contact->getId(),
                    'uniqid' => $contact->getUniqid(),
                        ]
        );
    }
}

我的联系实体与 Ticket 有这种关系:

/**
 * @ORM\OneToMany(targetEntity="Ticket", mappedBy="contact", cascade={"remove", "persist"})
 */
private $tickets;

还有我的 ContactTicketsType :

namespace AppBundle\Form\Type\Contact;

use AppBundle\Form\Type\Ticket\TicketType;
use AppBundle\Form\Type\Ticketadd\TicketaddType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
 * Description of ContactType
 */
class ContactTicketsType extends AbstractType
{

    /**
     * 
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('tickets', CollectionType::class, array(
                    'entry_type' => TicketType::class,
                    'allow_add' => true,
                    'allow_delete' => true,
                    'label' => false,
                    'by_reference' => false
                ))
                // ...
        ;

    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Contact'
        ));
    }

}

【问题讨论】:

    标签: inheritance constraints symfony


    【解决方案1】:

    它可能来自您将 $title 属性声明为私有而不是受保护。

    我们来看下面的例子:

    class Foo
    {
        private $property;
    
        public function getProperty()
        {
            if (null === $this->property)
            {
                return 'foo';
            }
            return $this->property;
        }
    }
    
    class Bar extends Foo
    {
        public function __construct()
        {
            $this->property = 'bar';
        }
    }
    
    $child = new Bar();
    
    echo $child->getProperty();
    

    此代码将返回“foo”,因为 $property 不是从类 Foo 继承的,因此构造方法实际上什么都不做。但是如果我们改变

    private $property;
    

    进入

    protected $property;
    

    然后

    echo $child->getProperty();
    

    将显示“栏”

    编辑:

    您的问题实际上来自嵌入式 Ticket FormType 而不是继承。根据this question,您必须在 Contact FormType 上启用 cascade_validation 参数

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Contact',
            'cascade_validation' => true
        ));
    }
    

    否则只会验证您的联系人实体。

    【讨论】:

    • 这显然是有道理的,但是我将我的属性更改为受保护并得到完全相同的结果...顺便说一句,即使我的标题属性是私有的,我也可以通过我的访问和修改它扩展实体...我不明白出了什么问题。
    • 您是否尝试在 getTitle 方法上设置验证器?如Symfony documentation 中所述
    • 嗯,你能提供你的控制器吗?
    • 我在第一条消息中添加了一些元素
    • 好吧,实际上它并没有改变任何东西,但是你的回答让我得到了答案,谢谢:) - 实际上 symfony 3 中已经删除了 cascade_validation
    【解决方案2】:

    我需要在我的集合上手动添加验证,因为 symfony 3 中删除了 cascade_validation,就像这样:

    $builder
                    ->add('tickets', CollectionType::class, array(
                        'entry_type' => TicketType::class,
                        'allow_add' => true,
                        'allow_delete' => true,
                        'label' => false,
                        'by_reference' => false
                    ))
    

    【讨论】:

      猜你喜欢
      • 2011-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多