【问题标题】:php Use class function that queries db inside another classphp 使用在另一个类中查询 db 的类函数
【发布时间】:2013-04-03 17:18:37
【问题描述】:

我设置了多个类,它们都需要访问数据库,他们这样做了。当我想在另一个类中使用一个函数时,麻烦就来了。

class General
{

private $_db = NULL;
private $_db_one;
private $_db_two;
private $offset;

public function __construct ( PDO $db ) {

    $this->_db     = $db;
    $this->_db_one = 'lightsnh_mage1';
    $this->_db_two = 'lightsnh_inventory';  
    $this->offset  = 10800; 

}
public function getTableNames() {

    $sql = 'SELECT TABLE_NAME 
            FROM INFORMATION_SCHEMA.TABLES
            WHERE TABLE_TYPE = "BASE TABLE" AND TABLE_SCHEMA="' . $this->_db_two . '"';

    $statement = $this->_db->query($sql);
    $result = $statement->fetchAll(PDO::FETCH_ASSOC);
    return $result;
}   

这很好用,然后我的其他班级也以同样的方式连接。正如您将在下面的“Distributors”类中看到的那样,我在构造函数中实例化了我的“General”类。在我边写边学习的过程中,我不禁觉得有一种更通用或更有效的连接方式。

class Distributors
{

private $_db = NULL;
private $_db_one;
private $_db_two;
private $_source_tbl;
public  $lights;


public function __construct ( PDO $db ) {

    $this->_db = $db;
    $this->_db_one = 'lightsnh_mage1';
    $this->_db_two = 'lightsnh_inventory';
    $this->_source_tbl = 'distributors';
    // is this the best way to get functions from another class inside of this class? I have 10 classes I will need to repeat this for.
    $this->lights = new General($db);

}



public function getInventorySources() {

    // calling function from General class inside my distributor class
    $tables = $this->lights->getTableNames();

    // using result of General function inside of a function from Distributors class
    $sql = 'SELECT * FROM `' . $tables . '` WHERE `exclude` = 0';
    $statement = $this->_db->query($sql);
    $result = $statement->fetchAll(PDO::FETCH_ASSOC);

    return $result;

}

【问题讨论】:

    标签: php class static instantiation


    【解决方案1】:

    Singleton 只是另一种形式的全局状态,这很糟糕。您应该始终避免它。

    从您的代码示例中,

    public function __construct ( PDO $db ) {
    
        $this->_db = $db;
        $this->_db_one = 'lightsnh_mage1';
        $this->_db_two = 'lightsnh_inventory';
        $this->_source_tbl = 'distributors';
        // is this the best way to get functions from another class inside of this class? I have 10 classes I will need to repeat this for.
        $this->lights = new General($db);
    }
    

    当你以这种方式实例化$this->lights = new General($db); 时,你会从全局范围中获取通用类。因此,模拟和单元测试几乎是不可能的。

    您应该注入一个General 的实例,就像您为PDO 所做的那样。 像这样:

    public function __construct (PDO $db, General $general)
    {
    
        $this->_db = $db;
        $this->_db_one = 'lightsnh_mage1';
        $this->_db_two = 'lightsnh_inventory';
        $this->_source_tbl = 'distributors';
        // is this the best way to get functions from another class inside of this class? I have 10 classes I will need to repeat this for.
        $this->lights = $general;
    }
    

    你会这样使用它:

    $pdo = new PDO(...);
    $pdo->setAttribute(...);
    
    $general = new General($pdo);
    $distributors = new Distributors($pdo, $general);
    

    这是从另一个类中获取函数的最佳方式吗 这节课?我有 10 节课需要重复。

    是的,你应该重复一遍,不是实例化,而是依赖注入。这使您的代码更易于维护,并且不会引入全局状态。

    除此之外,您的General 类似乎明显违反了Single-Responsibility Principle

    【讨论】:

    • metal_fan 感谢您为我指明了正确的方向。我特意没有深入研究我的项目,因为我想确保不必拆掉它然后再做一次。
    • 在你的依赖注入公共函数 __construct (PDO $db, General $general) 的例子中,我能用 Class Distributors extends General 来完成同样的事情吗?
    【解决方案2】:

    您应该使用单例在您的课程中获取数据库, 或者使用一些 ORM。

    关于带单例的mysql类:

    Establishing database connection in php using singleton class

    【讨论】:

      【解决方案3】:

      我不知道您遇到了什么问题,但我认为函数 getTableNames 会返回一个对象或一个数组,所以$tables 中的结果不是字符串,请执行var_dump($tables); 以查看$tables 中的内容

      试着用谷歌搜索你的出路。

      【讨论】:

        猜你喜欢
        • 2014-08-11
        • 2016-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多