【问题标题】:PHP __construct()PHP __construct()
【发布时间】:2012-07-25 20:58:49
【问题描述】:

我有以下内容,但是我无法访问初始 db 类之外的数据库函数?

谢谢!

数据库.php

class db
{
  private $connection;

  public function __construct()
  {
    $this->connection = new PDO();
  }
}

admin.php

class admin
{
  private $connection

  public function __construct(db $connection)
  {
    $this->connection = $connection;
  }

  function myFunc()
  {
    // How do I access the connection here?
  }
}

main.php

//include db.php
//include admin.php

$connection = new db();
$admin = new admin($connection);

// How do I access the DB here?

【问题讨论】:

    标签: php class pdo


    【解决方案1】:

    首先,你为什么封装PDO 只是为了包含那个对象的类?不能直接用PDO吗?

    一种常见的做法是在 db 类中实现 getter,例如:

    class db {
        ...
    
        public function getPDO(){
           return $this->connection;
        }
    }
    

    另一种方法是重新实现每个函数(为什么要这样做?!),或者使用__call 魔术函数...

    或者只是将$connection公开;)

    或者你可以扩展 PDO 类(我不确定它是否会起作用):

    class DB extends PDO {
        public function __construct ( $dsn, $username = null, $password = null, $driver_options = array()){
                parent::__construct( $dsn, $username, $password, $driver_options);
                ... more of your stuff
        }
    
        public function myFunc(){
            $this->...
        }
    }
    

    【讨论】:

    • 感谢您的回复。 db 类包含几个未在此处显示的函数,因此最好作为一个类。有人建议我在实例化类时创建 PDO 对象,以避免必须使用 $object->getPDO()->Prepare();每次。这是一个大项目,所以我试图避免公共变量。您能否解释一下为什么我的示例不起作用?谢谢!
    • @CraigWilson 看看编辑,如果这可行,它应该会立即解决您的所有问题
    • 已经实现了一个getter方法getPDO(),独立于__construct,然后将它传递给worker类的构造函数。谢谢。
    【解决方案2】:

    好的,您确实需要阅读面向对象的设计和访问修饰符。我会在这里解释你需要做什么,但这是一个临时解决方案,你需要深入了解这里的工作原理。

    在您的管理类中,您将连接定义为类的私有属性。因此,在 myFunc 函数中,您只需执行 $this->connection 即可访问您在构造函数中创建的连接。

    在您的 main.php 文件中,您正在初始化一个 DB 对象的 rom 对象不是连接。它是一个整体的db对象,所以你不能将连接本身传递给admin类(它被定义为私有,所以类外没有人可以查看它)。但是,为什么需要将它传递给管理类?管理 DB 连接应该是 DB 类的责任。

    换句话说,你想通过将数据库连接暴露给管理类来达到什么目的?

    更新:根据这里的回复是一个建议的答案:

    class Database {
        private $connection;
        public function __construct() {
            $this->connection = new PDO();
        }
    }
    
    class Admin {
        private $db;
        public function __construct() {
            $this->db = new Database();
        }
    
        public function myFunc() {
            $this->db->query('...');
        }
    }
    

    在你的 main.php 文件中:

    $admin = new Admin();
    $admin->myFunc();
    

    请记住,每个管理对象都会创建到数据库的新连接,因此如果您创建许多管理对象,您可能会遇到一些问题。您可以通过将 DB 声明为单例来解决此问题。

    【讨论】:

    • 感谢您的回复。这是几周前我的帖子的链接,其中向我建议了这种设计模式。 stackoverflow.com/questions/11508070/…
    • 谢谢。我认为这就是为什么建议我将 db 对象从 main.php 文件注入 Admin 的原因?您知道为什么我当前的示例不起作用吗?
    【解决方案3】:

    这个怎么样:更新了

     <pre>
     <?php 
    class DB {
    
        private $host;
        private $user;
        private $pass;
        private $dbase;
        private $connection;
    
        public function __construct($host,$user,$pass,$dbase)
        {
            $this->host = $host;
            $this->user = $user;
            $this->pass = $pass;
            $this->dbase = $dbase;
            $this->connection = new PDO("mysql:host=$this->host;dbname=$this->dbase", $this->user, $this->pass);
        }
        public function connect()
        {
            return $this->connection;
        }
        public function close()
        {
            unset($this->connection);
            return true;
        }
    }
    $dbh = new DB('localhost','root','','inventory');
    $result  = $dbh->connect()->query("SELECT * FROM products")->fetchAll(PDO::FETCH_ASSOC);
    print_r($result);
    ?>
    </pre>
    

    【讨论】:

    • 感谢您的回复。我在哪里定义 $connection?
    • 连接是在变量封装后在construct方法内部定义的。
    • 谢谢,但应该 $connection;不先定义为私有?
    • 我刚刚编辑了它。您可以使用方法链来直接进行交易。,
    【解决方案4】:

    更新了文件分离

    database.php

    class db
    {
        private $connection;
    
        public function __construct()
        {
            $this->connection = new PDO();
        }
    }
    

    admin.php

    class admin
    {
        private $connection
    
        public function __construct(db $connection)
        {
            $this->connection = $connection;
        }
    
        function myFunc()
        {
            return $this->connection->prepare('SQL');
        }
    
        function getConnection()
        {
            return $this->connection;
        }
    }
    

    ma​​in.php

    require_once 'database.php';
    require_once 'admin.php';
    
    $connection = new db();
    $admin = new admin($connection);
    $admin->myFunc()->execute();
    

    【讨论】:

    • 谢谢。您能否像我上面的示例一样演示这将如何跨文件工作?谢谢!
    • 感谢您的回复。不幸的是,这给了我一个致命错误:从管理类中通过 $this->connection->prepare 调用时调用未定义的方法 db::prepare()?有什么想法吗?
    猜你喜欢
    • 2011-10-08
    • 2011-03-29
    • 2013-02-16
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 2017-05-11
    相关资源
    最近更新 更多