2011-10-04 190 views
0

我是OOP(PHP)的新手,刚刚遇到设计模式 - singleton。 我找到了一个使用mysqli(单例类)的DB类。我已经添加了一些自定义的方法(insert_id(),query()fetch_result()等)。PHP Singleton扩展类

然后我创建了一个名为UserTools的新类,我想扩展数据库类以使用之前创建的方法(query()fetch_result()等)。 但我得到这个错误:

Fatal error: Call to private Database::__construct() from invalid context in (...) when I try to create instance of the new class (User Tools).

我该怎么办?这是一个正确的结构吗?

+0

单身===做错了。它是一个糟糕的设计模式,应该始终避免。 – Raynos

回答

1

有几种方式来实现你想要什么。

其中之一是:

class UserTools { 
    private $db; 
    function __construct() { 
     $this->db = Database::db_connect(); 
    } 

    function login() { /* ... */} 
} 

虽然这将是更好的数据库实例直接传递给构造函数是这样的:

class UserTools { 
    private $db; 
    function __construct($db) { 
     $this->db = $db; 
    } 

    function login() { /* ... */} 
} 

// Usage 
$userTools = new UserTools(Database::db_connect()); 

如果你真懒,你可以只修改数据库类和公共构造函数:

class Database { 
    /* ... */ 
    public function __construct(){/* ... */} 
    /* ... */ 
} 

class UserTools extends Database {/* ... */} 

但我真的不鼓励你使用后者。这是非常糟糕的代码,从逻辑的角度来看它没有任何意义。您的UserTools类使用一个数据库实例。它是而不是一个数据库。

+0

如果我使用第二个,是否创建了数据库类的新实例? (它工作正常,顺便说一句,谢谢) –

+1

编号由于'数据库'是一个单身人士,它将始终返回相同的实例。 – Alfwed

+0

非常感谢!这是我的一天。 = d –

0

你可以写类似

class UserTools extends DB { 
    .... 
} 

一个简单的例子就继承在PHP中:

class A { 
    public $a; 
    public function set_a($new_a) { $this->a = $new_a; return $this; } 
    public function get_a() { return $this->a; } 
} 

class B extends A { 
    public $b; 
    public function set_b($new_b) { $this->b = $new_b; return $this; } 
    public function get_b() { return $this->b; } 
} 

$objb = new B(); 

$objb->set_a("Some Value")->get_a(); //Some Value 
+0

我做到了。但我想在它做这样的事情: 公共功能登录($ un,$ pass){ //在这里使用一个DB的方法? } –

+0

'extends'关键字将导致所有函数和实例变量从父类('DB')类继承到子类'UserTools'类,您可以(也应该)另外添加更多类! –

+0

你确定扩展一个DB单例的User类是正确的吗?逻辑上,特别是 –

1

这是我的理解,只有protectedpublic方法和变量通过扩展继承,而不是私人的。尝试将您的方法/变量从private更改为protectedpublic对所有人都是可见的。

欲了解更多信息,请参见:PHP Visibility (Manual)

编辑

了解Singleton模式。它被称为'单身人士',因为只有一个类的实例预计。因此,大多数实现单例模式的类将构造函数定义为私有的,以限制您创建多个类。

要创建一个单例的实例,大多数类定义了某种getInstance静态方法,它是公共的。这个公共方法调用私有构造函数,该构造函数可能会设置标志,指​​示该类已被实例化,以防止进一步尝试实例化该类。 getInstance方法返回调用构造函数的结果,实质上是类的实例。

+0

+1这就是错误说 – Xeoncross

+0

好吧,我张贴从我的代码下面的链接(pastebin链接)。属性和构造函数是私有的,其他的都是公共的。 但我不明白一个瘦。当我扩展课程时,我是否会创建一个新实例? –

+0

不。您在定义类时扩展了一个类。在使用关键字'new'之前,您不要创建一个类的实例。想象一下,为建筑物采取一套蓝图,并用透明胶带为另一个房间添加蓝图。当你使用'new'关键字时,你实际上'建造'了建筑物。 –

0

在大多数情况下,单例模式通过将构造函数定义为私有(即private function __construct())阻止实例化Singleton类。

所以,如果您尝试实例化您的自定义类或您正在扩展的原始类,您将获得上述消息。您应该创建一个不同的类或定义并使用您的函数作为静态(例如public static function query($sql, $dbconnection))。

http://php.net/manual/en/language.oop5.patterns.php