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.