简体   繁体   中英

In Sonata Admin, How To Get Unmapped Field in sonata_type_collection Embedded Admins

I'm using Sonata Admin with Symfony 2.8.9.

Two entities: Skill and SkillStep. Skills have a one-to-many relationship with SkillSteps.

The Skill admin has a sonata_type_collection field, which embeds multiple SkillStep admins.

Each SkillStep admin has an unmapped text field called "data". It does not map directly to any value in the SkillStep entity.

When the user saves or updates a Skill, I want to run arbitrary code based on the input to the "data" field of each SkillStep admin in the sonata_type_collection.

The obvious place to do this would be prePersist() and preUpdate() in the SkillStep admin. However,

When embedding one Admin within another, for example using the sonata_type_admin field type, the child Admin's hooks are not fired.

How can I work with the unmapped fields of admins embedded with sonata_type_collection when saving the top-level entity? It is important that these unmapped fields are associated with the object of the admin they're in.

Relevant code:

# Entity/Skill.php

class Skill {
    /**
     * @ORM\OneToMany(targetEntity="SkillStep", mappedBy="skill")
     */
    private $steps;

    // ...
}

# Entity/SkillStep.php

class SkillStep {
    /**
     * @ORM\ManyToOne(targetEntity="Skill")
     * @ORM\JoinColumn(name="skill_id", referencedColumnName="id")
     **/
    protected $skill;

    // ..
}

# Admin/SkillAdmin.php

class SkillAdmin extends Admin 
{
    // Fields to be shown on create/edit forms
    protected function configureFormFields(FormMapper $formMapper) {
        $formMapper
            ->add('name')
            ->add('steps', 'sonata_type_collection',
                ['required' => false, 'label' => 'Manage the skill steps'],
                ['edit'=>'inline','inline'=>'standard']
            )
        ;
    }
}

# Admin/SkillStepAdmin.php

class SkillStepAdmin extends Admin 
{
    // Fields to be shown on create/edit forms
    protected function configureFormFields(FormMapper $formMapper) {
        $formMapper
            ->add('name')
            ->add('route')
            ->add('data', 'textarea', [
                'mapped' => false,
                'data' => $step_data,
            ])
        ;
    }

    // Before a new skill step is saved
    public function prePersist($skill_step) {
        // THIS IS NEVER CALLED BECAUSE THIS ADMIN IS EMBEDDED
    }

    // Before an existing skill step is updated
    public function preUpdate($skill_step) {
        // THIS IS NEVER CALLED BECAUSE THIS ADMIN IS EMBEDDED
    }

}

You need to manage this manually. Check out this example in the official documentation and the related issue entry

Regarding your example you can do something like this (replace the skill_step_admin_service_id with your service id to make this work):

# Admin/SkillAdmin.php    
private function getStepAdmin() {
    return $this->getConfigurationPool()
                ->getAdminByAdminCode('skill_step_admin_service_id');
}

public function prePersist($skill)
{
    foreach ($skill->getSteps() as $step) {
        $this->getStepAdmin->prePersist($step); 
    }
}

public function preUpdate($skill)
{
    foreach ($skill->getSteps() as $step) {
        $this->getStepAdmin->preUpdate($step); 
    }
}

adding to lordrhodos answer. You can access to unmapped field directly in the same form, just check form children. like:

$myUnmappedData = $form->get('steps')->get($key)->get('SkillStep')->get('unmappedField')->getData();

example:

# Admin/SkillAdmin.php    
private function getStepAdmin() {
    return $this->getConfigurationPool()
                ->getAdminByAdminCode('skill_step_admin_service_id');
}

public function prePersist($skill)
{
    
    foreach ($skill->getSteps() as $key => $step) {
        #access to unmapped form field
        $myUnmappedData = $form->get('steps')->get($key)->get('SkillStep')->get('unmappedField')->getData();
        $this->getStepAdmin->publicFunctionToManageMyData($step, $myUnmappedData); 
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM