symfony + doctrine + inheritance,如何使它们工作?

时间:2010-05-05 13:32:26

标签: php inheritance symfony1 doctrine

我开始使用Symfony,我发现了一些关于继承的文档。但也发现了this discouraging article,这让我怀疑Doctrine是否处理任何好的继承......

有没有人在Symfony + Doctrine中找到智能的继承解决方案?

作为一个例子,我已经构建了类似这样的数据库:

CREATE TABLE `poster` (
  `poster_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(50) NOT NULL,
  PRIMARY KEY (`poster_id`),
  UNIQUE KEY `id` (`poster_id`),
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;

CREATE TABLE `user` (
  `user_id` int(11) NOT NULL,
  `real_name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`user_id`),
  UNIQUE KEY `user_id` (`user_id`),
  CONSTRAINT `user_fk` FOREIGN KEY (`user_id`) REFERENCES `poster` (`poster_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

由此,Doctrine生成了这个“schema.yml”:

Poster:
  connection: doctrine
  tableName: poster
  columns:
    poster_id:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: true
    user_name:
      type: string(50)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
  relations:
    Post:
      local: poster_id
      foreign: poster_id
      type: many
    User:
      local: poster_id
      foreign: user_id
      type: many
    Version:
      local: poster_id
      foreign: poster_id
      type: many
User:
  connection: doctrine
  tableName: user
  columns:
    user_id:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: false
    real_name:
      type: string(50)
      fixed: false
      unsigned: false
      primary: false
      notnull: false
      autoincrement: false
  relations:
    Poster:
      local: user_id
      foreign: poster_id
      type: one

使用Doctrine自动生成的表单为此结构创建用户不起作用。

任何线索都将受到赞赏。

2 个答案:

答案 0 :(得分:2)

在使用列聚合和具体继承的项目工作几个月之后,我只能说一件事:远离具体的继承!真。

假设您有3个表:媒体和视频/音频,它继承自Media。你希望能够做到这样的事情:

Doctrine_Query::create()
    ->from('Media m')
    ->execute();

嗯它不适用于具体的继承。除了模型继承方法之外,它几乎没有价值,几乎没有实际用途。

另一方面,通过列聚合,Media表将自动添加“type”列,并使您能够执行以下操作:

Doctrine_Query::create()
    ->from('Video v')
    ->execute();

将返回Video对象集合。但你也可以这样做:

Doctrine_Query::create()
    ->from('Media m')
    ->execute();

您将获得视频和音频对象的混合结果。

无论如何你应该检查doctrine documentation。 但要小心,因为继承和教义很快就会变得麻烦。

答案 1 :(得分:0)

将“视频”数据与“音频”数据分开但仍然使用相同的表存储“媒体”的解决方案如下:

Media:
  columns:
    name: { type: string(255), notnull: true }
    description: { type: text }

Video:
  inheritance:
    type: column_aggregation
    keyField: type
    keyValue: video

Audio:
  inheritance:
    type: column_aggregation
    keyField: type
    keyValue: audio

VideoData:
  columns:
    resolution_x: { type: integer, notnull: true }
    resolution_y: { type: integer, notnull: true }
  relations:
    Video: { foreignAlias: Data, onDelete: CASCADE }

AudioData:
  columns:
    sample_rate: { type: integer, notnull: true }
  relations:
    Audio: { foreignAlias: Data, onDelete: CASCADE }

类似的东西......这样你可以将所有'Media'存储在一个表中,并按照上面提到的DuoSRX获取它,并且仍然没有该表中的无关数据。当然你必须加入它,但索引的外键根本不应该是性能损失。