单例类是否链接到PHP中的会话?

时间:2012-02-21 12:31:30

标签: php oop class session singleton

我有一个单例类,我正在使用CAPTCHA系统来生成代码和图像等。

我在html表单中包含一个脚本,用于加载类单例,生成代码和图像,并将其输出到浏览器。然后我有另一个脚本来验证和处理表单。这会加载类单例以检索先前创建的实例,并调用该函数来验证代码。

我遇到的问题是,当我验证表单时,表单上生成的代码已经更改或者在我验证它时完全不存在!

我还没有在php会话中启动或存储任何内容,但是在加载表单的页面上创建了一个会话。单例的实例是否以某种方式链接到该会话?如果它是一个命名会话或什么?

或者......我完全误解了单身人士课程的工作原理吗?在哪种情况下,任何人都可以告诉我如何检索在html表单页面上创建的类的实例,以便再次使用它来验证表单处理脚本中的代码? - 也许告诉我应该如何使用单身人士!

非常感谢。

3 个答案:

答案 0 :(得分:2)

单身人士在请求期间存在,而不是会话的持续时间。

单例的想法是在所有包含的脚本中提供对同一对象的访问,而不必使用任何显式初始化逻辑。

因此,第一次调用$foo = MyObject::singleton()会创建一个新的MyObject,但第二次调用只会返回该对象而不是创建一个新对象。这对于访问外部资源(如数据库和文件)的类非常有用。

答案 1 :(得分:2)

  

或者......我完全误解了单身人士课程的工作原理吗?

部分。由于PHP没有类似ASP.NET的应用程序变量,因此只要请求执行,PHP中的对象就会生效,除非序列化(例如在会话中)。

作为您的问题的解决方案:将验证码(或验证码类,有点过分杀戮)保存在会话变量中,例如$_SESSION['captcha']

答案 2 :(得分:1)

不,不是。

当代码执行结束时,您必须序列化单例对象并将其存储到会话中。显示下一页时,您可以从会话中反序列化对象。

当您将对象分配给会话时,PHP会自动序列化/反序列化对象。

这只能在您的单身人士不使用外部资源的链接标识符的前提下才能正常工作。

以下是从comments in PHP docs

获取的示例实现
class SessionSingleton {
    /**
     *    Returns an instance of the singleton class.
     *    @return    object        The singleton instance
     */
    public static function _instance()
    {
        // Start a session if not already started
        Session::start();

        if ( false == isset( $_SESSION[ self::$_singleton_class ] ) )
        {
            $class = self::$_singleton_class;
            $_SESSION[ self::$_singleton_class ] = new $class;
        }

        return $_SESSION[ self::$_singleton_class ];       
    }

    /**
     *    Destroy the singleton object. Deleting the session variable in the
     *    destructor does not make sense since the destructor is called every
     *    time the script ends.
     */
    public static function _destroy()
    {
        $_SESSION[ self::$_singleton_class ] = null;
    }

    /**
     *    Initialize the singleton object. Use instead of constructor.
     */
    public function _initialize( $name )
    {
        // Something...
    }

    /**
     *    Prevent cloning of singleton.
     */
    private function __clone()
    {
        trigger_error( "Cloning a singleton object is not allowed.", E_USER_ERROR );
    }

    private static $_singleton_class = __CLASS__;
}