Symfony2 - 如何根据数据库的动态参数创建表单? (EAV)

发布于 2024-12-03 00:53:12 字数 1809 浏览 2 评论 0原文

我想根据存储在数据库中的动态参数创建表单。 因此,我创建了一个名为 Parameter 的实体,它定义参数名称,该名称应显示为表单字段标签。

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

特定对象(公司对象)的参数值将存储在 ParameterValue 表中。

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

当然,公司实体包含参数属性,该属性仅存储为公司指定的参数。

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

如何创建从数据库动态获取所有参数的表单,创建具有特定标签的文本字段(label=Parameter->getName())并获取已与公司关联的参数的 ParameterValues(用于编辑操作)?

我已经创建了获取 ParameterValues 的“集合”字段,但问题是我获取的表单包含已用于公司但没有用于其他参数的参数字段。当然,我无法获得标签,因为集合字段类型是 ParameterType 而不是 Parameter。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

予囚 2024-12-10 00:53:12

我最近不得不做类似的事情。我将分享我的经验并尝试融入您的观点。您可能需要对此进行一些修改以满足您的需要。

我的公司实体与您的类似。我希望存储的每个公司都具有与其关联的动态数量的参数和值,并且能够使用 symfony2 表单框架在表单中编辑这些参数和值。

我首先创建了一个名为 CompanyParameter 的实体。添加命名空间并保存在包中的某个位置。

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

使用该类创建一个新变量并将参数发送给它。

$parameters = $em->getRepository("YourBundle:Parameter")->findAll();
$companyparameter = new CompanyParameter($parameters);

您现在拥有一个包含您想要管理的所有动态参数的实体。 (如果您想加载 CompanyParameter 并已存储值以进行编辑,只需向 CompanyParameter 发送一个 ParameterValue 实体数组并在构造函数中设置 $edit=true 即可。

创建一个 CompanyParameterFormType,如 http://symfony.com/doc/current/book/forms.html#creating-form-classes
确保 data_class 指向 CompanyParameter

在控制器中创建一个新表单:

$form = $this->createForm(new CompanyParameterTypeBundle(), $companyparameter);

在 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"]));
        }           
    }

如果我们使用 $form->createView(),我们现在将拥有一个包含“公司名称”和“CEO”两个字段的表单。

填写表单并将表单的提交发送回相同的操作。

在操作中检查 post 和 $form->bindRequest($this->getRequest())。

CompanyParameter 现在包含属于当前公司的参数的所有值。要保留此数据:

$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++;
}

如果您要编辑参数

$data = $companyparameter->get();
foreach ($parameters as $k => $value) {
$value->setValue($data[$value->getParameterid()]["value"]);
$em->persist($value);
}

希望这会有所帮助。我第一次发帖,我不太习惯“解释”代码,所以请记住。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文