您正在尝试实现Active record pattern。
对象持久化的一种方法是提供一个共同的祖先类 [e.g. BasicEntity] 每个子类都扩展,它基于给定的数据模式构建查询:
class BasicEntity
{
protected $tablename;
protected $schema;
public function update()
{
$fields = "";
$placeholders = "";
foreach($this -> schema as $field => $type)
{
// you join the fields here to get something like ('username', 'email', 'enabled', 'createdAt', 'password')
// then you write your PDO statement providing placeholders like (:?, :?, :?, :?, :?)
// you'll have to bind parameters based on their $type [int, string, date]
}
$query = sprintf(
"UPDATE %s SET VALUES(%s) = %s",
$this -> tablename,
$fields,
$placeholders
);
// execute statement here, handle exceptions, and so...
}
}
所以你的User 类将是这样的:
class User extends BasicEntity
{
protected $id;
protected $username;
protected $email;
protected $password;
protected $enabled;
protected $createdAt;
public function __construct()
{
$this -> tablename = '_user';
$this -> schema = array(
'id' => 'int',
'username' => 'string',
'email' => 'string',
'password' => 'string',
'enabled' => 'int',
'createdAt' => 'datetime'
);
}
}
还有你的Admin 班级:
class Admin extends User
{
protected $additionalProperty;
public function __construct()
{
parent::__construct();
$this -> schema['additionalProperty'] = 'string';
}
}
调用update() 将根据类模式构建正确的查询。这种方法适用于低复杂度级别,因为您会注意到:
- 如果您[在同一张表上!] 扩展实体,您需要为没有此类字段的行提供空表字段[在本例中为
additionalProperty];
- 如果您的架构发生更改 [例如您更改了变量名],您必须将其硬编码到类构造函数中,从而使其更难维护;
- 如果您想处理实体之间的关系,那么在每个 SELECT 语句中编写正确的连接将是一件很痛苦的事情,除非您只是编写大量单独的查询,从而降低性能。
要解决第一个问题,您需要对象的组合,因此您不会使主表增长太多[例如,它只是获取对外部AdditionalPropertyList 实体的引用]。
要解决第二个问题,您必须将架构保存在外部文件中或使用inline annotations。
要解决第三个问题,您必须编写自己的 ORM [Object Relational Mapping],或者更好地切换到 an existing one。
无论如何,出于学习的好处,如果您打算构建可扩展且可维护的应用程序,我会站在巨人的肩膀上,我会选择一个框架。