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