如何在symfony2实体中动态添加字段

时间:2014-04-18 22:08:49

标签: php symfony doctrine-orm

我想知道是否存在将动态添加到Symfony2上的任何实体的方法。我在大型互联网上搜索,但我找不到任何东西。当我说"一种方式"时,我的意思是如果存在具有该行为的Doctrine扩展,实现它的包,设计模式等。

我的想法类似于Doctrine Extensions的可翻译行为。 Supouse我有一个地址实体,所以我想在街道上添加一些属性,如街道,数字,交叉点等,但在开始时我并不知道哪些字段可能存在。

我认为有两个实体:Address和AddressFieldValues。地址将具有特定属性,如id,与其他classess的关系的foreing键,并将用于注入动态属性(字段值的集合)。 AddressFieldValue将具有地址的reals字段值,具有以下属性:id,address_id,field_name,field_value。

所以,实体地址可能是这样的:

/**
 * Address
 *
 * @ORM\Entity(repositoryClass="AddressRepository")
 * @ORM\Table(name="address")
 */
class Address
{
    /**
    * @var integer
    *
    * @ORM\Column(name="id", type="integer")
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    private $id;


    /**
     * @ORM\OneToMany(
     *   targetEntity="AddressFieldValues",
     *   mappedBy="object",
     *   cascade={"persist", "remove"}
     * )
     */
    private $field_value;

    public function __construct()
    {
        $this->field_value = new ArrayCollection();
    }

    public function getFieldValue()
    {
        return $this->field_value;
    }

    public function addFieldValue(AddressFieldValues $fv)
    {
        if (!$this->field_value->contains($fv)) {
            $this->field_value[] = $fv;
            $fv->setObject($this);
        }
    }

    public function getId()
    {
        return $this->id;
    }
}

和AddressFieldValues实体可能是这样的:

/**
 * @ORM\Entity
 * @ORM\Table(name="address_field_values",
 *     uniqueConstraints={@ORM\UniqueConstraint(name="lookup_unique_idx", columns={
 *         "object_id", "field"
 *     })}
 * )
 */
class AddressFieldValues
{

    /**
     * @var integer $id
     *
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue
     */
    protected $id;

    /**
     * @var string $field
     *
     * @ORM\Column(type="string", length=32)
     */
    protected $field;

    /**
     * @ORM\ManyToOne(targetEntity="Address", inversedBy="field_value")
     * @ORM\JoinColumn(name="object_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $object;

    /**
     * @var string $content
     *
     * @ORM\Column(type="text", nullable=true)
     */
    protected $content;

    /**
     * Convenient constructor
     *
     * @param string $field
     * @param string $value
     */
    public function __construct($field, $value)
    {
        $this->setField($field);
        $this->setContent($value);
    }        

    /**
     * Get id
     *
     * @return integer $id
     */
    public function getId()
    {
        return $this->id;
    }


    /**
     * Set field
     *
     * @param string $field
     */
    public function setField($field)
    {
        $this->field = $field;
        return $this;
    }

    /**
     * Get field
     *
     * @return string $field
     */
    public function getField()
    {
        return $this->field;
    }

    /**
     * Set object related
     *
     * @param string $object
     */
    public function setObject($object)
    {
        $this->object = $object;
        return $this;
    }

    /**
     * Get related object
     *
     * @return object $object
     */
    public function getObject()
    {
        return $this->object;
    }

    /**
     * Set content
     *
     * @param string $content
     */
    public function setContent($content)
    {
        $this->content = $content;
        return $this;
    }

    /**
     * Get content
     *
     * @return string $content
     */
    public function getContent()
    {
        return $this->content;
    }        
}

所以,如果我在表上有以下值:address_field_values

  id | object |      field      |    content
  1  |   1    |  street         | 1st Ave
  2  |   1    |  number         | 12345
  3  |   1    |  intersections  | 2sd Ave and 4th Ave
  4  |   2    |  street         | 1st Ave
  5  |   2    |  number         | 12347
  6  |   2    |  intersections  | 2sd Ave and 4th Ave
  7  |   3    |  street         | 1st Ave
  8  |   3    |  number         | 12349
  9  |   3    |  intersections  | 2sd Ave and 4th Ave

现在地址表只有以下值:

|  id |
|  1  |
|  2  |
|  3  |

我可以动态地将这些字段值注入到Address对象中,以执行以下操作:

// if I need get de Address with id = 2
$addressRepository = $em->getRepository('Address');
$address = $addressRepository->find(2);
sprintf('The address is: "%s", #"%s" between "%s".', $address->getStreet(), $address->getNumber(), $address->getIntersections());
// then it should show: The address is 1st Ave, #12347 between 2sd Ave and 4th Ave.
//
// or if I need add a new Address, do something like this:
$address = new Address();
$address->setStreet('1st Ave');
$address->setNumber('12351');
$address->setIntersections('2sd Ave and 4th Ave');
$em->persist($address);
$em->flush();

然后保存地址和address_field_values,表格具有以下值:

// address
|  id |
|  1  |
|  2  |
|  3  | 
|  4  |  

// address_field_values
  id | object |      field      |    content
  1  |   1    |  street         | 1st Ave
  2  |   1    |  number         | 12345
  3  |   1    |  intersections  | 2sd Ave and 4th Ave
  4  |   2    |  street         | 1st Ave
  5  |   2    |  number         | 12347
  6  |   2    |  intersections  | 2sd Ave and 4th Ave
  7  |   3    |  street         | 1st Ave
  8  |   3    |  number         | 12349
  9  |   3    |  intersections  | 2sd Ave and 4th Ave
 10  |   4    |  street         | 1st Ave
 11  |   4    |  number         | 12351
 12  |   4    |  intersections  | 2sd Ave and 4th Ave

那么,任何想法我该怎么做?

请记住,我的业务逻辑中有一个要求,我不知道哪些字段可以在开始时有一个地址,所以我需要动态注入字段。我使用Address作为示例,但此行为可用于任何实体。

提前致谢

1 个答案:

答案 0 :(得分:0)

我认为您的请求类似于collection in a form (Doctrine2 documentation)

在文档中,具有Tags属性的name个实体的集合链接到Task实体。在您的情况下,实体AddressFieldValue将具有fieldcontent属性,AddressFieldValue实体的集合将添加到Address实体。

因此,通过使用此文档并将Task替换为Address,将Tag替换为AddressFieldValue,它应该有效。