원칙 2 엔티티에서 변경/업데이트된 모든 필드를 가져올 수 있는 기본 제공 방법이 있습니까?

엔티티를 취득했다고 칩시다.$e설정기를 사용하여 상태를 수정합니다.

$e->setFoo('a'); $e->setBar('b'); 

변경된 필드 배열을 가져올 수 있습니까?

이 예제의 경우 검색하려고 합니다.foo => a, bar => b결과적으로.

PS: 네, 모든 액세스 장치를 변경하여 이 기능을 수동으로 구현할 수 있지만, 이 기능을 쉽게 구현할 수 있는 방법을 찾고 있습니다.



질문에 대한 답변



사용할 수 있습니다.DoctrineORMEntityManager#getUnitOfWork을 얻다DoctrineORMUnitOfWork.

다음으로 변경 세트 계산(관리 엔티티에서만 동작)을 트리거합니다.DoctrineORMUnitOfWork#computeChangeSets().

다음과 같은 유사한 방법을 사용할 수도 있습니다.DoctrineORMUnitOfWork#recomputeSingleEntityChangeSet(DoctrineORMClassMetadata $meta, $entity)전체 객체 그래프에서 반복하지 않고 무엇을 확인하고 싶은지 정확히 알고 있는 경우.

그 후 를 사용할 수 있습니다.DoctrineORMUnitOfWork#getEntityChangeSet($entity)오브젝트에 대한 모든 변경 내용을 가져옵니다.

종합:

$entity = $em->find('MyEntity', 1); $entity->setTitle('Changed Title!'); $uow = $em->getUnitOfWork(); $uow->computeChangeSets(); // do not compute changes if inside a listener $changeset = $uow->getEntityChangeSet($entity); 

참고. 업데이트수신기 내에서 업데이트된 필드를 가져오려고 할 경우 이미 수행된 변경 집합은 다시 계산하지 마십시오.단순히 getEntityChangeSet을 호출하여 엔티티에 대한 모든 변경을 가져옵니다.

경고:코멘트에서 설명한 바와 같이 이 솔루션은 독트린이벤트 리스너 이외에서는 사용할 수 없습니다.이것으로 독트린의 행동이 깨질 것이다.




다음 퍼블릭(내부 아님) 기능을 확인합니다.

$this->em->getUnitOfWork()->getOriginalEntityData($entity);

교리보고에서:

/**
* Gets the original data of an entity. The original data is the data that was
* present at the time the entity was reconstituted from the database.
*
* @param object $entity
*
* @return array
*/ public function getOriginalEntityData($entity) 

이 기능을 구현하기만 하면 됩니다.toArray또는serialize기능하여 차이를 만듭니다.이런 느낌:

$originalData = $em->getUnitOfWork()->getOriginalEntityData($entity); $toArrayEntity = $entity->toArray(); $changes = array_diff_assoc($toArrayEntity, $originalData); 



에서 설명한 방법을 사용하여 기업의 변경 사항을 확인하고자 하는 경우 크게 주의하시기 바랍니다.

$uow = $em->getUnitOfWork(); $uow->computeChangeSets(); 

$uow->computeChangeSets()method는 상기의 솔루션을 사용할 수 없게 하는 방법으로 영속적인 루틴에 의해 내부적으로 사용됩니다.이 방법에 대한 코멘트에는 다음과 같은 내용이 기재되어 있습니다.@internal Don't call from the outside. 다음 엔티티에 대한 변경 내용을 확인한 후$uow->computeChangeSets()다음 코드 조각은 메서드의 마지막에 실행됩니다(관리 대상 엔티티별로).

if ($changeSet) {
$this->entityChangeSets[$oid]
= $changeSet;
$this->originalEntityData[$oid] = $actualData;
$this->entityUpdates[$oid]
= $entity; } 

$actualDataarray는 엔티티의 속성에 대한 현재 변경 사항을 유지합니다.이것들은 에 써지는 대로$this->originalEntityData[$oid]이 변경은 아직 지속되지 않은 엔티티의 원래 속성으로 간주됩니다.

그 후,$em->persist($entity)엔티티에 대한 변경을 저장하기 위해 호출됩니다.또한 메서드도 포함됩니다.$uow->computeChangeSets()그러나 아직 지속되지 않은 변경은 엔티티의 원래 속성으로 간주되기 때문에 엔티티에 대한 변경은 찾을 수 없습니다.




통지 정책을 사용하여 변경을 추적할 수 있습니다.

먼저 Notify를 구현합니다.PropertyChanged 인터페이스:

/**
* @Entity
* @ChangeTrackingPolicy("NOTIFY")
*/ class MyEntity implements NotifyPropertyChanged {
// ...
private $_listeners = array();
public function addPropertyChangedListener(PropertyChangedListener $listener)
{
$this->_listeners[] = $listener;
} } 

다음으로 데이터를 변경하는 모든 메서드에 대해 다음과 같이 _onPropertyChanged를 호출합니다.

class MyEntity implements NotifyPropertyChanged {
// ...
protected function _onPropertyChanged($propName, $oldValue, $newValue)
{
if ($this->_listeners) {
 foreach ($this->_listeners as $listener) {

$listener->propertyChanged($this, $propName, $oldValue, $newValue);
 }
}
}
public function setData($data)
{
if ($data != $this->data) {
 $this->_onPropertyChanged('data', $this->data, $data);
 $this->data = $data;
}
} } 



변경 내용이 반환됩니다.

$entityManager->getUnitOfWork()->getEntityChangeSet($entity)