当前位置: 首页 > 面试题库 >

在类中使用全局变量

欧阳永宁
2023-03-14
问题内容

我正在尝试创建一个分页类,并使用该类外部的变量。

但这给了我致命错误“在非对象上调用成员函数query()”。

这是索引文件:

$db = new DB_MySQL("localhost", "root", "", "test"); // connect to the database
include_once("pagi.php");

$pagination = new pagi();
$records = $pagination->get_records("SELECT * FROM `table`");

这是pagi.php文件:

class pagi {

    public function get_records($q) {
        $x = $db->query($q);
        return $db->fetch($x);
    }

}

是否可以在类内部使用该变量,而无需在类内部创建新变量?


问题答案:

解决此问题的正确方法是将数据库对象注入另一个类(依赖项注入):

$db = new DB_MySQL("localhost", "root", "", "test"); // connect to the database
include_once("pagi.php");

$pagination = new Paginator($db);
$records = $pagination->get_records("SELECT the, fields, you, want, to retrieve FROM `table`");

class Paginator
{    
    protected $db;

    // Might be better to use some generic db interface as typehint when available
    public function __construct(DB_MySQL $db)
    {
        $this->db = $db;
    }

    public function get_records($q) {
        $x = $this->db->query($q);
        return $this->db->fetch($x);
    }

}

解决该问题的另一种方法是将数据库类的实例注入使用它的方法中:

$db = new DB_MySQL("localhost", "root", "", "test"); // connect to the database
include_once("pagi.php");

$pagination = new Paginator();
$records = $pagination->get_records("SELECT the, fields, you, want, to retrieve FROM `table`", $db);

class Paginator
{
    public function get_records($q, DB_MySQL $db) {
        $x = $db->query($q);
        return $db->fetch($x);
    }

}

您选择哪种方法取决于情况。如果只有一个方法需要数据库的实例,则可以将其注入该方法,否则我会将其注入到类的构造函数中。

另请注意,我已将您的班级从重命名pagiPaginator。Paginator是该类的更好的名字恕我直言,因为其他人(重新)查看您的代码很明显。另请注意,我已将首字母大写。

我所做的另一件事是更改查询以选择要使用的字段,而不是使用“通配符”
*。出于同样的原因,我也更改了类名:(重新)查看代码的人员将确切知道将检索哪些字段,而无需检查数据库和/或结果。

更新资料

因为答案引起了关于为什么我要走依赖注入途径而不是声明对象的讨论,所以我想global阐明为什么我要对global关键字使用依赖注入:当您有如下方法时:

function get_records($q) {
    global $db;

    $x = $db->query($q);
    return $db->fetch($x);
}

当您在某处使用上述方法时,不清楚使用的类或方法取决于$db。因此,这是一个隐藏的依赖关系。上面的代码不好的另一个原因是因为您已经将$db实例(因此DB_MySQL)类与该方法/类紧密耦合。如果您需要在某个时候使用2个数据库怎么办。现在,您将需要遍历所有代码才能更改global $dbglobal $db2。您永远不必为了切换到另一个数据库而更改代码。因此,您不应该这样做:

function get_records($q) {
    $db = new DB_MySQL("localhost", "root", "", "test");

    $x = $db->query($q);
    return $db->fetch($x);
}

同样,这是一个隐藏的依赖关系,并将DB_MySQL类与方法/类紧密耦合。因此,不可能正确地对Paginator类进行单元测试。Paginator您不仅要同时测试单元(课程),还要同时测试DB_MySQL课程。如果您有多个紧密耦合的依赖关系,该怎么办?现在,您突然用所谓的单元测试测试了几个类。因此,在使用依赖注入时,您可以轻松切换到另一个数据库类,甚至可以切换到一个模拟类来进行测试。除了只测试一个单元的好处(您不必担心由于依赖性而导致的错误结果)之外,它还可以确保测试能够快速完成。

某些人可能认为Singleton模式是访问数据库对象的正确方法,但是应该很清楚,在阅读了以上所有内容之后,Singleton基本上只是另一种制作方法global。它的外观可能有所不同,但具有与相同的特征,因此也存在相同的问题global



 类似资料:
  • 问题内容: 如何与线程共享全局变量? 我的Python代码示例是: 我不知道如何让两个线程共享一个变量。 问题答案: 您只需要在中声明为global ,这样就无需修改该函数本地的。 在中,您不需要执行任何特殊操作,只要您不尝试修改的值(这将创建一个局部变量以遮盖全局变量;请在需要时使用)>

  • 问题内容: 我刚刚创建了angularJS应用程序。 这是我的 index.html app.js 我有login.html,register.html和forgotpassword.html,home.html。每个人在单独的文件中都有单独的控制器。login.js,register.js,forgot.js,home.js。 login.js 同样,我在其他控制器中也有post方法。 我想要的

  • 问题内容: 例如,我想使用自定义记录器: 如何在其他模块而不是console.log中使用此记录器? 问题答案: 大多数人建议不要使用全局变量。如果要在不同模块中使用相同的记录器类,则可以执行此操作 logger.js foob​​ar.js 如果确实需要全局变量,则可以执行以下操作:

  • 问题内容: 如何在函数中创建或使用全局变量? 如果在一个函数中创建全局变量,如何在另一个函数中使用该全局变量?我是否需要将全局变量存储在需要对其进行访问的函数的局部变量中? 问题答案: 你可以在其他函数中使用全局变量,方法是像在分配给它的每个函数中一样声明它: 我想这是因为全局变量是如此危险,因此Python希望通过显式要求使用关键字来确保您真正知道这就是要使用的内容。

  • 本文向大家介绍使用配置类定义Codeigniter全局变量,包括了使用配置类定义Codeigniter全局变量的使用技巧和注意事项,需要的朋友参考一下 CodeIgniter中公共函数不能追加,可以通过 helper 辅助函数实现。 创建 common_helper.php 文件,定义所需公共函数,存放至 application/helpers 目录中。 在 application/config/

  • 问题内容: 我尝试了各种方式,但似乎没有任何效果。这是我的詹金文件。 阶段脚本的输出(“初始化变量”)没有任何作用,它没有设置全局变量ZIP_NODE的值: 然后我们进入阶段(代码-Build),我们没有得到ZIP_NODE的值。请参阅22:34:17的echo声明 感谢@awefsome,我有一些观察,我想补充一下细节:当我使用下面的代码时,我得到了想要的输出,即ZIP_NODE的正确值: 但是