【问题标题】:PHP Class Database interaction (using PDO)PHP 类数据库交互(使用 PDO)
【发布时间】:2011-03-13 02:59:58
【问题描述】:

大家好,我对面向对象的 PHP 完全陌生——我已经阅读了一些教程,但我找不到任何真正适用于使用 PHP 类的数据库的内容。

我正在尝试做一些简单的事情——一个快速新闻发布类。您从数据库等中获取帖子。但是,每当我尝试与数据库交互时都会收到错误消息。

我读到 PDO 是使用 OO PHP 的方式;为此,我开发了一个数据库类,详见这篇文章:Use of PDO in classes

class Database
{
    public $db;   // handle of the db connexion
    private static $dsn  = "mysql:host=localhost;dbname=test";
    private static $user = "admin";
    private static $pass = "root";
    private static $instance;

    public function __construct () 
    {
        $this->db = new PDO(self::$dsn,self::$user,self::$pass);
    }

    public static function getInstance()
    {
        if(!isset(self::$instance))
        {
            $object= __CLASS__;
            self::$instance=new $object;
        }
        return self::$instance;
    }

    // others global functions
}

然后我尝试在我的 PHP 类中使用它,以便检索新闻帖子中的数据:

<?php
require_once "database.php";

class news extends Database
{
    private $title;
    private $author;
    private $date;
    private $content;
    private $category;


    function __construct($id)
    {
        $db = Database::getInstance();
        $query = $this->db->prepare("SELECT title, author, date, content, category FROM news WHERE id = :id LIMIT 1");
        $query->bindParam(":id", $this->id, PDO::PARAM_INT);
        if ($query->execute())
        {
            $result = $query->fetch(PDO::FETCH_OBJ);

            $this->set_title($result->title);
            $this->set_author($result->author);
            $this->set_date($result->date);
            $this->set_content($result->content);
            $this->set_category($result->category);
        }
    }
<...>
?>

但每次我尝试运行此脚本时,都会收到以下错误:

致命错误:在第 16 行的 /news.class.php 中的非对象上调用成员函数 prepare()

有什么想法吗?

【问题讨论】:

  • 旁注:如果您想将 Database 类实现为单例(即 xx::getInstance()),请将 __construct() 留空,甚至将其设为私有,以便 getInstance() 是唯一的访问它的方式。否则它只是一个带有有趣实例化的普通类。

标签: php oop pdo


【解决方案1】:

你的设计有缺陷。为什么新闻扩展数据库?数据库代表您的全局数据库连接。新闻表的单行不是数据库连接。所以它不应该继承它。您应该做的是遵循“优先组合优于继承”的原则。

扩展单例不是一个好主意。事实上,单例一般来说是个坏主意,因为它们会使您的代码变得单一。

您所做的基本上是对象关系映射。你应该看看一些现有的 PHP ORM,我建议Doctrine

【讨论】:

  • 如果我不想使用像 Doctrine 这样大的东西怎么办,你将如何进行数据库/对象交互?
【解决方案2】:

$db = 数据库::getInstance(); 需要: $db = 新数据库();

这一行 $query = $this->db->prepare(); 需要 $query = $db->prepare();

然后这个 $query->bindParam(":id", $this->id, PDO::PARAM_INT); 需要 $query->bindParam(":id", $id, PDO::PARAM_INT);

我不确定您为什么需要 Database 类中的 getInstance() 函数?

新数据库()

会给你一个新的实例。

【讨论】:

  • 我相信他的目标是使用getInstance 的单例模式。
  • 可能——但我想从一开始就学习好习惯,即使这意味着更陡峭的学习曲线。不过感谢您的回答!
【解决方案3】:
$db = Database::getInstance();
$query = $this->db->prepare();

您必须同时使用$db$this-&gt;db$db 是本地函数中的变量。 $this-&gt;db 是类的实例变量。他们不一样。在这种情况下,$this-&gt;db 不存在,因此没有成员函数 prepare,如错误所示。

您正在尝试在父类的构造函数中创建 $this-&gt;db,但由于您要覆盖子类中的构造函数,因此该代码不会运行。您需要调用 parent::__constructor 才能运行该代码。

【讨论】:

  • 错误已更改;但是,prepare() 不应该存在,因为我在 Database 类中有 $db 作为 PDO 对象吗?致命错误:在第 16 行的 /home1/centasmn/public_html/other_sites/test/news.class.php 中调用未定义的方法 Database::prepare()
  • Database::getInstance 返回Database 类的实例,该类本身也没有prepare 方法。 $db-&gt;db 是您要查找的对象,但这可能不是您想要使用该对象的方式。
猜你喜欢
  • 2012-07-20
  • 1970-01-01
  • 2011-03-17
  • 2021-04-28
  • 2018-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
相关资源
最近更新 更多