PHP面向对象的数据库访问

时间:2014-07-06 10:11:47

标签: php mysql oop

我不熟悉使用PHP的面向对象范例,所以我可能错过了一些明显的东西。

我有一个类Question,有多个子类用于不同的问题样式,其实例可以从MySQL数据库创建,也可以由用户在表单中创建。但是,如果它是由用户创建的,它将不会在数据库中附加任何自动递增ID。

最好的方法是什么?不幸的是,我有点难过。

我是否应该为用户创建的Question使用不同的类,直到它被添加到数据库中?我应该让它们是同一个类,但根据来源使用不同的方法来实例化它们?还有别的吗?

1 个答案:

答案 0 :(得分:4)

首先,您的Question类应该首先与数据库无关。它们应该纯粹是愚蠢的域对象,它只保存数据并可能对其执行一些数据验证:

class Question {

    protected $title;
    protected $body;

    ...

    public function setTitle($title) {
        if (strlen($title) == 0) {
            throw new InvalidArgumentException(...);
        }
        $this->title = $title;
    }

    public function getTitle() {
        return $this->title;
    }

    ...

}

根据您的要求,您可以通过在构造函数中要求它们来使这些属性成为必需。通过这样做,您可以确保如果您有Question的实例,它至少具有使其成为有效问题的最小属性:

public function __construct($title) {
    $this->setTitle($title);
}

再次注意,这个对象绝对没有数据库的概念。这是其他一些类的责任,它可以访问数据库连接器并可以从Question对象读取它们以将它们存储在数据库中并从数据库数据创建新的Question对象:

class QuestionStore {

    protected $db;

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

    public function getQuestion(...) {
        $data = $this->db->query('SELECT ...');

        $question = new Question($data['title']);
        $question->setBody($data['body']);
        return $question;
    }

}

(你可以辩论将这些责任进一步分为工厂等,但你得到了基本的想法。)

如何处理ID然后变得非常简单。您只需将id设置为Question类的非必需属性之一,因此某些Question实例具有ID,而其他实例则尚未保存在数据库中。或者,如果您的代码更容易区分这两类问题,那么请从中创建一个子类型:

class StoredQuestion extends Question {

    protected $id;

    public function __construct($id, $title) {
        $this->setId($id);
        parent::__construct($title);
    }

    ...

}