2016-03-25 7 views
1

Ist das immer der Fall? Ich habe das Internet durchsucht und die Dokumente gelesen, bin aber nicht klüger. Ich habe gelesen, dass DataTransformers nicht angewendet werden kann, wenn inherit_data wahr ist, was auch eine Schande scheint. (Was könnte der Grund sein?)DataMapper nicht untergeordnet FormType mit 'inherit_data' => true (Symfony)

Ich habe ein Formtype ‚PermissionType‘ die Karten eine ‚Erlaubnis‘. Berechtigung hat, wie auch einige andere Entitäten, eine Erstellung/lastModification DateTime. Nachdem ich How to Reduce Code Duplication with "inherit_data" gelesen hatte ging ich natürlich meinen Weg um den neu gefundenen guten Rat zu implementieren und erstellte einen TimeTrackedType.

Dieses untergeordnete Formular für PermissionType zeigt zwei DateTimeType-Felder an und hat inherit_data auf true festgelegt. Sie werden korrekt für den Browser gerendert, aber sie bleiben leer, aber ich versuche, Daten in sie einzugeben. Ich begann mit dem Hinzufügen eines DataMappers, aber der von TimeTrackedType wird nicht aufgerufen. Der DataMapper des übergeordneten PermissionType ist jedoch ein untergeordnetes Formular und scheint der einzige Ort zu sein, an dem ich den Wert der DateTimeType-Felder von TimeTrackedType ändern kann.

Ich hoffe, dass ich hier etwas falsch mache, weil es falsch erscheint, die Eingaben in der untergeordneten Form zu erstellen, sie aber in der übergeordneten Klasse zuordnen zu müssen. Kann jemand das näher ausführen? Alle Hinweise werden sehr geschätzt.

Hier sind die Entitäten, erste Benutzer:

/** 
* @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; 
    // (...) 
} 

Dann Erlaubnis:

/** 
* @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...) 
} 

Schließlich Klasse Rolle:

/** 
* @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; 
} 

Und nun die 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' 
    ]); 
} 
} 

... und ...

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'; } 

} 

... und schließlich:

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'; } 
} 
+0

Es wäre mir klarer mit einem Minimum an Code :) – Heah

+0

Da gehen Sie. Habe ich etwas Außergewöhnliches getan? – Firestorm

+0

Ich verstehe nicht, hat die "Permission" -Einheit eine "Timing" -Eigenschaft mit richtiger Getter und Setter? weil es so aussieht, als ob Sie ein Merkmal verwenden, um die Datumsfelder hinzuzufügen. – Heah

Antwort

0

Der Artikel DataMapper gar nicht verwenden.

ein Merkmals Mit der Benutzung der Eigenschaften Teil des PermissionEntity Objekts als normal sind, so anstatt diese Eigenschaften wie die anderen Felder in der entsprechenden PermissionType Form zu halten, werden sie in ihrem Unterformulartyp TimeTrackedEntityType verschachtelt.

Dann brauchen Sie nur inherit_data zu true und die richtige data_class Option zu setzen, wenn Sie diese Unterform benötigen sonst wo, und das ist, was Sie bereits in TimeTrackedEntityType tun, da die Unter Form ihrer Daten Mutter Formulars bekommt, so dass keine Notwendigkeit für DataMapper.

Wenn Sie eines verwenden möchten, sollte es nur mit dem übergeordneten Formular sein, nicht mit seinem untergeordneten Element, es wird wie erwartet ignoriert.

Verwandte Themen