如何在会话到期后修复Zend DbTableGateway读取/销毁无限循环?

时间:2016-07-15 13:58:53

标签: php session zend-framework

我有一个带有DbTableGateway的Zend \ Session Manager来处理会话。我的代码在another SO answer。但是每当会话到期时,我都会收到错误Fatal error: Maximum function nesting level of '100' reached, aborting! in [path]\vendor\zendframework\zend-db\src\Sql\AbstractExpression.php on line 40

我发现如何将xdebug嵌套级别更改为200,但我也达到了200限制。

Picture of the fatal error.

所以我在DbTableGateway-> read()和DbTableGateway-> destroy()之间有一个无限循环。我注意到错误中引用的2行每次调用另一个方法,但它是Zend代码所以我不想改变它。

它仅在会话到期后发生,而不是在我从数据库中删除包含会话信息的行时发生。发生这种情况后,当我查看表时,我注意到除了数据列之外,表中仍然存在该行。

id              name            modified    lifetime data
[random string] [session name]  1468587768  1440     -

因此看起来read()方法检查表中包含id和name的行,并找到该行,然后调用destroy(),它调用read()。我该如何解决这个问题?

另外,刷新页面可以解决用户的问题,但我不希望代码在用户处抛出异常并强制他们刷新页面。

1 个答案:

答案 0 :(得分:0)

这对我有用:创建一个扩展DbTableGateway的类并修改其destroy方法以检查是否存在行而不是调用read()函数。然后使用该类而不是DbTableGateway。

所以这里是新的保存处理程序类的代码:

id

以下是您如何更换DbTableGateway:

class MySessionSaveHandler extends DbTableGateway
{
    /**
     * Destroy session
     *
     * @param  string $id
     * @return bool
     */
    public function destroy($id)
    {
        // I removed "read" to prevent an infinite loop, and am using the first line of "read" instead to check if the row exists
        $rows = $this->tableGateway->select([
            $this->options->getIdColumn()   => $id,
            $this->options->getNameColumn() => $this->sessionName,
        ]);

        if (! (bool) $rows) {
            return true;
        }

        return (bool) $this->tableGateway->delete([
            $this->options->getIdColumn()   => $id,
            $this->options->getNameColumn() => $this->sessionName,
        ]);
    }
}