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

Php 如何实例化数据库对象,以便在其他类中使用?,php,model-view-controller,variables,scope,Php,Model View Controller,Variables,Scope,我的应用程序遇到了架构问题。我已经推出了自己的(非常基本的)MVC,其中一个模型是数据库对象:classmysqldatabase{} 我希望在许多地方使用我的数据库对象,而不创建重复的实例。在我的控制器中,我声明了public$dbdb=newmysqldatabase 问题: 如何在我的其他类中使用$db——它们也都在控制器的\uu构造{}中实例化。。。我会在所有需要数据库连接的类的顶部声明global$db 我习惯于在全局范围中将全局变量声明为常规变量,然后使用global关键字引用全局范

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

我希望在许多地方使用我的数据库对象,而不创建重复的实例。在我的控制器中,我声明了
public$db\uuu构造{}
中,我有
$this->db=newmysqldatabase

问题:

如何在我的其他类中使用
$db
——它们也都在控制器的
\uu构造{}
中实例化。。。我会在所有需要数据库连接的类的顶部声明
global$db


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

我认为这里需要的是一个数据库对象的单例:)

有关更多详细信息,请参见此处:

使用php的示例singleton进行编辑:

<?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();
?>

您需要使用单例模式。他们在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);
    }

}

?>


我不会使用globals或Singleton模式(这本质上是一种全局模式),而是尝试找到一些替代方案。此外,您谈论的是数据库连接,通过使用单例模式,您可以说永远不会有多个数据库连接,而这在较小的应用程序中通常是正确的,因为它们越来越大,您将无法容纳多个连接

一旦你把某个东西变得全球化,那么你就失去了在哪里可以使用/修改它的自动约束。使用MVC视图不应用于显示数据以外的任何用途,通过使用全局/单例视图,开发人员可以不使用全局视图。然而,采用不同的设计,他们没有这种选择

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

如果模型从公共基类扩展而来,则可以将数据库对象作为静态变量传递给该类,该静态变量可以分配给构造中的任何新实例,也可以使用factory方法中的factory方法

<>这并不是说要不惜一切代价避免全球化或独裁者,但一定要试着考虑那些可能导致更为合理设计的替代方案。

如果您感兴趣,这里有一些关于单例模式的阅读:


还有更多…

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

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


我认为你这样做是错误的,你不应该从你的控制器那里对数据库执行任务

这意味着以下内容无效

class ControllerIndex extends Controller
{
    public function index()
    {
        $this->db->selectAll("table");
    }
}
应该有一个层将控制器与数据库接口分开,这就是模型的作用

您应该有一个models文件夹,其中包含用户、帖子、日志等操作的类

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
    }
}
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
  }

}
然后在主控制器中:

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);
    }
}
通过这种方式,您可以将加载程序引入子控制器的作用域:

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

希望这有帮助

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

class ModelLoader
{
    private $models = array();

    public function __get($model)
    {
        //load (/application/models/?.php) and initiate it here
        //Storing it in models array above
    }
}
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
  }

}

你也可以传递一个显式的模型对象,例如代表用户的对象,但这对你的项目来说可能太过分了。

@Tsadiq:这听起来正是我需要的,不幸的是,我在PHP培训中还没有走到这一步:p加载文档的时间到了……Singleton本质上是一个全局变量,在使用那个设计模式之前,我会考虑其他的选择。@ Shango,我用一个例子更新了我的答案,如果你想尝试一下的话:我不认为独生子是应该使用的。@雅各伯,如果你用静态调用,它不是真正的全局变量。在完整的OOP项目中,这真的很方便。@Jacob-那么另一种方法是创建需要数据库连接的类,即实例化数据库对象的类的扩展?我必须重新构建我的架构方法。。。这可能不是坏事…@Shango这绝对是个好选择。您还可以查看Factory方法()并查看它是否适合您的框架。应用这样的设计,防止使用数据库对象在控制器/模型之外,这似乎是合理的。我读到(大部分)您在这里给出的链接,我只注意到一件事:它们大部分涉及java、C++或其他软件编程。这不是真正的PHP。你的单身汉不会在你的记忆中活很多年。你从一开始。这些链接中的大部分内容都忽略了考虑“理论”方面的有用性。@Tsadiq它们都与面向对象编程语言有关,设计模式贯穿其中。Singleton设计模式来自著名的GangofFour书籍()。使用globals/singleton很方便,但过多地使用它们会降低代码的可读性、可维护性和可测试性。重要的是,在PHP框架中,您不应该将自己限制为只有一个数据库连接。@Tsadiq单例模式的目的是“确保