doulieyu0881 2015-10-26 20:11
浏览 193
已采纳

使用Laravel将两个模型组合成一个带有急切加载关系的分页查询

I have two Models that I would like to merge into one timeline. I have been able to do this by creating a View in mysql that normalizes and unions the tables. I created a Model for this view, NewsFeed. This works well if I do not want related Comment model. I have gotten close to this by overriding the getMorphClass method on the model. This allows me to get the related comments for the pictures, but not the posts, because when getMorphClass is called the model doesn't have any data.

I am open to any approach on how to solve this, not just the way I am proposing, but I don't want to pull more data than I have to from the database.

NewsFeed

    <?php

    namespace App\Users;

    use App\Pictures\Picture;
    use App\Social\Comments\CommentableTrait;
    use App\Posts\Post;
    use App\Users\User;
    use Illuminate\Database\Eloquent\Model;

    class UserFeed extends Model
    {
        use CommentableTrait;

        public function user()
        {
            return $this->belongsTo(User::class);
        }

        public function getMorphClass(){
            if ($this->type == 'post'){
                return Post::class;
            }
            return Picture::class;
        }
    }

MySQL View

CREATE VIEW 
   `user_feeds`
AS SELECT
   `posts`.`id` AS `id`,
   `posts`.`user_id` AS `user_id`,
   'post' AS `type`,
   NULL AS `name`,
   NULL AS `thumbnail`,
   `posts`.`body` AS `body`,
   `posts`.`updated_at` AS `updated_at`,
   `posts`.`created_at` AS `created_at`
FROM 
    `posts` 
UNION SELECT
    `pictures`.`id` AS `id`,
    `pictures`.`user_id` AS `user_id`,
    'picture' AS `type`,
    `pictures`.`name` AS `name`,
    `pictures`.`thumbnail` AS `thumbnail`,
    `pictures`.`description` AS `body`,
    `pictures`.`updated_at` AS `updated_at`,
    `pictures`.`created_at` AS `created_at` 
FROM
    `pictures`;

pictures table

    id
    user_id
    title
    img
    img_width
    img_height
    img_other
    description
    created_at
    updated_at

posts

    id
    user_id
    title
    body
    created_at
    updated_at
  • 写回答

2条回答 默认 最新

  • dscrb00804 2015-11-01 06:35
    关注

    You are really close with your idea to build a view. In fact, if you create an actual table instead of a view, the solution becomes quite simple.

    With a 'FeedItem' polymorph object that points to your Post class or Picture class, you can attach the comments directly to the FeedItem with a hasMany relationship.

    class FeedItem extends Model {
        use CommentableTrait;
        public function feedable()
        {
            return $this->morphTo();
        }
    }
    
    class Post extends Model {
        public function feeditem()
        {
            return $this->morphOne('FeedItem', 'feedable');
        }
    }
    
    class Picture extends Model {
        public function feeditem()
        {
            return $this->morphOne('FeedItem', 'feedable');
        }
    }
    

    This solution may require some refactoring on your forms since you will need to create a FeedItem entry for each Post entry and Picture entry. Event listeners for Picture::created and Post::created should do the trick (http://laravel.com/docs/5.1/eloquent#events).

    Once it's set up, you can use:

    FeedItem::with('comments')->orderBy('created_at','desc')->paginate(15);
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 Matlab问题解答有两个问题
  • ¥50 Oracle Kubernetes服务器集群主节点无法访问,工作节点可以访问
  • ¥15 LCD12864中文显示
  • ¥15 在使用CH341SER.EXE时不小心把所有驱动文件删除了怎么解决
  • ¥15 gsoap生成onvif框架
  • ¥15 有关sql server business intellige安装,包括SSDT、SSMS。
  • ¥15 stm32的can接口不能收发数据
  • ¥15 目标检测算法移植到arm开发板
  • ¥15 利用JD51设计温度报警系统
  • ¥15 快手联盟怎么快速的跑出建立模型