DataMapper没有使用' inherit_data'来调用子FormType。 =>真(Symfony)

时间:2016-03-25 22:17:36

标签: symfony-forms symfony

总是这样吗?我已经在网上搜索并阅读了文档,但不是更明智的。我确实读过,当 inherit_data 为真时,不能应用DataTransformers,这似乎也是一种耻辱。 (可能是什么原因?)

我有一个FormType ' PermissionType' ,用于映射'权限' 权限和其他一些实体一样,还有 creation / lastModification DateTime 。阅读How to Reduce Code Duplication with "inherit_data"后,我自然而然地继续实施新发现的好建议并创建了 TimeTrackedType

此子窗体到PermissionType显示两个DateTimeType字段,inherit_data设置为true。它们被正确呈现给浏览器,但它们仍然是空的,但我尝试将数据输入它们。我开始时添加了一个DataMapper,但没有调用TimeTrackedType。然而,它的父PermissionType的DataMapper本身就是一个子表单,而且这似乎是我可以更改TimeTrackedType的DateTimeType字段值的唯一地方。

我希望我在这里做错了,因为在子表单中创建输入但在父类中必须映射到它们似乎是错误的。任何人都可以详细说明这个吗?任何指针都非常感谢。

以下是实体,第一位用户:

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 */
class User implements AdvancedUserInterface, \Serializable {
    use HasSingleId, TimeTrackedEntityTrait, EntityCreatorTrait;
    //                 ^^^ This trait has two DateTime fields and that's it.
    // (...)
    /**
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Permission", mappedBy="user")
     * @Assert\Valid()
     */
    private $permissions;
    // (...)
}

然后许可:

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\PermissionRepository")
 */
class Permission {
use TimeTrackedEntityTrait, EntityCreatorTrait;

/**
 * @var User
 * @ORM\Id
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="permissions")
 */
private $user;

/**
 * @var array
 * @ORM\Id
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Role", inversedBy="permissions")
 */
private $role;
// (...getters and setters...)
}

最后一级角色:

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\RoleRepository")
 */
class Role implements RoleInterface {
use HasSingleId, TimeTrackedEntityTrait, EntityCreatorTrait;

/**
 * @var type string
 * @ORM\Column(type="string", nullable=false, unique=true);
 */
private $name;

/**
 * @var type ArrayCollection
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\Permission", mappedBy="role")
 * @Assert\Valid()
 */
private $permissions;
}

现在FormTypes:

class UserType extends AbstractType {

/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder->add('username', TextType::class, [ 'attr' => [ 'size' => 10 ] ] )
            ->add('password', RepeatedType::class, [
                'type' => PasswordType::class, 
                'attr' => ['size' => 10 ], 
                'first_options' => [ 'label' => 'Password' ], 
                'second_options' => [ 'label' => 'Confirm' ] ]);
    $entity = $builder->getData();
    $admin = $entity->hasRole('ROLE_ADMIN');
    if($admin) {
        $builder->add('id', TextType::class, [ 'attr' => [ 'size' => 4 ] ]);
        $builder->add('isEnabled', CheckboxType::class, [ 'required' => false ]);
    }

    $builder->add('permissions', CollectionType::class, [
        'data_class' => 'Doctrine\ORM\PersistentCollection',
        'mapped'=>true, 
        'prototype'=>true,
        'allow_add'=>true,
        'allow_delete'=>true,
        'entry_type' => PermissionType::class]);
    $builder->add('email', EmailType::class);
}

/**
 * @param OptionsResolver $resolver
 */
public function configureOptions(OptionsResolver $resolver) {
    $resolver->setDefaults([
        'required' => true,
        'mapped' => true,
        'data_class' => 'AppBundle\Entity\User'
    ]);
}
}

...和...

class PermissionType extends AbstractType implements DataMapperInterface {

public function mapDataToForms($permission, $forms) {
    $forms = iterator_to_array($forms);
    if($permission instanceof Permission && $permission) {
        $forms['role']->setData($permission->getRole()->getName());
        // These two statements get the job done, but not as was intended.
        $forms['created']->setData($permission->getCreated());
        $forms['lastModified']->setData($permission->getLastModified());
    }

}

public function mapFormsToData($forms, &$permission) {
    $forms = iterator_to_array($forms);
    if($permission instanceof Permission) {
        $permission->setCreated($forms['created']->getData());
        $permission->setLastModified($forms['lastModified']->getData());
    }
}


public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder->setDataMapper($this);
    $builder->add('role', TextType::class, [ 'mapped' => true ]);
    $builder->add('timing', TimeTrackedEntityType::class, [ 
    'data_class' => 'AppBundle\Entity\Permission', 
    'inherit_data' => true, 'mapped'=>true ]);
}

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

public function getParent() {
    return FormType::class;
}

public function getName() { return 'PermissionType'; }

}

......最后:

class TimeTrackedEntityType extends AbstractType implements DataMapperInterface {
// This is the method that doesn't get called
public function mapDataToForms($permission, $forms) {
    $forms = iterator_to_array($forms);
    $forms['created']->setData($permission->getCreated()->format("d/m/Y H:i:s"));
$forms['lastModified']->setData($permission->getLastModified()->format("d/m/Y H:i:s"));
}
public function mapFormsToData($forms, &$data) {
    $forms = iterator_to_array($forms);
    $data->setCreated($forms['created']->getData());
    $data->setLastModified($forms['lastModified']->getData());
}
public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->setDataMapper($this);
    $builder->add('created', DateTimeType::class, [
         'format' => 'd/M/Y H:i:s', 
         'input' => 'datetime', 
         'widget' => 'single_text',
         'attr'=>['size'=>14, 'class'=>'right'],
         'mapped' => true ]);
    $builder->add('lastModified', DateTimeType::class, [ 
        'format' => 'd/M/Y H:i:s',
        'input' => 'datetime', 
        'widget' => 'single_text', 
        'attr'=>['size'=>14, 'class'=>'right'], 
        'mapped' => true ]);
}
public function configureOptions(OptionsResolver $resolver) {
    $resolver->setDefaults(array(
        'mapped'=>true,
        'compound'=>true,
        'inherit_data' => true,
    ));
}

public function getName() { return 'TimeTrackedEntityType'; }
}

1 个答案:

答案 0 :(得分:0)

该文章根本不使用DataMapper

使用特征意味着属性是正常的PermissionEntity对象的一部分,因此它们不是像对应的PermissionType形式中的其他字段那样保存这些属性,而是嵌套在子表单类型中TimeTrackedEntityType

然后,您只需要将inherit_data设置为true和右data_class选项,如果您需要此子表单,其他地方,以及您已经在{ {1}},因为子表单获取其父表单的数据,因此不需要TimeTrackedEntityType

如果你想使用一个,它应该只有父表单而不是它的子表单,它会被按预期忽略。