单例和PDO的无限循环

时间:2013-04-03 21:42:30

标签: php pdo singleton

我为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);
    }

      ........

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

3 个答案:

答案 0 :(得分: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

的属性

答案 1 :(得分:2)

__ construct()不应该有返回值。

将其删除,并将fetch_instance()改为:

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

    return self::$PDOInstance;
}

答案 2 :(得分:0)

你的单身人士模式是错误的。如果希望类“Db”的实例为单例,则应该执行的操作是将Db::fetch_instance()中唯一的“Db”实例存储到静态私有属性中。然后,此实例应具有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扩展阻止程序多次使用相同的凭据连接到同一个数据库。

第四:虽然目前可能没有需要,但有时会有多个数据库在同一时间。这是将数据库连接创建为单例的时间最多的时间。

所以我真的建议不要使用单例模式进行数据库连接。你什么都得不到,但却失去了很多。