2012-03-30 14 views
2

私の会社が購入したデータウェアハウスへのレポート拡張機能を書いています。データウェアハウスはデータモデル中立であり、テーブルの関係とフィールドのメイヤーデータを格納するテーブルを持っています。これは私がやっていることである基本的なORMクラスを書くのはかなり簡単です。それはすべて動作しますが...ORMクラスを手渡すハンド - シングルトン、静的親、?

私のORMクラスは、PDOインスタンス、テーブルのフィールド(ホワイトリストとして使用される)、およびフィールドのメタルレイヤ情報を保持します。また、テーブル関係のマッピング(FROM/JOIN句の生成)とWebから提供されるフィルタのマッピング(WHERE句の生成)のための便利な機能も備えています。

SELECT句は、要求されたモデルに基づいて、ORMの子クラスで生成されます。ページが読み込まれると、いくつかのモデルが構築される必要があります。明らかに、私はORM(モノステートのような)のインスタンスを1つだけ必要としますが、子クラスがインスタンス化されるたびに親クラスのクエリーをやり直さずに、各子クラスがORMのプロパティと便利関数を継承するようにしたいと思います。

ここではシングルトンパターンが当てはまるかもしれませんが、シングルトンをサブクラス化することは困難です。私はちょうど静的なプロパティを正しく動作させるように見えることはできません。

私は近くにいると思うが、私は何かを見逃しているか、これをあまりにも難しくしている。私は今、プロパティを薄いクラスに落としてそこから伸びていくことを検討しています。私はこのトピックについて同様の質問を見たことがありますが、明確な解決策を思い付いていません。

私は仕事中ではありませんが、これは私がしようとしていることの要点を示すコードの単純な例です。

Class ORM { 

    protected $conn; 
    protected $fields; 
    protected $relations; 
    protected $table; 
    protected $sql; 

    public function __construct ($view, $database) { 

     $this->conn = new PDO(...$database...); 
     $this->table = $view; 
     $this->getFields(); 
     $this->getRelations(); 
    } 

    private function getFields() { 
     //select fields from metalayer where table = $table; 
     //$this->fields = $result; 
    } 

    private function getRelations() { 
     //select relations from relations where table = $table; 
     //$this->relations = $result; 
    } 

    protected function mapTables ($tables) { 
     // $this->sql = "FROM $this->table"; 
     // foreach ($tables as $table) { 
     // $this->sql .= "LEFT JOIN $table ON $relations[$table]['key1'] = $relations[$table]['key2']; 
    } 

    protected function mapFilters ($filters) { 
     // $this->sql = "WHERE 1=1"; 
     // foreach $filters as $filter { 
     // $this->sql .= "AND ($filter['field'] = $filter['criterion1'] OR ...criterion2, etc.) 
    } 
} 

Class ExampleModelDAO extends ORM { 
    public function __construct($view, $database, $params) { 
     parent::__construct($view, $database); 
     // parse params 
     parent::mapTables($tables); 
     parent::mapFilters($filters); 
    } 

    public function get() { 
     // Prepend $this->sql with SELECT statement specific to model 
     // Query database and return model 
    } 
} 
+0

PDOインスタンスを依存関係として渡す必要があります。これは、テストを行うときに模擬オブジェクトで置き換えるほうがずっと簡単です。 – Xeoncross

答えて

2

まず、orm/modelはデータベースについて何も知ってはいけません。これを行うには百万の方法がありますが、私はpdoの上にいくつかの追加機能を提供するが、他のものから完全に独立した単純なデータベースクラスから始めます。これにより、モデルを必要とせずにデータベースに直接アクセスしたり、データベースに依存しないモデルを作成することもできます。最大限の柔軟性を得るためには、アダプターパターンとデータマッパーを調べる必要があります。ただし、モデルをデータストアにマッピングする、非常に基本的な例(アダプタまたはデータマッパーなし)を簡単に説明します。

したがって、データベースクラスには簡単な操作が必要です。次に、あなたのORMは、これはあなたが軌道に乗るのに十分でなければならないので...

<?php 
class ORM { 
    public function __construct() { 
     $this->db = new DB(); 
    } 

    public function find($options) { 
     return $this->db->read($options); 
    } 

    public function save($data) { 
     return $this->db->create($data); // or update() 
    } 

    // etc... 
} 

のように、このクラスと対話することができます。また、むしろあなたが外部からあなたの接続を管理していない場合、あなたは簡単な修正レジストリタイプのパターンを使用することができ、データベースのシングルトンパターンを使用するよりも(これが真のレジストリではないことに注意)

<?php 

class DB extends PDO { 
    protected static $instances = array(); 

    public function __construct() ... 

    public static function get($name) { 
     if(! isset(self::$instances[$name]) { 
      self::$instances[$name] = new self(); 
     } 
     return self::$instances[$name]; 
    } 
} 

class ORM { 
    public function __construct() { 
     $this->db = DB::get('connection1'); 
    } 
} 

ありますこれを行うより良い方法が、私はあなたにそれを残します。

+0

副作用として、ORM *はデータベースについて知っているはずです。**結局のところ、オブジェクトリレーショナルマッパー**です。これは、オブジェクトモデルを開発者に提示し、反対側のRDBMS呼び出しに変換する方法を知っています。データベースについて知る必要のないモデル*です。 – Xeoncross

+1

入力いただきありがとうございますが、私は同意しません。あなたのデータ層が適切に抽象化されていれば、ormはデータベース、セッション、キャッシュ、ログなどに書き込むことができます。 – Rob

関連する問題