Symfony Doctrine EntityManager 没有正确刷新

Symfony Doctrine EntityManager not refreshing properly

我有一个棘轮 WebSocket 服务器,其 entityManager 是从后端初始化的。但是,如果由于 WebSocket 服务器 entityManager 的状态与后端不同,其中一个前端发生了某些更改,则新更改不会反映在 WebSocket 服务器提供的数据中。

为此,我在后端编写了一些侦听器,用于侦听这些实体中的更改,然后向服务器发送请求,如下所示:

public function postUpdate(Room $entity, LifecycleEventArgs $_)
{
    try {
        Loop::run(function() use ($entityName, $id) {
        $conn = yield connect('ws://localhost:8080');
        yield $conn->send(json_encode(['message' => $entityName, 'data' => ['duid' => $id]]));
        $conn->close();});
    } catch (Exception $e) {}
}

然后我在 WebSocket 服务器中获取实体并简单地刷新它,如下所示:

function onMessage(ConnectionInterface $from, $msg)
{
    try {
        $messageData = json_decode($msg);
        switch ($messageData->message) {
            case BookingSocketActions::ROOM_CHANGED_EVENT:
//                $room = $this->entityManager->getRepository('ResourcesBundle:Room')
//                                            ->find(['id' => $id]);
                $room = $this->entityManager->getRepository('ResourcesBundle:Room')
                                            ->findRoomDetailById($messageData->data->duid);
                // $this->entityManager->clear();
                $this->entityManager->refresh($room);
                break;
        }
    } catch (Exception $ex) {
        $from->send($ex);
    }
}

现在出现了一个奇怪的错误:在 WebSocket 服务器中刷新的 $entity 状态总是落后于实体的真实变化。假设我将 $entity->name 从“1”更改为“2”。

刷新后 $entity->name 在 WebSocket 服务器上仍然是“1”。只有当我再次将其更改为其他内容时,例如“3”,会不会变成“2”(刷新后)。如果我把它改成“4”,它就会变成“3”等等。

事件正在从后端正确触发,实体正在服务器上正确获取。只是 refresh() 仅适用于对 WebSocket 服务器的第二次请求(因此是第二次刷新),而不适用于第一次请求。

我什至尝试过 $entityManager->merge($entity); 但没有结果。

我正在使用 symfony 3.4、doctrine 2.7 和 ratchet 0.4.3。

Doctrine 使用 identity map

websocket 服务器是一个 守护进程,所有清理任务均由开发人员负责

使用

\Doctrine\ORM\EntityManager::find$lockMode 参数 = \Doctrine\DBAL\LockMode::NONE

\Doctrine\ORM\EntityManager::find

之前调用\Doctrine\ORM\EntityManager::clean方法

首先可能是触发检测更新变化的事件

如果您 postPersist 数据库中的实体不会发生变化。它会在 flush 发生之前触发。

您需要在 flush.

之后触发消息到套接字服务器

第二件事是确保 entityManager 实例分离并重新加载 room 实体实例。这可以用

来完成

$this->entityManager->getUnitOfWork()->clear(Room::class);

就在您再次查询实体之前

$this->entityManager->getUnitOfWork()->clear(Room::class);
$room = $this->entityManager
        ->getRepository('ResourcesBundle:Room')
        ->findRoomDetailById($messageData->data->duid);