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