2010-12-08 5 views
1

を設定するには、私は、親テーブルに関連されるいくつかのテーブルを持っています。関係のものを解決するために「醜い」の方法は、スキーマに手動で依存関係を含めることであろう。symfonyのとDoctrineテンプレート - 私のDBスキーマでは1対多の関係

sfArea: 
    columns: 
    id: integer 
    name: string 

sfCity: 
    columns: 
    name: string   
    area_id: integer 
    relations: 
    Area: 
     class: sfArea 
     local: area_id 
     foreignType: many 
     foreignAlias: Cities 

sfItem: 
    columns: 
    name: string 
    area_id: integer 
    relations: 
    Area: 
     class: sfArea 
     local: area_id 
     foreignType: many 
     foreignAlias: Items 

しかし、私はクラスを追加するたびにエリアに接続されるように、私は追加する必要があります関係とそれに付随するすべての行(コピー/ペースト=>未来の地獄)。私は私がそのような同じことを達成することを可能にするDoctrine_Templateを、使用することを決めたところである:

sfArea: 
    columns: 
    id: integer 
    name: string 

sfCity: 
    actAs: 
    AreaRelated: { foreignAlias: Cities } 
    columns: 
    name: string   

sfItem: 
    actAs: 
    AreaRelated: { foreignAlias: Items } 
    columns: 
    name: string 

そして、テンプレートクラス:

class AreaRelated extends Doctrine_Template 
{ 
    protected $_options = array(
     'foreignAlias' => '' 
    ); 

    public function setTableDefinition() 
    { 
     $this->hasColumn('area_id', 'integer'); 
    } 

    public function setUp() 
    { 
     $this->hasOne('sfArea as Area', array(
       'local' => 'area_id', 
       'foreign' => 'id', 
       'foreignType' => 'many', 
       'foreignAlias' => $this->_options['foreignAlias'] 
      ) 
     ); 
    } 
} 

テーブルが正しく生成との関係はで動作しますされています$ sfCity-> Areaの方向です。しかし、sfAreaクラスに設定されなければならない関係が作成されていません($ sf_area->都市sfArea「『『上』」不明なレコードのプロパティ/関連部品』都市エラーを与えます)。

はどのように他の関係を作成することができますか?私はあなただけあなたが頭痛の多くを取得するデータベースにhirearchyのこの種を表す、大きなモデルの問題を持っていると思う

//... 
public function setUp() 
{ 
    $thisTable = $this->_table; 
    $areaTable = Doctrine::getTable("smArea"); 

    $thisTable->hasOne('smArea as Area', array(
      'local' => 'area_id', 
      'foreign' => 'id', 
      'foreignType' => Doctrine_Relation::MANY 
     ) 
    );   

    $areaTable->hasMany($thisTable->getOption('name') . ' as ' . $this->_options['foreignAlias'], array(
      'local' => 'id', 
      'foreign' => 'area_id', 
      'foreignType' => Doctrine_Relation::ONE 
     ) 
    );    
} 
+0

ええと、スキーマのバージョンはうまくいくはずです...私が見る唯一の問題は、あなたの 'foreignAlias'は各クラス、すなわち' Cities'と 'Items'で異なるはずだということです。一方、ハードコーディングされたバージョンには問題があります。 – prodigitalson

+0

こんにちは、ちょっと、タイプミスを修正しました。それは私の大きな問題です。手作業のコピーを貼り付けるのを避けるため、AreaRelatedテンプレートを動作させるのが大好きです。 –

+0

少しのコピー/ペースト/タイピングを避けるために多くの作業があるようです。わからない、私のスキーマはそれを頻繁に変えない。 – Nathan

答えて

0

残念ながら、私は残念なことに、少なくともいくつかの追加の定義なしでこれを行う方法はないと思います。最小限の追加が必要となること、これを行うための一つの方法は、オプションによってエリアの関係を列挙するために、次のようになります。

Area: 
    options: 
    models_with_areas: [Cities, Items] 

が続いもちろんArea::setUp

public function setUp() 
{ 
    parent::setUp(); 
    $models = $this->getTable()->getOption('models_with_areas'); 
    foreach($models as $model) 
    { 
    $this->hasMany($model, array(
     'local' => 'id', 
     'foreign' => Doctrine_Inflector::tablize($model) . '_id' 
    )); 
    } 
} 

に関係を添付して、このようなアプローチは、柔軟性がなく、かなり複雑なロジックやオプションが必要な場合は、うまく機能しません。あなたは常にエリアでのみ関係を定義することができますが、関係の多くの側面のための行動を使用し続けます。

これは他の回答とは対照的に、私はこれが健全なアプローチであり、潜在的に良い考えだと思います。 Symfony/Doctrineの哲学の中心的な教義は、あなた自身を繰り返さないことです。このソリューションは、そのアイデアを遵守します。また、AreaRelatedクラス間でロジックが共有されている場合、大きなメリットがあります。

* 1つの醜い例外を除いて、すべてのテーブルを繰り返して、テンプレートAreaRelatedを持つテーブルを見つけることができます。これは、Areaレコードがロードされるたびにすべてのテーブルをインスタンス化する必要があり、絶対にひどい考えのように聞こえます。

-1

:私も(成功なし)ことを試みました。私はそれのような何かを持って地獄です主要なサイトのいくつかのmantainenceをやっている。

私のアドバイスは、上で物事を考えるされ、hirearchyが本当にデータベースまたはリレーショナルデータベースをモデル化しながら、多分あなたがオブジェクトに考えているにあることが必要な場合、再analize。あなたは、一例では市を与え、あなたは参照テーブルに入れた場合の領域は、コードの複製を最小限に抑え、分類することができるよう、「カテゴリー」のように思える情報で

。カテゴリは他の関係を持っているかもしれませんし、単に多くのフィールドを持つ大きなテーブルであるかもしれません。

CategoryClass >> 
public function getObjectRepresentation() 
{ 
    return new $this->getModelClassName()($this); 
} 
[...] 

RealObjectRepresentation1 >> 
public function __construct(Category $category) 
{ 
    //Initialize proper object using category information 
} 
:生のデータをどのように処理するかを知るためのヒントとしてmode_class_nameを使用して

Area: 
    tableName: area_table 
    description: Area 
    columns: 
    id: 
    name: 
    category_id: 
     type: integer 
     foreignClass: Category 
     foreignReference: id 
     required: true 

Category 
    tableName: categor_table 
    description: An area specialization 
    columns: 
    id: 
    model_class_name: 
     type: varchar(255) 
     description: the model Class that will represent this piece of information 
    field1: 
    field2: 
    relation:1 

は、あなたのような何かができる:だからここ

は、私が提案するモデルの種類(Propelの)です

このように、DatabaseHirearchyをPhpObjectHirearchyに移動しました。

これは何らかの形で役立ちます。詳細が必要な場合は、私が手伝ってくれて嬉しいです!

+1

こんにちは、私はあなたが質問で表現した本当の問題を誤解していると思います。さらに、CityとItemは、名前だけでなく(実際には2つだけでなく10から15まで)多くの列を持つ実際には完全に未実現のオブジェクトです。あなたのアプローチでは、私は200列のテーブルが残っています。クエリを最適化したい場合に必要な実際のオブジェクトに応じて適切な列を選択することでバグが発生する可能性があります。 –

0

これまでのところ、記録のために、私の最高の推測では、それをスキーマファイルの手動の方法を行うことです。 Nathanが述べたように、スキーマがほとんど変更されないので、Behaviorを実装できない場合(これはサイドプロジェクトとしてやっていきます)、これを実行するための最良の方法です。 Behaviorのアプローチの利点は、この中央オブジェクトに依存するすべてのオブジェクトにわたって、特定の非常に中央のオブジェクトとの関係を自動的かつ一貫して生成できるということです。

これは、例えば、すべての投稿、ユーザー、カテゴリ、メディアアップロードなどが特定のブログに関連するマルチサイトブログエンジンです。

sfArea: 
    columns: 
    id: integer 
    name: string 

sfCity: 
    columns: 
    name: string   
    area_id: integer 
    relations: 
    Area: 
     class: sfArea 
     local: area_id 
     foreignType: many 
     foreignAlias: Cities 

sfItem: 
    columns: 
    name: string 
    area_id: integer 
    relations: 
    Area: 
     class: sfArea 
     local: area_id 
     foreignType: many 
     foreignAlias: Items