封装PHP会话

时间:2016-02-12 09:41:13

标签: php session design-patterns

我的一位同事搬到了另一家公司,我得到了现有项目的源代码。 令我震惊的是代码看起来有多乱。我不是PHP开发人员,所以这可能是一个愚蠢的问题,但在我看来他使用$_SESSION太多了,我们在Sessions上遇到很多错误。我想知道封装$_SESSION并为每个使用自己的方法的值编写是否合适。

我在这段代码中看到的问题是他使用像这样的会话对象

$_SESSION['customer']['items'] = getItems() //returns an array
$_SESSION['article'][$Id]['name'] = utf8_decode[$received[1]];

因此,从我的观点来看,我会将所有内容存储在简单的Popos中,并将它们放入Session中。

所以客户的Popo看起来像这样

class CustomerPopo
{

    private $_id;

    private $_salutation;

    private $_name;

    private $_surename;

        public function getId()
    {
        return $this->_id;
    }

    public function setId($value)
    {
        $this->_id = $value;
    }

    public function getSalutation()
    {
        return $this->_salutation;
    }

    public function setSalutation($value)
    {
        $this->_salutation = $value;
    }

    public function getName()
    {
        return $this->_name;
    }

    public function setName($value)
    {
        $this->_name = $value;
    }

    public function getSurename()
    {
        return $this->_surename;
    }

    public function setSurename($value)
    {
        $this->_surename = $value;
    }

    function CustomerPopo() {

    }
}

我想像这样的SessionManager

class SessionManager
{

    private static function getValue($valueName)
    {
        $value = SessionManager::getValueFromSession($valueName);
        if (is_null($value)) {
             //Handle stuff and do further checks
        }
        return $value;
    }

    private static function getValueFromSession($valueName)
    {
        $value = null;
        if (isset($_SESSION[$valueName])) {
            $value = $_SESSION[$valueName];
        }
        return $value;
    }

    private static function setValue($valueName, $value)
    {
        $_SESSION[$valueName] = $value;
    }

    private static function clearValue($valueName)
    {
        if (isset($_SESSION[$valueName])) {
            unset($_SESSION[$valueName]);
        }
    }

    public static function getCustomer()
    {
        $customer = '';
        try {
            $customer = SessionManager::getValue('customer');
        } catch (Exception $e) {
            $customer = '';
        }
        return $customer;
    }

    public static function setCustomer($customer)
    {
        SessionManager::setValue('customer', $customer);
    }
}

有了这个,我可以消除由于客户/客户/客户这个词的不同拼写而产生的一些错误。 我想SessionManager会变大,因为我们在代码中有~30个Session变量。

我是否有一个设计模式可以实现这样的SessionManager而不会让它最终变得更糟?如上所述,我对PHP(还)不是很熟悉。

修改

由于该方法似乎有效,我如何处理我提到的30个Session变量?如果我对每个值都有一个set / get和一个明确的方法,我最终会得到60-90个方法

2 个答案:

答案 0 :(得分:1)

最好让一个对象封装对全局变量的访问,例如$_SERVER$_GET$_POST$_SESSION。 MVC架构中的常见做法是这样做。

该类是否应该具有IDE completition的方法?这实际上取决于你,但在我工作的工作场所的常见做法是不要使用它们,而是改为使用const字段的字符串标识符,然后用于指定全局$_SESSION中的索引通过对象变量,例如SessionManager

但即便如此,我可能会放弃静态方法,而是选择管理器的实例。使用静态方法的类可以防止打字错误,但不能修复全局状态问题,这在单元测试应用程序时可能是个大问题。

答案 1 :(得分:1)

我绝对同意像你的大学一样使用$ _SESSION很麻烦,因为你很难弄清楚会话中实际存储的内容。

在我看来,CustomerPopo是一个非常好的主意,因为它很容易理解可用的数据。此外,IDE也可以理解它,并在代码完成和检查时向您提供此信息。

我也喜欢你的SessionManager,但是我会尝试摆脱这些getValue / setValue函数并移动以移动像getCustomer / setCustomer这样的详细函数。 我猜你没有使用PHP框架。我想你应该看看它们,它们非常方便(例如Symfony或Yii2)。

最后一件事:始终记住,对于每个请求,将加载和解析存储在会话对象中的所有数据,不管您是否使用它。因此,如果您存储了大量仅用于特定请求的数据,则应考虑使用其他位置来存储它,如外部缓存。 此外,会话引入了状态,如果可能的话,应该避免使用状态。