php websocket 棘轮不从学说中获取最新数据

php websocket ratchet doesn't fetch newest data from doctrine

我刚刚在弄乱 WebSocket 应用程序时发现了一个非常有趣的事实,我现在正在使用 Symfony 4.1 和 https://github.com/GeniusesOfSymfony/WebSocketBundle(基于 PHP Ratchet 构建)。

我想使用 $repository->find(2); 定期从 MySQL 数据库中获取最新数据以进行测试,但它总是返回相同的结果,即使我在订阅 WebSocket 通道时正在更改数据.

在弄乱代码并哭了好几个小时后,我发现出于某种原因,Doctrine 正在缓存结果(或者我认为它就是这样做的)。

为了检验我的理论,我使用以下代码创建了一个处理从数据库中获取数据的服务:

/**
 * @return mixed
 * @throws \Doctrine\DBAL\DBALException
 */
public function fetchNewest()
{
    $stmt = $this->em->getConnection()->prepare('SELECT * FROM test WHERE id=2');
    $stmt->execute();

    return $stmt->fetch();
}

出于某种原因,这奏效了。谁能解释为什么 find(2) 方法没有得到最新数据而原始 SQL 得到了?

实际上我自己设法解决了这个问题。

Doctrine 的 EntityManager find(...) 方法实际上将结果缓存在实体名称和条目 ID 下名为 $unitOfWork 的私有字段中。

每次您尝试使用 $em->find(...) 查找内容并成功时,结果将存储在 $this->unitOfWork 中,如果您再次尝试获取相同的内容,它只会从缓存中加载。

   // Check identity map first
    if (($entity = $unitOfWork->tryGetById($sortedId, $class->rootEntityName)) !== false) {
        if ( ! ($entity instanceof $class->name)) {
            return null;
        }

        switch (true) {
            case LockMode::OPTIMISTIC === $lockMode:
                $this->lock($entity, $lockMode, $lockVersion);
                break;

            case LockMode::NONE === $lockMode:
            case LockMode::PESSIMISTIC_READ === $lockMode:
            case LockMode::PESSIMISTIC_WRITE === $lockMode:
                $persister = $unitOfWork->getEntityPersister($class->name);
                $persister->refresh($sortedId, $entity, $lockMode);
                break;
        }

        return $entity; // Hit!
    }

这是"symfony/orm-pack": "^1.0""doctrine/orm": "^2.5.11"

的情况

编辑:

调用$repository->find(2, LockMode::NONE);解决了问题。

这是正确的,并且是 ORM 的预期行为。这是一种减轻数据库负载的方法。

它有很好的文档记录,但大多数时候我们只是跳到示例而错过了它。 :)

您通常不会在应用程序中注意到这一点,因为 PHP 生命周期。一个请求进来,一个响应出去,然后一切都关闭了。下一个请求从零开始。

如果你使用 websocket,这永远不会发生,PHP 永远运行(不是真的,但理想情况下),并且棘轮响应事件。

(OFF: 查看 PHP-PM...他们已经能够达到请求/s 的急剧增加,因为他们颠覆了 PHP 生命周期)。

锁定模式是一种解决方案,但您也可以调用 $em->refresh($entity),这会触发从数据库重新加载。

编辑:文档https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/working-with-objects.html#entities-and-the-identity-map