如何实例化我的数据库对象,以便在其他类中使用?

时间:2011-03-06 23:17:43

标签: php model-view-controller variables scope

我的应用程序遇到了架构问题。我已经推出了自己的(非常基础的)MVC,我的一个模型是一个数据库对象:class MySQLDatabase { }

我有很多地方想要使用我的数据库对象,而不会创建重复的实例。在我的控制器内部,我已声明public $db;并在__construct { }$this->db = new MySQLDatabase;

问题:

如何在我的其他类中使用$db - 它们都在控制器的__construct { }中实例化...我会在所有我的顶部声明global $db需要数据库连接的类?

我习惯在全局范围内将全局变量声明为常规变量,然后使用global关键字引用全局范围...我不确定这是否适用于在一个班级(我的控制员。)

6 个答案:

答案 0 :(得分:4)

我会远离使用全局变量或Singleton模式(无论如何都是一个全局模式),并尝试找到一些替代方案。此外,您正在谈论数据库连接,通过使用Singleton模式,您说永远不会有多个数据库连接,而在较小的应用程序中通常是这样,因为它们变大,您将无法容纳多个连接。

一旦你创造了一些全局性的东西,你就失去了它可以被使用/修改的地方的自动约束。使用MVC时,除了显示数据之外,不应该使用视图,通过使用global / singleton,开发人员可以不使用全局变量。鉴于设计不同,他们没有这种选择。

你提到你已经创建了自己的MVC框架,所以我想你想要使用它的类是你的模型吗?如果他们在其他任何地方,请纠正我。

如果模型从公共基类扩展,那么您可以将数据库对象作为静态变量传递给该类,该静态变量可以分配给构造中的任何新实例或在工厂方法中使用工厂方法。

这并不是说应该不惜一切代价避免全球或单身,但绝对要考虑可能导致整洁设计的替代品。

如果您有兴趣,可以阅读Singleton模式:

还有更多......

答案 1 :(得分:3)

如果我理解正确,你有一个实例化数据库对象的控制器,它还负责实例化其他类。如果是这样,您可以实现某种形式的依赖注入,或者在其他类的构造函数中传递db对象,或者创建一个setter方法。

关于这个主题的好博客文章:

http://www.potstuck.com/2009/01/08/php-dependency-injection/

答案 2 :(得分:2)

我认为你以错误的方式解决这个问题,你不应该从你的控制器那里对问题进行处理。

这意味着以下内容无效。

class ControllerIndex extends Controller
{
    public function index()
    {
        $this->db->selectAll("table");
    }
}

应该有一个层将您的控制器与数据库接口分开,这就是Model的用武之地。

您应该有一个模型文件夹,其中包含所采取操作的类,例如用户,帖子,日志记录等。

class Users_Model extends Model
{
    public function getUser($id)
    {
    }
}

模型类应该是系统核心的一部分,并且应该扩展您的数据库类,这样在您的主控制器中,您应该通过ModelLoader类加载模型。

例如:

class ModelLoader
{
    private $models = array();

    public function __get($model)
    {
        //load (/application/models/?.php) and initiate it here
        //Storing it in models array above
    }
}

然后在你的主控制器中:

class Controller
{
    private $model;

    public function __construct()
    {
        $this->model = new ModelLoader;
    }
}

这样你就可以将你的加载器带入子控制器的范围:

class Controller_index extends Controller
{
    public function index()
    {
        $user = $this->model->users->getUser(22);
    }
}

希望这有帮助!

答案 3 :(得分:1)

我认为你需要的是一个单独的数据库对象:)

请点击此处了解详情:http://en.wikipedia.org/wiki/Singleton_pattern

使用示例单例编辑php:

<?php
class UniqueObject {

    private $_uniq = null;

    //private cause you don't want to instanciate the classic way
    private function __construct() {
        //...
    }

    //check if unique object exists or not, then return it
    public static function uniq() {
        if(!self::$_uniq)
            self::$_uniq = new UniqueObject();

        return self::$_uniq;
    }
}

//call your unique object whenever you need it
UniqueObject::uniq();
?>

(已经很晚了,我希望我没有犯任何错误:))

答案 4 :(得分:1)

不要使用单身人士。显式传递数据要好得多。例如:

abstract class Controller {
  private static $conn; // could be an array for multiple connections
  final protected function getDBConnection() {
    if (!$this->conn) {
      $this->conn = new DBConnection();
    }
    return $this->conn;
  }
  abstract public function process(Request $r);
}

class HomePageController extends Controller {

  public function process(Request $r) {
    $results = $this->getDBConnection()->query('SELECT stuff FROM foo;');
    // do stuff with $results
  }

}

你也可以有一个明确的模型对象,例如:代表用户的那个,但这可能对你的项目来说太过分了。

答案 5 :(得分:0)

您需要使用单例模式。他们在php文档中给出了示例

<?php
class Example
{
    // Hold an instance of the class
    private static $instance;

    // A private constructor; prevents direct creation of object
    private function __construct() 
    {
        echo 'I am constructed';
    }

    // The singleton method
    public static function singleton() 
    {
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }

        return self::$instance;
    }

    // Example method
    public function bark()
    {
        echo 'Woof!';
    }

    // Prevent users to clone the instance
    public function __clone()
    {
        trigger_error('Clone is not allowed.', E_USER_ERROR);
    }

}

?>

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