我想知道是否有一种方法可以向Symfony2上的任何实体动态添加字段。我在大互联网上搜索,什么也没找到。当我说"一种方式"时,我的意思是,如果存在具有该行为的条令扩展、实现它的捆绑包、设计模式等。
我的想法类似于教义扩展的可翻译行为。假设我有一个Address实体,所以我想动态添加一些属性,比如街道、数字、十字路口等,但一开始我不知道可能存在哪些字段。
我把一些东西看作两个实体:Address和AddressFieldValues。Address将具有特定的属性,如id、与其他classess关系的外键,并将用于注入动态属性(字段值的集合)。AddressFieldValue将具有Address的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_value,这些表具有以下值:
// 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作为示例,但这种行为可以用于任何实体。
提前感谢
我认为您的请求类似于表单中的集合(Doctrine2文档)。
在文档中,具有name
属性的Tags
实体的集合链接到Task
实体。在您的情况下,实体AddressFieldValue
将具有field
和content
属性,并且AddressFieldValue
实体的集合将添加到Address
实体中。
因此,通过使用此文档并用Address
替换Task
,用AddressFieldValue
替换Tag
,它应该可以工作。