Symfony2 - how to create form based on dynamic parameters from db? (EAV)
I would like to create form based on dynamic parameters that are stored in DB. So I've created an entity called Parameter that defines parameter name, which should be displayed as form field label.
/**
* @ORM\Entity
*/
class Parameter
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", length="255")
* @Assert\NotBlank()
*/
protected $name;
/**
* @ORM\OneToMany(targetEntity="ParameterValue", mappedBy="parameter")
*/
protected $values;
Parameter values for specific object (Company object) are about to be stored in ParameterValue tabel.
/**
* @ORM\Entity
*/
class ParameterValue
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToOne(targetEntity="Parameter", inversedBy="values")
* @ORM\JoinColumn(name="parameter_id", referencedColumnName="id", nullable=false)
*/
protected $parameter;
/**
* @ORM\ManyToOne(targetEntity="Company", inversedBy="parameters")
* @ORM\JoinColumn(name="company_id", referencedColumnName="id", nullable=false)
*/
protected $company;
And of course Company entity contains parameters attribute that stores only those parameters that has been specified for Company.
/**
* @ORM\Entity
*/
class Company
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", length="255")
*/
protected $name;
/**
* @ORM\OneToMany(targetEntity="ParameterValue", mappedBy="hotel")
*/
protected $开发者_运维问答parameters;
How can I create Form that dynamically fetches all Parameters from DB, creates text fields with specific labels (label=Parameter->getName()) and gets ParameterValues for parameters that has already been associated with Company (for edit action)?
I have already created 'collection' field that gets ParameterValues but the problem is that I get form with fields for parameters that has been used for Company but no others. And of course I cannot get label because collection field type is ParameterType not Parameter.
I recently had to do something similar. I will share my experience and try an incorporate your point of view. You may have to modify this some to fit your need.
I had my Company entity similar to yours. I wanted each Company stored to have a dynamic amount of parameters and values associated with them and able to edit these in forms using the symfony2 form framework.
I first created an entity called CompanyParameter. Add namespace and save somewhere in your bundle.
class CompanyParameter {
protected $data;
public function __construct($parameters,$edit=false)
{
if ($edit==false) {
foreach ($parameters as $k => $value) {
$name = $value->getId();
$this->data[$name] = array("label"=>$value->getName(),"value"=>"");
$this->{$name} = "";
}
} else {
foreach ($parameters as $k => $value) {
$name = $value->getParameterid();
$pvalue = $value->getValue();
$this->data[$name] = array("label"=>$value->getName(),"value"=>$pvalue);
$this->{$name} = $pvalue;
}
}
}
public function get() { return $this->data; }
}
Create a new variable with the class and send your parameters to it.
$parameters = $em->getRepository("YourBundle:Parameter")->findAll();
$companyparameter = new CompanyParameter($parameters);
You now have an entity with all the dynamic parameters you want to manage. (If you want to load the CompanyParameter with already stored values for edit purpose, just send CompanyParameter an array of ParameterValue entities instead and set $edit=true in constructor.
Create a CompanyParameterFormType like described at http://symfony.com/doc/current/book/forms.html#creating-form-classes Make sure data_class points to CompanyParameter
Create a new form in your controller:
$form = $this->createForm(new CompanyParameterTypeBundle(), $companyparameter);
Inside the CompanyParameterFormType:
public function buildForm(FormBuilder $builder, array $options)
{
$data = $options["data"]->get();
foreach ($data as $k => $value) {
$builder->add($k,"text",array("label"=>$value["label"]));
}
}
If we would $form->createView() we would now have a form with the two fields "Company name" and "CEO".
Fill in the form and send the submit of the form back to the same action.
In the action check for post and $form->bindRequest($this->getRequest()).
CompanyParameter now contains all the values for the parameters belonging to current company. To persist this data:
$data = $companyparameter->get();
$counter = 0;
foreach($data as $k => $value) {
$parameter = new ParameterValue();
$parameter->setCompany($company);
$parameter->setParameter($parameters[$counter]);
$parameter->setValue($value["value"]);
$em->persist($parameter);
$counter++;
}
If You are instead editing the parameters
$data = $companyparameter->get();
foreach ($parameters as $k => $value) {
$value->setValue($data[$value->getParameterid()]["value"]);
$em->persist($value);
}
Hope this helps some. My first time posting and I'm not that used to "explaining" code yet so keep in mind please.
精彩评论