学说跟踪多个实体关系的变化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学说跟踪多个实体关系的变化相关的知识,希望对你有一定的参考价值。

我有这个实体

class nmEntidad
{

/**
 * @var int
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 **/
private $id;

/**
 * @var boolean
 *
 * @ORM\Column(name="eliminado", type="boolean")
 **/
private $eliminado;

/**
 * @var boolean
 *
 * @ORM\Column(name="tiene_area", type="boolean")
 **/
private $tieneArea;

/**
 * @var integer
 *
 * @ORM\Column(name="tiene_entidad", type="integer")
 **/
private $tieneEntidad;

/**
 * @var string
 * @Assert\NotBlank(message="error.nmEntidad.nombre.blank")
 * @ORM\Column(name="nombre", type="string")
 **/
private $nombre;

/**
 * @var string
 * @Assert\NotBlank(message="error.nmEntidad.acronimo.blank")
 * @ORM\Column(name="acronimo", type="string")
 **/
private $acronimo;

/**
 * @var string
 *
 * @ORM\Column(name="logo", type="string", nullable=true)
 **/
private $logo;

/**
 * @var string
 *
 * @ORM\Column(name="direccion", type="string", nullable=true)
 **/
private $direccion;

/**
 * @var string
 *
 * @ORM\Column(name="telefono", type="string", length=100, nullable=true)
 **/
private $telefono;

/**
 * @var string
 * @Assert\NotBlank(message="error.nmEntidad.email.blank")
 * @Assert\Email(message="email:error.nmEntidad.email.notvalid")
 * @ORM\Column(name="email", type="string", length=50)
 **/
private $email;

/**
 * @var boolean
 *
 * @ORM\Column(name="primaria", type="boolean")
 **/
private $primaria;

/**
 * @var string
 * @Assert\NotBlank(message="error.nmEntidad.respinf.blank")
 * @Assert\Email(message="informatic_email:error.nmEntidad.respinf.notvalid")
 * @ORM\Column(name="email_responsable_informatica", type="string", length=50)
 **/
private $RespInform;

/**
 * @ORM\ManyToOne(targetEntity="nmEntidad")
 * @ORM\JoinColumn(name="id_padre", referencedColumnName="id")
 */
private $padre;

/**
 * @ORM\ManyToOne(targetEntity="nmEmpresa")
 * @ORM\JoinColumn(name="id_empresa", referencedColumnName="id")
 */
private $empresa;

/**
 * @ORM\ManyToOne(targetEntity="nmUsuario")
 * @ORM\JoinColumn(name="id_representante", referencedColumnName="id", nullable=false)
 */
private $representante;




}

然后我有一个doctrine lifecyclecallback事件的监听器,所以每当这些事件中的一个触发时,我都会为asociated事件创建一个登录数据库。

 public function onSucessLogin(AuthenticationEvent $event)
{
    if (!$event->getAuthenticationToken()->getUser() instanceof UserInterface)
        return;
    if(!$this->request)
        return;
    if ($this->request->getMethod() == 'GET')
        return;
    $user = $event->getAuthenticationToken()->getUser();
    $this->container->get('monolog.logger.db')->info('request', ['user' => $user->getUsername(), 'empresa' => $user->getEmpresa()->getEmpresa()]);

}


//establecemos el codigo de response para ver si fallo la operacion o no
public function onKernelResponse(FilterResponseEvent $event)
{
    if (!$this->checkIfUserRequest())
        return;
    if (!$this->isLog())
        return;
    if (!$event->isMasterRequest())
        return;


    $responseCode = $event->getResponse()->getStatusCode();
    if (!$this->request->attributes->has('logEntry'))
        return;
    $logEntry = $this->request->attributes->get('logEntry');
    if ($responseCode == Response::HTTP_BAD_REQUEST) {
        $logEntry['status'] = Response::HTTP_BAD_REQUEST;
    } else if ($responseCode == Response::HTTP_FORBIDDEN) {
        $logEntry['status'] = Response::HTTP_FORBIDDEN;
    } else if ($responseCode == Response::HTTP_UNAUTHORIZED) {
        $logEntry['status'] = Response::HTTP_UNAUTHORIZED;
    }
    $this->request->attributes->set('logEntry', $logEntry);
}


//terminamos de construir el log y lo procesamos a la base de datos
/*  public function onKernelFinishRequest(FinishRequestEvent $event)
  {
      $this->log($event);

  }*/

private function log()
{
    /* if (!$event->isMasterRequest())
         return;
     if (!$this->checkIfUserRequest())
         return;*/
    $log = $this->request->attributes->get('logEntry');
    if (!$log)
        return;

    $logEntity = $this->buildLog($log);
    if ($logEntity->getMessage() == '')
        return;
    $this->container->get('doctrine')->getEntityManager()->persist($logEntity);
    $this->container->get('doctrine')->getEntityManager()->flush();
}


public function preUpdate(LifecycleEventArgs $args)
{
    if (!$this->isLog())
        return;

    $entity = $args->getObject();
    $em = $this->getEm();

    $uow = $em->getUnitOfWork();
    $changeSet = $uow->getEntityChangeSet($entity);
    if ($entity instanceof UserInterface) {
        if (sizeof($changeSet) == 1 && array_key_exists("lastLogin", $changeSet)) {
            return;
        }
    }
    if (!$changeSet)
        return;
    $value = $this->generateObjectChangeSet($entity, $changeSet, 'preUpdate');
    $this->addEntityChangeSet($value);
    //generando el id
}


public function postUpdate(LifecycleEventArgs $args)
{

    if (!$this->isLog())
        return;

    $method = $this->request->getMethod();
    $body = array();
    $entity = $args->getObject();
    $changeSet = $this->getEntityChangeSet($entity, 'preUpdate');

    if (!$changeSet && $method != 'DELETE')
        return;

    if ($method == 'DELETE') {
        $message = array('action.delete', 'target:%s', 'id:%s');
        $params = array($this->getEntityName(get_class($entity)), $entity->getName());
        $body['message'] = $message;
        $body['params'] = $params;
    } else {
        if ($this->request->request->get('deleted') === 'false' && $entity->getEliminado()) {
            //dump($changeSet);die;
            $message = array('action.restore', 'target:%s', 'id:%s', 'values:%s');
            $params = array($this->getEntityName(get_class($entity)), $entity->getName(), $changeSet);
            $body['message'] = $message;
            $body['params'] = $params;
        } else {
            //dump($changeSet);die;
            $message = array('action.update', 'target:%s', 'id:%s', 'values:%s');
            $params = array($this->getEntityName(get_class($entity)), $entity->getName(), $changeSet);
            $body['message'] = $message;
            $body['params'] = $params;
        }
    }


    $this->addEntryLog($body);
    $this->log();
}

public function postPersist(LifecycleEventArgs $args)
{
    if (!$this->isLog())
        return;
    $body = array();
    $entity = $args->getObject();
    $name = $this->getEntityName(get_class($entity));
    if ($name == 'Log')
        return;
    $method = $this->request->getMethod();
    if ($method == 'DELETE')
        return;
    $message = array('action.insert', 'target:%s', 'id:%s');
    $params = array($this->getEntityName(get_class($entity)), $entity->getName());
    $body['message'] = $message;
    $body['params'] = $params;
    $this->addEntryLog($body);
    $this->log();
}

public function preRemove(LifecycleEventArgs $args)
{
    if (!$this->isLog())
        return;
    $entity = $args->getObject();
    $value = $this->generateObjectChangeSet($entity, $entity->getname(), 'preRemove');
    $this->addEntityChangeSet($value);
}

public function postRemove(LifecycleEventArgs $args)
{
    if (!$this->isLog())
        return;
    $body = array();
    $entity = $args->getObject();
    $changeSet = $this->getEntityChangeSet($entity, 'preRemove');
    /*if (!$changeSet)
        return;*/
    $message = array('action.deletefromsystem', 'target:%s', 'id:%s');
    $params = array($this->getEntityName(get_class($entity)), $entity->getname());
    $body['message'] = $message;
    $body['params'] = $params;
    $this->addEntryLog($body);
    $this->log();
}

/**
 * @param mixed $request
 */
public function setRequest($request)
{
    $this->request = $request->getCurrentRequest();
}

private function addEntryLog($entry)
{
    $logEntry = $this->request->attributes->get('logEntry');
    $logEntry['body'][] = $entry;
    $this->request->attributes->set('logEntry', $logEntry);
    $this->request->attributes->remove('entityChangeSet');
}

private function addEntityChangeSet($object)
{
    $this->request->attributes->set('entityChangeSet', $object);
}

private function getEntityChangeSet($entity, $method)
{
    $className = $this->getEntityName(get_class($entity));
    $hashId = $this->hashId($className, $entity->getId(), $method);
    $changeSetObj = $this->request->attributes->get('entityChangeSet');
    if (!$changeSetObj)
        return false;
    $changeSetObjId = $changeSetObj['id'];
    if ($changeSetObjId == $hashId)
        return $changeSetObj;
    return false;
}

private function checkIfUserRequest()
{
    $token = $this->container->get('security.token_storage')->getToken();
    if (!$token)
        return false;
    $user = $token->getUser();
    if ($user instanceof UserInterface)
        return true;

    return false;
}

private function isLog()
{
    try {
        return $this->request->attributes->has('logEntry');
    } catch (\ErrorException $e) {
        return false;
    }
}

private function getEm()
{
    return $this->container->get('doctrine')->getEntityManager();
}

private function generateObjectChangeSet($entity, $changeSet, $method)
{
    $className = get_class($entity);
    $className = $this->getEntityName($className);
    $id = $entity->getId();
    $hash = $this->hashId($className, $id, $method);
    $resp = array('id' => $hash, 'value' => $changeSet);
    return $resp;

}

private function hashId($className, $id, $method)
{
    $hash = $className . $id . $method;
    return $hash;
}

private function getLogEntry()
{
    if ($this->isLog())
        $this->request->attributes->get('logEntry');
    return false;
}

这适用于实体的简单值,例如名称地址等,但是当@manytoone或@manytomany带注释的属性发生更改时,例如,侦听器的preupdate方法不会触发。是否有这种属性的额外配置或我遗漏了什么?

答案

对于Collection,您可以使用:

$uow->getScheduledCollectionUpdates();
$uow->getScheduledCollectionDeletions();

如果它是PersistentCollection,您可以检索原始数据:

$entity->getSnapshot()

以上是关于学说跟踪多个实体关系的变化的主要内容,如果未能解决你的问题,请参考以下文章

学说中的关系

Symfony学说OneToAll关系

如何通过学说实体之间的 ID 建立一对一的关系

学说:通过这种关系找到了一个新的实体

推进学说代码片段

Symfony学说中的许多关系