ORMは、常にDBへのアクセスではなくするためにモデルを使用するのが便利である多くの場合、すべてのあなたの問題
を解決することはできません。複雑なクエリや高性能が必要な作業をORMモデルに任せておく方がよいでしょう。
使用ORMパターンが正しく
ORMはただ一つ、あなたのコード内で使用することができ、多くのコーディングパターンのです。
あなたは、データベースへのアクセスを隔離し、アプリケーション層としてのORMを検討するべきではありませんそれについてWhat is an ORM and where can I learn more about it?
の多くを学ぶために、このトピックをお読みください。これは、オブジェクト指向の方法でデータを操作する単なる技法です。
すべての一般的なフレームワークで、ORMはオプションであり、必須のレイヤではありません。
特定のファイルのすべてのバージョンを取得する場合を考えてみましょう。メソッドgetAllVersions
でFileVersionManager
シングルトンのようなものを作成し、fid
でJOINクエリを実行します。ここにはcheckoutToVersion
やgetPreviousVersion
のようなものもあります。このメソッドは、Version
ORMモデルの1つまたは複数を返すことができます。そして重要なことは、このように意味的に意味があり、したがって他のプログラマーが読んで理解しやすくなります。
また、各ファイルのバージョンを変更する必要がある場合は、このロジックを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を使う準備ができました。 –