【问题标题】:PHP PDO-MYSQL : How to use database connection across different classesPHP PDO-MYSQL:如何跨不同类使用数据库连接
【发布时间】:2012-07-15 21:08:57
【问题描述】:

我对使用 MYSQL 的 PDO 有点陌生,这是我的两个文件:

我有一个用于连接数据库的连接类:

class connection{

private $host = 'localhost';
private $dbname = 'devac';
private $username = 'root';
private $password ='';  

public $con = '';

function __construct(){

    $this->connect();   

}

function connect(){

    try{

        $this->con = new PDO("mysql:host=$this->host;dbname=$this->dbname",$this->username, $this->password);
        $this->con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);


    }catch(PDOException $e){

        echo 'We\'re sorry but there was an error while trying to connect to the database';
        file_put_contents('connection.errors.txt', $e->getMessage().PHP_EOL,FILE_APPEND);

    }
}   
}

我有一个 account_info 类,用于从数据库中查询数据:

class account_info{


function getAccountInfo(){

    $acc_info = $this->con->prepare("SELECT * FROM account_info");
    $acc_info->execute();

    $results = $acc_info->fetchAll(PDO::FETCH_OBJ);

    foreach ($results as $key) {
        $results->owner_firstname;

    }
}       


}

我将这两个文件都包含在我的 index.php 页面中:

include_once 'classes/connection.class.php';
include_once 'classes/accountinfo.class.php';

$con = new connection();
$info = new account_info();
$info->getAccountInfo();

我只是无法让它工作我没有得到任何输出,我认为它与范围有关,但我不知道为什么要修复它,因为我是这个 PDO 的新手并且哎呀的东西。 提前致谢。

【问题讨论】:

    标签: php mysql class pdo


    【解决方案1】:

    解决方案 1

    class account_info { 替换为class account_info extends connection {

    替换

    $con = new connection();
    $info = new account_info();
    

    $info = new account_info();
    

    它应该可以工作。

    解决方案 2(建议)

    我强烈建议您在这种情况下使用依赖注入来解决您的问题。 只需将您的帐户类替换为:

    class account_info {
    
        private $con;
    
        public function __construct(connection $con) {
            $this->con = $con->con;
        }
    
        public function getAccountInfo(){
    
            $acc_info = $this->con->prepare("SELECT * FROM account_info");
            $acc_info->execute();
    
            $results = $acc_info->fetchAll(PDO::FETCH_OBJ);
    
            foreach ($results as $key) {
                $results->owner_firstname;
            }
        }       
    
    }
    

    并像这样在 index.php 中使用它:

    include_once 'classes/connection.class.php';
    include_once 'classes/accountinfo.class.php';
    
    $con = new connection();
    $info = new account_info($con);
    $info->getAccountInfo();
    

    说明

    作为一个普遍的好规则:始终为函数(public、protected 或 private)指定范围关键字。

    第一个解决方案称为继承,我们所做的基本上是用连接类扩展帐户类,以便从连接类继承所有方法和属性并轻松使用它们。在这种情况下,您必须注意命名冲突。我建议你看看PHP手册中的类继承。

    第二种解决方案称为依赖注入,这是一种广受鼓励的设计模式,它使您的类在其构造函数中接受其他类,以便显式定义类依赖树(在这种情况下,帐户依赖于连接,而没有我们的连接)无法使帐户工作)。

    在成千上万种可能的解决方案中,另一种是有人在下面发布的一种称为 Singleton 的设计模式。然而,该模式最近已被重新评估为反模式,不应使用。

    【讨论】:

    • 那么他将为他的帐户类的每个实例(以及需要数据库连接的所有其他类)创建一个新的数据库连接。
    • 好的,所以在最新版本之后,他现在需要在他的应用程序的整个范围内跟踪 $con(并且非常小心不要覆盖它),并将它显式传递给每个其他对象/闭包.现在我明白为什么单身人士是个坏主意了! :)
    • @Martin,singletons 使用 static 关键字的全局范围,以便拥有一个可免费使用的全局类实例并拥有一个实例。但这是结构良好的应用程序中不需要的 hack。它被称为反模式,因为它根本不是一种模式,并且违反了设计模式指南中最重要的几点。
    • 依赖注入肯定是要走的路。
    • 谢谢!第一个解决方案效果很好!但我真的想使用第二种解决方案,但我收到此错误:致命错误:调用 C:\wamp\www\php-tests\projects\devac\classes\accountinfo.class 中的未定义方法连接::prepare()。 php 在第 13 行
    【解决方案2】:

    一种常见的方法是在您的数据库类中使用singleton 模式。

    类似这样的:

    class connection {
    
       private static $hInstance;
    
       public static function getInstance() {
         if (!(self::$hInstance instanceof self)) {
             self::$hInstance = new self();
         }
    
         return self::$hInstance;
       }
    
       /* your code */
    }
    

    然后,你可以简单地使用

    $database = connection::getInstance(); 
    $database->con->prepare(....)
    

    【讨论】:

    • 现在非常不鼓励单身人士。
    • 我觉得网上到处都是这种文章
    • 我可以整天发布相反的链接:c2.com/cgi/wiki?SingletonsAreGood - 它更多的是关于使用而不是模式本身。对于 OP,它肯定是一个更简单、更清洁的解决方案。
    • 从 Brian Button 转述:1)它们通常用作全局实例,为什么这么糟糕?因为您在代码中隐藏了应用程序的依赖项,而不是通过接口公开它们。使某些东西全局化以避免传递它是一种代码味道。 2)他们违反了单一职责原则:因为他们控制自己的创建和生命周期。
    • 3) 它们在应用程序的生命周期内携带状态。测试的另一个打击,因为您最终可能会遇到需要订购测试的情况,这对于单元测试来说是一个很大的禁忌。为什么?因为每个单元测试都应该相互独立。
    猜你喜欢
    • 2021-12-06
    • 1970-01-01
    • 2010-12-13
    • 2021-02-25
    • 2013-01-29
    • 2013-08-03
    • 2013-05-14
    • 2018-10-23
    相关资源
    最近更新 更多