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

who*_*boy 18 php mysql laravel laravel-5.1

我有两个模型,我想合并到一个时间轴.我已经能够通过在mysql中创建一个规范化和联合表的视图来实现这一点.我为这个视图创建了一个模型NewsFeed.如果我不想要相关Comment模型,这很有效.通过覆盖getMorphClass模型上的方法,我已经接近了这一点.这允许我获取图片的相关注释,但不能获得帖子,因为在getMorphClass调用时模型没有任何数据.

我对如何解决这个问题的方法持开放态度,而不仅仅是我提出的方式,但我不想从数据库中提取比我更多的数据.

新闻源

    <?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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

MySQL视图

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`;
Run Code Online (Sandbox Code Playgroud)

图片表

    id
    user_id
    title
    img
    img_width
    img_height
    img_other
    description
    created_at
    updated_at
Run Code Online (Sandbox Code Playgroud)

帖子

    id
    user_id
    title
    body
    created_at
    updated_at
Run Code Online (Sandbox Code Playgroud)

Tri*_*rip 8

您真的很接近构建视图的想法.实际上,如果您创建一个实际的表而不是视图,则解决方案变得非常简单.

使用指向Post类或Picture类的"FeedItem"多态对象,可以将注释直接附加到具有hasMany关系的FeedItem.

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');
    }
}
Run Code Online (Sandbox Code Playgroud)

此解决方案可能需要对表单进行一些重构,因为您需要为每个Post条目和Picture条目创建一个FeedItem条目.Picture :: created和Post :: created的事件监听器应该起作用(http://laravel.com/docs/5.1/eloquent#events).

设置完成后,您可以使用:

FeedItem::with('comments')->orderBy('created_at','desc')->paginate(15);
Run Code Online (Sandbox Code Playgroud)