您正在尝试实现活动记录模式。
对象持久化的一种方法是提供一个共同的祖先类[例如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
例如,它只是获取对外部实体的引用]。
要解决第二个问题,您必须将架构保存在外部文件中或使用内联注释。
要解决第三个问题,您必须编写自己的 ORM [对象关系映射],或者更好地切换到现有的。
无论如何,出于学习的好处,我会站在巨人的肩膀上,如果您计划构建可扩展且可维护的应用程序,我会选择一个框架。