【问题标题】:Error in object declaration when PDO class is extended扩展 PDO 类时对象声明中的错误
【发布时间】:2011-09-12 16:41:44
【问题描述】:

我创建了三个类。一类是从 PDO 扩展的 db。其他两个类扩展自 db 类。但问题是当我初始化这些子类的对象时,第二个对象被创建为第一个对象的克隆。提前感谢您的帮助。

<?php
/** The Database Driver */
define('DB_DRIVER', 'mysql');

/** The name of the database */
define('DB_NAME', 'sample');

/** MySQL database username */
define('DB_USER', 'root');

/** MySQL database password */
define('DB_PASSWORD', 'root');

/** MySQL hostname */
define('DB_HOST', 'localhost');

class db extends PDO
{
    public function __construct()
    {
        echo "DB constructor called\n";
        $options = array(
            PDO::ATTR_PERSISTENT => true,
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
        );
        $dsn = DB_DRIVER . ":host=" . DB_HOST . ";dbname=" . DB_NAME;
        parent::__construct($dsn, DB_USER, DB_PASSWORD, $options);
    }
}

class Admin extends db
{
    private $uid, $username, $password, $level, $name, $email;

    public function __construct()
    {
        echo "Admin constructor called\n";
        parent::__construct();
    }
}

class Movie extends db
{
    private $mid, $title, $slug;

    public function __construct()
    {
        echo "Movie constructor called\n";
        parent::__construct();
    }
}


$adminObj = new Admin();
$movieObj = new Movie();
var_dump($adminObj);
var_dump($movieObj);
?>

这是上面的输出。 请注意输出中显示的对象类型

Admin constructor called
DB constructor called
Movie constructor called
DB constructor called
object(Admin)#1 (6) {
  ["uid":"Admin":private]=>
  NULL
  ["username":"Admin":private]=>
  NULL
  ["password":"Admin":private]=>
  NULL
  ["level":"Admin":private]=>
  NULL
  ["name":"Admin":private]=>
  NULL
  ["email":"Admin":private]=>
  NULL
}
object(Admin)#2 (6) {
  ["uid":"Admin":private]=>
  NULL
  ["username":"Admin":private]=>
  NULL
  ["password":"Admin":private]=>
  NULL
  ["level":"Admin":private]=>
  NULL
  ["name":"Admin":private]=>
  NULL
  ["email":"Admin":private]=>
  NULL

}


当父::__construct($dsn, DB_USER, DB_PASSWORD, $options);在 db 类中删除该问题将消失。

【问题讨论】:

  • 如果您对提议的解决方案不满意并需要持久连接,那么(好吧,无论如何我都会建议)不要扩展 PDO 并在您的 db 类中创建 PDO 实例或将 PDO 实例作为参数传递给 Admin/Movie 类构造函数。

标签: php oop class inheritance pdo


【解决方案1】:

您有PDO::ATTR_PERSISTENT =&gt; true, 并尝试使用相同的 DSN 字符串创建 2 个 PDO 对象。这会告诉 PDO 在您执行 $movieObj = new Movie(); 时返回已建立的连接,而不是创建新连接。

您的解决方案: PDO::ATTR_PERSISTENT =&gt; false,

有用的链接:Connections and Connection management

当父级::__construct($dsn, DB_USER, DB_PASSWORD, $options);在 db 类已删除,问题将 消失。 是的,因为在这种情况下不会创建实际的 PDO 对象。

【讨论】:

  • 虽然这是一个正确的答案,但它只适用于 PHP 错误。这将导致每个对象只有一个连接,这是一种浪费,并且会阻止跨请求使用任何持久连接(这可能是需要的)。
  • 我完全同意“持久连接”的事情。最好的方法是不要扩展 PDO ,而是直接使用 PDO(作为 db 处理程序)并声明没有“扩展”的 db 类(例如 class db { ... }),并将 PDO 对象作为类字段(在 __construct() 中创建或作为参数传递等)。
【解决方案2】:

首先,这似乎是一个错误,这可能是由于 PDO 类在内部处理持久连接的方式。也就是说,PHP 不应该返回错误的扩展类,但可能是因为核心 PDO 驱动程序在设计时没有考虑到扩展它。

我在 bugs.php.net 上搜索了一些错误,并列出了一些。 (例如,搜索“pdo extend persistent”)参见#47407 了解类似内容。

说了这么多,这对你来说似乎是一个糟糕的设计。您的类应该使用现有 PDO 对象的句柄:

$db = new DB();
$movie = new Movie($db);

这将解决 PHP 错误,但同样重要......它的设计更好。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-03
  • 2021-12-14
  • 2017-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
相关资源
最近更新 更多