5

私は問題に直面しており、programmers.stackexchange.com にも配置される可能性がありますが、Doctrine と ZF2 にかなり関連付けられているため、ここに配置することにしました。私のシナリオを紹介しましょう。

  • ユーザーがエンティティ ( BaseEntity) を投稿するアプリケーションがあります。
  • BaseEntityプロパティを持っています$cagetory
  • ただし、エンティティによっては$category、追加のプロパティが必要です

非常に単純な例:

class BaseEntity {
    protected $id;
    protected $title;
    protected $description;
}

class MovieEntity {
    protected $id;
    protected $title;
    protected $description;
    protected $airingDateStart; // new property
    protected $airingDateEnd;   // new property
}

これで、ユーザーが最初に自分のカテゴリを選択し、それに応じて EntityClass が選択されるという 2 段階の式を簡単に実行できますが、それはできません。しかし、ユーザーがBaseEntity-Category にムービーを投稿し、後でエンティティを に変更したい場合はどうすればよいのMovieEntityでしょうか? したがって、その考えは実際には安全な選択肢ではありません。

追加の要件(物事をより複雑にするため)

  • カテゴリとエンティティは Doctrine で制御する必要があります
  • それぞれCategoryが単一の経由でアプリケーションに提供されますModule
  • モジュールは、多くの構成を必要とせずにアプリケーションに配置する必要があります (最大 1 つの DB-Query でデータを入力しますCategoryTable) 。

私がこれまでにやったこと

最初に、Doctrines 機能Single Table Inheritanceで実行することを選択しました。これにより、次のようなことを簡単に実行できMovieEntity extends BaseEntity、データベースに新しいエンティティを追加するための魅力のように機能します。しかし、主な問題は残っています: ユーザーがカテゴリを変更すると、EntityClass が変更され、それはほとんど No-Go です。

はい、私は潜在的に私の現在の方法で物事を行うことができ、カテゴリの変更時に手動で変更することができますDiscriminatorColumnが、それは非常に汚いです.

別の代替アプローチは、カテゴリを変更するイベントで、新しいエンティティが作成され、古いエンティティが破棄されるというものですが、それもちょっと汚い感じがします。

全体として、私は間違った方向に向かっていると思います。私の知らない開発パターンがあり、私のすべての苦労が無駄に見え、最終的に物事が非常に簡単になる可能性がありますが、私は物事を見落としているようです.

私が何をしようとしているのかをよりよく理解するために、GitHub で私のアプリケーションを見てください。

  • DuitMarketplace - これは、基本カテゴリ、すべてのコントローラーなどを備えたメイン アプリケーションです。これは、ItemController#editAction()いくつかのものを自動化する方法について、さらにいくつかの手がかりを提供する可能性があります。
  • DuitMarketplaceItemVehicle - mainapp にドロップされるカテゴリ

フィードバックをお寄せいただきありがとうございます。この質問は、おそらくSOとprogrammers.stackexchangeの境界線であることを十分に理解していますが、結局ここに置くことにしました。

4

2 に答える 2

3

私があなたの状況を正しく読んでいれば、モノの継承を避け、代わりにモノとカテゴリの間の関係のプロパティとしてカテゴリ固有の属性について考えるほうがよいように思えます。

次のようなアーキテクチャはどうでしょうか。

<?php

class Category {
    protected $id;
    protected $title;
    protected $things; //@ManyToOne(targetEntity="ThingCategory")
}

class Thing {
    protected $id;
    protected $title;
    protected $description;
    protected $category; //@ManyToOne(targetEntity="ThingCategory")
}    

/**
 * Use [Single|Class]-Table Inheritence to model subject-category attributes.
 * 
 * ThingCategory is just a base class.  Modules provide concrete subclasses
 * that encapsulate category-specific attributes.
 */
class ThingCategory {
    protected $id; //surrogate key, not strictly necessary
    protected $thing; //@ManyToOne(targetEntity="Thing")
    protected $category //@ManyToOne(targetEntity="Category")
}

class ThingMovieCategory extends ThingCategory{
    protected $airingStartDate;
    protected $airingEndDate;
}

class ThingCarCategory extends ThingCategory {
    protected $horespower;
    protected $numberOfDoors;
    protected $color;
}

そのため、関連する ThingCategory エンティティを置き換えることで、カテゴリ間を移動できるようになりました。カテゴリとの関係だけで、モノのアイデンティティは決して変わりません。そのカテゴリに含めるために必要な属性は、モノ自体ではなく、ThingCategory 関係エンティティのプロパティです。

編集: 遭遇する可能性のある問題は、エンティティをサブクラス化するときに識別子マップを変更する方法が文書化されていないことです。不幸な副作用は、ベース モジュールが可能なすべてのモジュールを認識しなければならないことです。しかし、それはおそらく大きな懸念事項ではありません。もしそうなら、各モジュールが基本エンティティの ClassMetaData を操作することでこれを回避できると思いますが、実際にそれを機能させることは決してしませんでした。

于 2013-06-05T21:15:15.563 に答える