在类中使用mysqli对象,它应该存储在会话中——这是更好的方法


Use mysqli object in class, which should be stored in session - better approaches

我正在开发一个web应用程序,需要以多种语言提供。对于每个注册用户,我将选择的语言存储在数据库中。

此外,登录用户可以选择不同的语言,然后它应该在飞行中改变,这意味着网站应该重新加载并以新选择的语言显示。

翻译文件是带有键值对的简单CSV文件(目前大约有600对)。现在我实现了一个类Localization,它将所选语言的CSV文件加载到一个数组中。因为我认为最好不要在每个新页面上读取CSV文件,所以我将Localization对象存储在SESSION中。

现在的问题是,如果用户更改语言,我想更新数据库中选择的语言,还需要初始化支持的(可选择的)语言,这意味着我需要一个mysqli连接。

class Localization
{
    private $mysqli; // cannot be serialized and stored in session
    private $language;
    private $supportedLanguages;
    public function __construct($language, $mysqli) {
        $this->mysqli = $mysqli;
        $this->initSupportedLanguages();
        $this->setLanguage($language);
    }
    [...]
    public function setLanguage($language) {
        if ($language != $this->language)
        {
            if ($this->isSupportedLanguage($language))
            {
                $this->language = $language;                
                set_current_user_language($language, $this->mysqli);
                // loads the csv file into an array
                $this->loadTranslation($language);
            }
            else
            {
                echo "Language is not supported.";
            }
        }
    }
    private function initSupportedLanguages() {
        $query = "SELECT * FROM Sprache";
        if ($stmt = $this->mysqli->prepare($query))
        {
            $stmt->execute();
            $result = $stmt->get_result();
            foreach ($result as $row)
            {
                $this->supportedLanguages[$row['LanguageCode']] = $row['Name'];
            }
        }
        else 
        {
            echo "Could not create prepared statement.";
        }
    }
    [...]
}

一切正常,在创建对象的第一页。但是,如果用户访问下一页,则无法访问mysqli对象。

不幸的是,我发现,不可能序列化mysqli对象并将其存储在会话中,这导致了无法访问它的问题。

我现在要求以最佳实践方式处理数据库连接的方法。值得一提的是,其他函数使用添加了require_once功能的mysqli对象,但据我所知,在类中使用requireinclude是不可能的。

不能序列化资源对象,这是没有意义的。

在您的情况下,只要重新打开数据库连接,如果$mysqli == null .

因为我认为最好不要在每个新页面上读取CSV文件,所以我将本地化对象存储在SESSION中。

所以你让你的应用程序在每个新页面上读取一个序列化文件,这都是一样的。

所以你使你的应用程序更复杂,消耗更多的资源,让自己陷入麻烦而一无所获。

这就是为什么说过早优化是万恶之源。

感谢您的回复。我终于知道怎么做了。我仍然要使用require内的每个函数,我想查询数据库,但我可以忍受。另一个问题是,我使用require_once而不是require,这显然不起作用。

public function setLanguage($language) {
    if ($language != $this->language)
    {
        if ($this->isSupportedLanguage($language))
        {
            $this->language = $language;
            require(PATH_INCLUDES . '/db_connect.php');
            set_current_user_language($language, $mysqli);
            $this->loadTranslation($language);
        }
        else
        {
            echo "Language is not supported.";
        }
    }
}

在这些情况下,我使用的是类方法__sleep()__wakeup()

在类i的sleep方法中取消关闭连接的变量

public function __sleep()
{
    unset($this->_mysqli);
}

在唤醒方法中,我重新初始化连接,使其始终可用

public function __wakeup()
{
    $this->_mysql = new MysqliConnect(); //My custom mysqliwrapper
}

我希望这对你有帮助。

关于睡眠和觉醒的进一步阅读在这里