【问题标题】:How should I define my polymorphic tables?我应该如何定义我的多态表?
【发布时间】:2014-05-03 09:41:40
【问题描述】:

我有一个帖子表,可以是视频帖子、文字帖子或图片帖子,并且帖子属于一个组。我认为多态关系是正确的方法,但我的表看起来有点奇怪。

我的帖子表:

+---------------+------------------+------+-----+---------------------+----------------+
| Field         | Type             | Null | Key | Default             | Extra          |
+---------------+------------------+------+-----+---------------------+----------------+
| id            | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| postable_id   | int(10) unsigned | NO   |     | NULL                |                |
| postable_type | varchar(255)     | NO   |     | NULL                |                |
| group_id      | int(10) unsigned | NO   | MUL | NULL                |                |
| upvotes       | int(10) unsigned | NO   |     | 0                   |                |
| downvotes     | int(10) unsigned | NO   |     | 0                   |                |
| created_at    | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at    | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+---------------+------------------+------+-----+---------------------+----------------+

text_posts 表:

+------------+------------------+------+-----+---------------------+----------------+
| Field      | Type             | Null | Key | Default             | Extra          |
+------------+------------------+------+-----+---------------------+----------------+
| id         | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| title      | varchar(130)     | NO   |     | NULL                |                |
| body       | text             | NO   |     | NULL                |                |
| created_at | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+------------+------------------+------+-----+---------------------+----------------+

video_posts 表:

+------------+------------------+------+-----+---------------------+----------------+
| Field      | Type             | Null | Key | Default             | Extra          |
+------------+------------------+------+-----+---------------------+----------------+
| id         | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| title      | varchar(130)     | NO   |     | NULL                |                |
| path       | varchar(255)     | NO   |     | NULL                |                |
| body       | varchar(255)     | YES  |     | NULL                |                |
| created_at | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+------------+------------------+------+-----+---------------------+----------------+

picture_posts 表:

+-------------+------------------+------+-----+---------------------+----------------+
| Field       | Type             | Null | Key | Default             | Extra          |
+-------------+------------------+------+-----+---------------------+----------------+
| id          | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| path        | varchar(255)     | NO   |     | NULL                |                |
| body        | varchar(255)     | YES  |     | NULL                |                |
| is_external | tinyint(1)       | NO   |     | NULL                |                |
| created_at  | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at  | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+-------------+------------------+------+-----+---------------------+----------------+


我查看了来自 laravel.com 的示例。它指出“多态关系允许一个模型在一个关联上属于多个其他模型。”但在这种情况下,我的“帖子”不应该属于“视频帖子”或“文本帖子”等。而是'视频帖子'或类似内容应属于'帖子'。如何改进我的表格??

【问题讨论】:

    标签: database laravel


    【解决方案1】:

    貌似Many To Many多态关系:

    根据您有问题的表,您的公用表是posts,并且您希望在其他三个不同实体(表)之间建立关系,换句话说,所有三个表(textsvideospictures)都将共享posts 表,例如,您有三个这样的表(每个表都以idPrimary Key):

    texts  table   |
    videos table   |--- posts
    pictures table |
    

    每个表都应该与posts 表相关,因此您需要三个单独的表和每个like 的三个模型;

    Table                  | Other Personal Fields   |  Model
    ------------------------------------------------------------
    texts (with id PK)     | title, body             |  Text
    videos (with id PK)    | title, path, body       |  Video
    pictures (with id PK)  | path, body, is_external |  Picture
    

    主/公用表是posts,把所有公用字段都放在这个表里:

    id (PK)       |
    group_id      |
    upvotes       |--- These are common/sharable fields by other three models
    downvotes     |
    created_at    |
    updated_at    |
    

    第四张表postablesPOST 与所有其他人(文本、视频和图片)之间的关系:

    post_id       | Always id of posts table
                  | These two fields will build relation
    postable_id   | id of texts or videos or pictures
    postable_type | The model/type: Text/Video/Picture
    

    Post相反的三个模型:

    // Text: In the postables table postable_id
    // will be texts_id and type will be Text for text_post
    class Text extends Eloquent {
        public function posts()
        {
            return $this->morphToMany('Post', 'postable');
        }
    }
    
    // Video: in the postables table postable_id will
    // be videos_id and type will be Video for video_post
    class Video extends Eloquent {
        public function posts()
        {
            return $this->morphToMany('Post', 'postable');
        }
    }
    
    // Picture: in the postables table postable_id will
    // be pictures_id and type will be Picture for picture_post
    class Picture extends Eloquent {
        public function posts()
        {
            return $this->morphToMany('Post', 'postable');
        }
    }
    

    Post 模型:

    class Post extends Eloquent {
    
        public function texts()
        {
            return $this->morphedByMany('Text', 'postable');
        }
    
        public function videos()
        {
            return $this->morphedByMany('Video', 'postable');
        }
    
        public function pictures()
        {
            return $this->morphedByMany('Picture', 'postable');
        }
    }
    

    postables 表中的数据可能是这样的:

    post_id | postable_id  |  postable_type
    ---------------------------------------
       1    |      1       |      Text      // In postable_id 1 is id of texts table
       1    |      1       |      Video     // In postable_id 1 is id of videos table
       1    |      1       |      Picture   // In postable_id 1 is id of pictueres table
       2    |      3       |      Text      // In postable_id 3 is id of texts table
    

    用法:

    $post = Post::find(1);
    $postsHastTextPosts = $post->texts();
    

    反向使用(Text):

    $text = Text::find(1);
    $text->posts()->first()->group_id;
    $text->posts()->first()->upvotes;
    

    反向使用(Video):

    $vdo = Video::find(1);
    $vdo->posts()->first()->group_id;
    $vdo->posts()->first()->upvotes;
    

    反向使用(Picture):

    $picture = Picture::find(1);
    $picture->posts()->first()->group_id;
    $picture->posts()->first()->upvotes;
    

    这可以使用many to many 多态关系来完成。所有三种模型(TextVideoPicture)都可以共享相同的公共POST 属性,这意味着所有三种类型的模型都可以属于一组 (group_id)。

    在这个使用一个表 (postables) 的 many-to-many polymorphic 关系中,三个单独的 pivot 表(post_textpost_picturepost_video)已被排除在外。

    【讨论】:

    • 谢谢,但我有一个问题,是什么让它成为多对多多态而不是传统的多态关系??
    • 因为您与其他模型共享相同的东西,它更适合使用反向关系 many-to-many,但也可以通过其他方式完成,就像通常 many-to-manypivots 一样。跨度>
    • 那么传统的多态适用于什么情况,是不是不共享公用表的时候呢?
    • 我很少使用它,因为使用one-to-many 可以做类似的事情,例如,Photo 可能属于两个不同的模型,在这种情况下Laravel 给出了一个@987654367 的示例@ 关系,但我可以做同样的事情 using one-to-many,你只需尝试使用 one-to many/non-poly 来做 polymorphic 关系,你可以做到,你会弄明白的。
    猜你喜欢
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    相关资源
    最近更新 更多