I'm new to symfony and I'm experiencing a bit with it's functionalities. I'm facing a problem and I will simplify it for better understanding : let's say we have a Shape Doctrine Entity (I want only one table to store different kind of shapes) :
class Shape {
protected $id;
protected $type;
protected $options;
}
Depending of the shape type, the options will differ :
class Rectangle extends Shape {
protected $options = array('width' => 20, 'height' => 20);
protected $type = 'rectangle';
}
class Circle extends Shape {
protected $options = array('radius' => 15);
protected $type = 'circle';
}
Now I would like to create a generalist form with the formBuilder for adding/creating such entities (I'm using sonata but it's not very important)
So with a Choice input for the type and other inputs for the options that will change depending of the type choosen. (I have a function that returns an array of the available options and their type on each extended class)
.content {
font-family: Arial;
}
<form class="content">
<label>Type : </label><select name="type">
<option value="circle">Circle</option>
<option value="rectangle">Rectangle</option>
</select>
<fieldset>
<legend>Circle</legend>
<input type="number" name="radius" placeholder="Radius">
</fieldset>
<fieldset>
<legend>Rectangle</legend>
<input type="number" name="width" placeholder="Width">
<input type="number" name="height" placeholder="Height">
</fieldset>
</form>
Is this approach correct ?
And how could I implement this form ? (My first thoughts would be some ajax or directly outputing every inputs for every options and then a javascript function that will display the right ones depending of the choosen type)
Any opinion/better approach is greatly appreciated.
I usually do the following steps:
1. Doctrine Inheritance Mapping
First make sure you use one of the doctrine inheritance mapping approaches for your entities, e.g. the 'JOINED' table method:
# AppBundle/Entity/Shape.php
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorMap({
* "rectangle" : "AppBundle\Entity\Rectangle",
* "circle" : "AppBundle\Entity\Circle"
* })
*/
class Shape {
protected $id;
protected $type;
protected $options;
}
2. Set the child classes in your admin service definition:
# app/config/services.yml
app.admin.shape:
class: AppBundle\Admin\ShapeAdmin
arguments: [~, AppBundle\Entity\Shape, SonataAdminBundle:CRUD]
tags:
- { name: sonata.admin, manager_type: orm, group: admin, label: InterestService }
calls:
- [setSubclasses, [{'Rectangle': AppBundle\Entity\Rectangle, 'Circle': AppBundle\Entity\Circle}]]
3. check type of object in admin class
Now you can check inside the admin class for the type of the subject, and manipulate the views to your liking. You could, e.g. change the edit form in the configureFormFields
method:
# AppBundle/Admin/ShapeAdmin.php
protected function configureFormFields(FormMapper $formMapper)
/** @var Shape $shape */
$shape = $this->getSubject();
// add form fields for both types
$formMapper
->add('service', null, ['disabled' => true]);
// add specific form fields
if ($shape instanceof Rectangle) {
// custom rectangle form fields
} elseif ($shape instanceof Circle {
// custom circle form fields
}
}