4

我有一个类userdb,我在其中声明了一个返回与数据库的连接的函数:

return $con = new PDO("mysql:host=$host;dbname=$db", $user, $pass);

我有各种功能,甚至跨其他类,我必须访问$con(例如,传递查询或获取数据),但我不能访问这个变量。

有没有更好的方法来定义和使用数据库类?请记住,我还有其他需要访问该课程的userdb课程。

4

7 回答 7

3

我建议您为此使用单例模式

在您的 userdb 类中,声明一个静态属性$scon

private static $scon;

并假设您上面提到的函数是 named createConnection(),您应该创建以下静态方法:

public static function connect() {
    if (empty(self::$scon)) {
         $instance = new userdb();
         self::$scon = $indtance->createConnection(); 
    }
    return self::$scon; 
}

有了这个,您将能够通过以下方式访问您的 userdb 连接:

userdb::connect();

此外,由于这是一个单例,它只会连接一次,并使用该连接直到脚本结束。

注意(关于依赖注入):由于@KevinM1 提到了Dependency Injection,我必须补充一点,它也是一种可能的、非常优越的解决方案。它要求您使用数据库连接为所有类创建 setConnection() 方法(或抽象祖先),并且在这些类的实例化期间,您可以使用工厂将所需的连接添加到对象。这应该包含在一些类加载器中,这与您的模型结构不同。

看,小菜一碟,但对于小而快的开发,我会坚持使用 Singleton ;)

于 2012-10-19T11:58:53.070 回答
1

如果它在一个类中,将实例存储在一个属性中:

class userDB
{

   public $dbCon = false;//because you want to access the instance 
   //from outside the class, I have made the property public

    function connect()
   {

      $con = new PDO("mysql:host=$host;dbname=$db", $user, $pass);

      $this->dbCon = $con;

   }


}

要在课堂外访问它:

$useDBInstance->dbCon;

于 2012-10-19T11:52:07.920 回答
0

好吧,$con 已经是一个对象,因为它正在实例化一个新的 PDO 对象。除非您尝试向 PDO 对象添加功能,否则包装它是没有意义的。

也就是说,与其他对象共享您的 userdb/PDO 对象(取决于您是否坚持使用包装器)的最佳方法是使用Dependency Injection。这是一个花哨的术语,用于将您的数据库传递给任何需要它的对象。由于对象在 PHP 中默认通过引用传递,如果您首先创建 db 对象,则所有接收它作为构造函数/方法参数的对象都将使用同一个实例。

编辑:链接到依赖注入实现

EDIT2:澄清小项目中的DI-

正常的 DI 模式通常需要一个称为 DI Container 的特殊对象。这是一个特殊用途的对象,它会自动将依赖注入到需要它的对象中。对于小型项目,这是矫枉过正的。DI 的简单、低复杂度版本很简单:

class SomeClass {
    protected $db;

    public function __construct($db) {
        $this->db = $db;
    }
}

class SomeClass2 {
    public function SomeMethod($db) {
        // do something with the db
    }
}

$db = new PDO(/* connection string */);

$obj = new SomeClass($db, /* other constructor args */);

// or

$obj2 = new SomeClass2(/* constructor args */);
$obj2->someMethod($db, /* method args */);

神奇的是,由于在 PHP 中对象默认通过引用传递,$obj 和 $obj2 使用相同的数据库连接。

整个想法是不要通过使用静态方法来破坏范围或封装,并确保类和它们的方法预先知道它们需要什么才能工作。

单身人士则完全相反。它们是通过绕过作用域的静态方法访问的,并且由于它们被调用而不是传递,它们永远不会出现在方法签名中,因此任何不熟悉代码的人都不会意识到隐藏的要求。 即使是 Erich Gamma(帮助编纂单例模式的人之一)也对此感到遗憾

我赞成放弃 Singleton。它的使用几乎总是一种设计气味。

在 PHP 中,没有共享内存的概念,并且脚本每次请求执行一次,想要使用单例的唯一原因是可以轻松访问单个资源。由于对象是通过引用传递的,一个实例自然可以与多个对象共享。从那里开始,它是关于良好的设计和授权。

于 2012-10-19T11:56:55.210 回答
0
return $this->con 

从你的班级以这种方式返回并以这种方式调用它..

$this->classObject->con->prepare();
于 2012-10-19T11:52:00.637 回答
0

查看我的视频教程 + 代码以获得全局 PHP 变量的替代方案。

你在那里做错了。如果您计划在函数中创建连接并将其存储在那里,则需要使用静态变量。否则,您将继续连接每个函数调用。我的教程解释了常规函数中静态变量的这个概念。

如果还不够清楚,请告诉我,我会尽力回答您的问题。

这是一些伴随此的代码:

/**
* Arguments are none or [$db, [$user, [$pass[, $host]]]].
*
* @return PDO
*/
function PdoDb(){
    static $con = null; // I'm explicit :)
    // Every time you pass Arguments you reconnect
    if(func_num_args()){
        $args = array_pad(func_get_args(), 4, null);
        list($db, $user, $pass, $host) = $args;
        if(empty($user)) $user = 'root';
        if(empty($host)) $host = 'localhost';
        $con = new PDO("mysql:host={$host};dbname={$db}", $user, $pass);
    }
    if(empty($con)){
        trigger_error('Provide arguments to connect first.', E_USER_ERROR);
        return null;
    }
    return $con;
}

// First run (provide arguments to connect)
PdoDb($db, $user, $pass, $host);
PdoDb($db); // Works if you connect root@localhost with no password

// From here on (it returns PDO)
PdoDb()->DoStuffOfPdo();

一旦连接,它就会保持这种状态。但是您可以通过提供参数随意重新连接。

于 2012-10-19T12:18:32.803 回答
-2

使用单例类实现

class connectdb
{
    protected static $_instance = NULL;


    private function __construct()
    {
    }

    public function getinstance()
    {
     if (null === self::$_instance) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }
    public function connect()
    {
     $this->connection =new PDO("mysql:host=$host;dbname=$db", $user, $pass);


    }

}
于 2012-10-19T11:57:59.693 回答
-4

要在类函数或独立函数中使用变量,您需要放置一个全局关键字

$conn=mysql_connect(); 
   function test(){
      global $conn;
   }

now$conn将在 test 函数的范围内可用,并且在脚本顶部定义时将在任何地方可用。对于类,您也需要做同样的事情,创建一个类的对象并在函数中将其声明为全局

于 2012-10-19T11:55:43.147 回答