ORM不会解决所有的问题
在很多情况下是很方便的使用模型来访问数据库,但并非总是如此。如果你需要复杂的查询和高性能,可能会让你的ORM模型免于任务。
使用ORM模式正确
ORM只是众多编码模式,你可以在你的代码中使用的一个。
阅读本主题以了解更多有关它What is an ORM and where can I learn more about it?
你不应该考虑ORM作为隔离访问数据库的应用层。这只是一种以面向对象的方式操作数据的技术。
在每一个流行的框架中,你都会看到ORM是一个选项,而不是一个强制层。
考虑一下您希望获取特定文件的所有版本的情况。使用方法getAllVersions
创建类似FileVersionManager
的单身人士,其将通过fid
执行JOIN查询。这里也可以是类似checkoutToVersion
或getPreviousVersion
。此方法可以返回一个或一组Version
ORM型号。重要的是 - 这种方式在语义上更具有意义,因此更易于被其他程序员阅读和理解。
或者,如果您需要为每个文件更改生成版本,则可以将此逻辑委托给像Versionable
行为之类的内容。
我更喜欢将ORM看作某种应用程序域定义层。
所以,回答你的问题
如果你想让自己的ORM实现,那么就不要弄得太复杂。使用CRUD方法和模式定义为每个表创建单独的ORM模型。并使用其他模式执行复杂的查询。
实施例(Query.selectWhere
应被实现以使例如工作):
<?php
/**
* @property $name
**/
class File extends ORMModel
{
public function tableName()
{
return 'files';
}
public function properties()
{
return array_merge(parent::properties(), ['name']);
}
}
/**
* @property $number
* @property $file_id
**/
class Version extends ORMModel
{
public function tableName()
{
return 'versions';
}
public function properties()
{
return array_merge(parent::properties(), ['file_id', 'number']);
}
public function getFile()
{
return new File($this->file_id);
}
}
class FileVersionManager
{
public static function getLatestVersion($file)
{
$query = new Query();
$rows = $query->selectWhere((new Version())->tableName(), ['file_id' => $file->id]);
$max = 0;
$maxId = null;
foreach ($rows as $row) {
if ($row['number'] > $max) {
$maxId = $row['id'];
$max = $row['number'];
}
}
return new Version($maxId);
}
public static function createNewVersion($file)
{
$latestVersion = static::getLatestVersion($file);
$newVersion = new Version();
$newVersion->file_id = $file->id;
$newVersion->number = $latestVersion->number + 1;
$newVersion->insert();
return $newVersion;
}
}
class Query
{
private static $datasource = [
'files' => [
1 => [
'name' => 'file1',
],
2 => [
'name' => 'file1',
]
],
'versions' => [
1 => [
'file_id' => 1,
'number' => 1
],
2 => [
'file_id' => 1,
'number' => 2
],
3 => [
'file_id' => 2,
'number' => 1
],
4 => [
'file_id' => 2,
'number' => 2
],
]
];
public function select($tablename) {
return static::$datasource[$tablename];
}
public function selectOne($tablename, $id) {
return @static::$datasource[$tablename][$id];
}
public function selectWhere($tableName, $condition) {
//@todo: implement selection assuming that condition is ['propertyName1' => 'propertyValue1', 'propertyName2' => 'propertyValue2', ]
//should retun array of properties including id for above example
return [];
}
public function update($tableName, $id, $values) {
if (empty(static::$datasource[$tableName][$id])) return false;
static::$datasource[$tableName][$id] = $values;
return true;
}
public function insert($tableName, $values) {
$id = max(array_keys(static::$datasource[$tableName])) + 1;
static::$datasource[$tableName][$id] = $values;
return $id;
}
public function delete($tableName, $id)
{
unset(static::$datasource[$tableName][$id]);
return true;
}
}
/**
* @property $id
**/
abstract class ORMModel
{
private $properties;
public abstract function tableName();
public function properties() {
return ['id'];
}
public function __get($name) {
$propertyNames = $this->properties();
if (in_array($name, $propertyNames)) {
return @$this->properties[$name];
}
}
public function __set($name, $value) {
$propertyNames = $this->properties();
if (in_array($name, $propertyNames)) {
$this->properties[$name] = $value;
}
}
public function __construct($id = null)
{
if (!empty($id)) {
$query = new Query();
if ($this->properties = $query->selectOne($this->tableName(), $id)) {
$this->properties['id'] = $id;
}
}
}
public function insert()
{
$query = new Query();
$id = $query->insert($this->tableName(), $this->properties);
$this->properties['id'] = $id;
return $this;
}
public function update()
{
if (empty($this->properties['id'])) return false;
$query = new Query();
return $query->update($this->tableName(), $this->id, array_diff($this->properties, ['id']));
}
public function delete()
{
if (empty($this->properties['id'])) return false;
$query = new Query();
return $query->delete($this->tableName(), $this->id);
}
}
$version = new Version(1);
$file = $version->getFile();
var_dump($file->name);
$file = new File(2);
$version = FileVersionManager::getLatestVersion($file);
var_dump($version->number);
FileVersionManager::createNewVersion($file);
$version = FileVersionManager::getLatestVersion($file);
var_dump($version->number);
P.S.在这里你可以定义自己的Query
的实现,这应该适用于你的(任何)数据源
P.P.S.我仍然会建议你学习一些流行的框架(Yii2,Laravel,Symfony或任何其他),因为它是学习构建应用程序体系结构的最佳实践的好方法
如果您和您的团队都是PHP开发人员并且不愿意没有时间学习框架,我建议使用redbean http://www.redbeanphp.com/index.php快速且简单的orm准备好使用 –