Templates Symfony和条令模板-建立一对多关系

Templates Symfony和条令模板-建立一对多关系,templates,symfony1,doctrine,behavior,Templates,Symfony1,Doctrine,Behavior,在我的DB模式中,有几个表将与父表相关。解决关系的“丑陋”方法是在模式中手动包含依赖项: sfArea: columns: id: integer name: string sfCity: columns: name: string area_id: integer relations: Area: class: sfArea local: area_id foreignType: many

在我的DB模式中,有几个表将与父表相关。解决关系的“丑陋”方法是在模式中手动包含依赖项:

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
但是,每次我将添加一个类以附加到该区域时,我都需要添加该关系以及与之相关的所有行(copy/paste=>future hell)。这就是我决定使用Doctrine_模板的地方,它允许我实现同样的目标:

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->Cities在“sfArea”上给出错误“未知记录属性/相关组件”Cities”)

如何创建其他关系?我甚至尝试过(没有成功):


我认为你有一个很大的模型问题,在数据库中表示这种hirearchy只会让你头疼。我正在为一个主要网站做一些维护工作,这个网站有类似的东西,简直就是地狱

我的建议是,如果真的需要在数据库中使用hirearchy,或者您在对关系数据库建模时正在考虑对象,请仔细考虑并重新分析

根据您在示例中提供的信息,City和看起来像“Categories”,因此如果您将它们放在参考表中,就可以对一个区域进行分类,从而最大限度地减少代码复制。一个类别可能有其他关系,或者只是一个包含许多字段的大表

下面是我建议的模式(推进模式):

使用mode_class_name作为提示,了解如何处理原始数据,您可以执行以下操作:

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

RealObjectRepresentation1 >>
 public function __construct(Category $category)
 {
   //Initialize proper object using category information
 }
因此,通过这种方式,您已经将DatabaseHirearchy移动到了PhpObjectHirearchy


希望这对你有所帮助,如果你需要更多的细节,我很乐意帮助你

到目前为止,为了记录在案,我的最佳猜测是在模式文件中手动执行。由于Nathan提到的模式很少改变,因此我认为如果行为无法实现(我将继续尝试作为一个辅助项目来实现),这是最好的方法。行为方法的好处在于,它可以在依赖于该中心对象的所有对象之间自动且一致地生成与特定中心对象的关系

另一个有用的例子是多站点博客引擎,例如,所有帖子、用户、类别、媒体上传等等。。。与特定博客相关

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

不幸的是,如果没有至少一些额外的定义,我不认为有任何方法可以做到这一点*。这样做的一种方法需要最少的添加,即通过选项枚举区域上的关系:

Area:
  options:
    models_with_areas: [Cities, Items]
然后在
区域::设置中附加关系

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/教义哲学的一个核心原则是不要重复你自己。这一解决方案坚持这一观点。如果在区域相关的类之间共享逻辑,它还提供了显著的好处


*除了一个丑陋的表外:您可以遍历每个表并找到任何与模板区域相关的表。这将需要在每次加载区域记录时实例化每个表,这听起来绝对是个糟糕的主意。

Hmm我认为模式版本应该可以工作。。。我看到的唯一问题是,您的
外国别名
对于每个类别都应该是不同的,即
城市
项目
。另一方面,硬编码的版本有问题。嗨,是的,更正了错误(我的原始代码中没有错误,就在这里)。这是我的大问题,为了避免大量手动复制粘贴,我想让与区域相关的模板正常工作。为了避免少量复制/粘贴/键入,似乎需要做很多工作。我不知道,我的模式不会经常改变。不过,我想知道我的方法中有哪些地方不正确。它应该可以工作,不是吗?1)你调试了$this->_选项['foreignAlias']吗?设置好了吗?2) 您是否在更改任何内容后重建了sfArea的模式、模型等?您好,我想您误解了我在问题中表达的真正问题。此外,City和Item实际上是完全不相关的对象,它们有很多列,而不仅仅是一个名称(并且不仅有2个,还有10到15个)。因此,使用您的方法,我将得到一个有200列的表。就性能而言,这并不理想,而且我认为,如果我们想要优化查询,那么根据实际对象选择适当的列可能会导致错误。
Area:
  options:
    models_with_areas: [Cities, Items]
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'
    ));
  }
}