我不熟悉使用PHP的面向对象范例,所以我可能错过了一些明显的东西。
我有一个类Question
,有多个子类用于不同的问题样式,其实例可以从MySQL数据库创建,也可以由用户在表单中创建。但是,如果它是由用户创建的,它将不会在数据库中附加任何自动递增ID。
最好的方法是什么?不幸的是,我有点难过。
我是否应该为用户创建的Question
使用不同的类,直到它被添加到数据库中?我应该让它们是同一个类,但根据来源使用不同的方法来实例化它们?还有别的吗?
答案 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);
}
...
}