0

我为 PDO 创建了一个单例模式,问题是当我使用它时,我有一个无限循环,例如,这样做:

$db=Db::fetch_instance(); 
$product = $db->query(<query>);

我有这个错误:

Fatal error: Maximum function nesting level of '100' reached, aborting!

我的课是这个:

class Db {

    //START OF SINGLETON PATTERN

    private static $PDOInstance;

    public static function fetch_instance() {
        try {           
            if(empty(self::$PDOInstance)){                      
                self::$PDOInstance = new Db();                  
            }
            return self::$PDOInstance;
        } catch (Exception $e) {
                     <something>
        }
    }

    private function __construct() {
            return new PDO("something");
    }

    //START OF DECORATOR PATTERN

    public function beginTransaction() {
        .......
    }

    public function query($statement) {
        return self::$PDOInstance->query($statement);
    }

      ........

为什么这个循环?,我没有看到任何循环。

4

3 回答 3

4

这个错误对我来说很清楚,你的方法query正在调用自己。

public function query($statement) {
    return self::$PDOInstance->query($statement);
}

这是因为您的单例有错误,您应该将代码更改为:

public static function fetch_instance() {
    try {           
        if(empty(self::$PDOInstance)){                      
            self::$PDOInstance = new PDO("something");
            return self::$PDOInstance;
        }
    } catch (Exception $e) {
                 <something>
    }
}

private function __construct() {

}

小心,构造函数并不意味着返回任何东西,你正在分配self::$PDOInstance一个新Db对象的实例!

更新

顺便说一句,这里更接近您想要做的事情:

class Db {

    // START OF SINGLETON PATTERN

    private static $instance;

    private $PDOInstance;

    public static function fetch_instance() {
        try {
            if (empty(self::$PDOInstance)) {                      
                self::$instance = new Db();
            }

            return self::$instance;
        } catch (Exception $e) {
            // <something>
        }
    }

    private function __construct() {
        return $this->PDOInstance = new PDO("something");
    }

    // START OF DECORATOR PATTERN

    public function beginTransaction() {
        // .......
    }

    public function query($statement) {
        return $this->PDOInstance->query($statement);
    }

}

$PDOInstance是私有的并且绑定到您的单例,$instance是静态的并且将包含Db该类的唯一实例。您的构造函数在这里负责初始化您$PDOInstance,然后您可以将其用作属性$this->PDOInstance

于 2013-04-03T21:53:53.860 回答
2

__construct() 不应该有返回值。

删除它,让你fetch_instance()像这样:

public static function fetch_instance()
{
    if (!self::$PDOInstance) {
        self::$PDOInstance = new PDO();
    }

    return self::$PDOInstance;
}
于 2013-04-03T21:54:05.413 回答
0

你的单例模式是错误的。如果您希望“Db”类的实例是单例的,您应该做的是将唯一且唯一的“Db”实例存储Db::fetch_instance()到静态私有属性中。这个实例应该有一个 PDO 实例。

class Db {

//START OF SINGLETON PATTERN

private static $dbInstance;

private $PDO;

public static function fetch_instance() {
    try {           
        if(empty(self::$dbInstance)){                      
            self::$dbInstance = new Db();                  
        }
        return self::$dbInstance;
    } catch (Exception $e) {
                 <something>
    }
}

private function __construct() {
        $this->PDO = new PDO("something");
}

//START OF DECORATOR PATTERN

public function beginTransaction() {
    .......
}

public function query($statement) {
    return $this->PDO->query($statement);
}

  ........

请注意,实际上没有必要使用单例。

在一般层面上,单例越来越多地被认为是一种反模式。它们确实使代码的可测试性很差,应该避免。

第二:PHP 中总是有不止一个实例,因为每个请求都在它自己的变量空间中运行。所以每个并发请求有一个实例,而不是每个服务器一个实例。这意味着所有这些实例都同时连接到数据库。

第三:PHP 中的 mysql 扩展可防止程序多次连接到具有相同凭据的同一个数据库。

第四:虽然目前可能没有需求,但会有一段时间同时存在多个数据库。这是将数据库连接创建为单例的时候会受到最大的伤害。

所以我真的建议不要将单例模式用于数据库连接。你一无所获,却失去了很多。

于 2013-04-03T22:06:43.873 回答