相当有趣的事实,我刚刚发现,而搞乱了WebSocket应用程序,我现在使用Symfony 4.1和https://github.com/GeniusesOfSymfony/WebSocketBundle(这是建立在PHP棘轮)。
我想使用$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却得到了?
3条答案
按热度按时间flvtvl501#
这是正确的,也是ORM的预期行为。这是减轻数据库负载的一种方法。
这是有据可查的,但大多数时候我们只是跳到例子,错过了它。:)
由于PHP的生命周期,在应用程序中通常不会注意到这一点。一个请求进来,一个响应出去,然后一切都关闭了。下一个请求以一个干净的石板开始。
如果使用WebSocket,这种情况永远不会发生,PHP只是永远运行(不是真的,但理想情况下),棘轮响应事件。
(OFF:查看PHP-PM......他们之所以能够大幅增加每秒的请求,是因为他们颠覆了PHP的生命周期)。
锁定模式是一种解决方案,但您也可以调用
$em->refresh($entity)
,它触发从db重新加载。编辑:文档https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/working-with-objects.html#entities-and-the-identity-map
bnl4lu3b2#
其实我自己也想明白了。
Doctrine的EntityManager
find(...)
方法实际上将结果缓存在一个实体的名称和条目ID下名为$unitOfWork
的私有字段中。每次尝试使用
$em->find(...)
查找内容并成功时,结果将存储在$this->unitOfWork
中,如果再次尝试获取相同的内容,它将从缓存中加载。"symfony/orm-pack": "^1.0"
和"doctrine/orm": "^2.5.11"
就是这种情况调用
$repository->find(2, LockMode::NONE);
可以解决这个问题。mspsb9vt3#
我将php ratchet库与pimcore一起使用,并通过在套接字的"onOpen"事件上重新连接到数据库来修复此问题。
下面是代码:
希望这个有用。