Две модели в один разбитый на страницы запрос с активными загруженными отношениями с использованием Laravel
У меня есть две Модели, которые я хотел бы объединить в одну временную шкалу. Я смог сделать это, создав представление в mysql, которое нормализует и объединяет таблицы. Я создал модель для этого вида, NewsFeed
. Это хорошо работает, если мне не нужна соответствующая модель Comment
. Я подошел к этому, переопределив метод getMorphClass
модели. Это позволяет мне получать связанные комментарии для изображений, но не постов, потому что, когда getMorphClass
называется модель, у нее нет данных.
Я открыт для любого подхода к решению этой проблемы, а не только по тому, как я предлагаю, но я не хочу извлекать больше данных, чем я должен из базы данных.
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
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`;
таблица изображений
id
user_id
title
img
img_width
img_height
img_other
description
created_at
updated_at
сообщения
id
user_id
title
body
created_at
updated_at
Ответы
Ответ 1
Вы действительно близки своей идее построить представление. Фактически, если вы создаете фактическую таблицу вместо представления, решение становится довольно простым.
С полиморфным объектом FeedItem, который указывает на ваш класс Post или Picture, вы можете присоединить комментарии непосредственно к FeedItem с помощью отношения hasMany.
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');
}
}
Это решение может потребовать некоторого рефакторинга в ваших формах, так как вам нужно будет создать запись FeedItem для каждой записи Post и Picture. Слушатели событий для Picture:: created и Post:: created должны делать трюк (http://laravel.com/docs/5.1/eloquent#events).
После настройки вы можете использовать:
FeedItem::with('comments')->orderBy('created_at','desc')->paginate(15);
Ответ 2
Хотя я не знаком с Laravel или Eloquent на этот счет, вот мой вклад в это.
Предполагая, что вы получаете результат из этого представления SQL в $Entries
Как я понимаю, Eloquent позволяет вам устанавливать значения для себя, поэтому для вас может быть что-то вроде этого (я не уверен в синтаксисе или использовании в этом отношении).
$Collection = [];
foreach( $Entries as $Entry ) {
if( $Entry->type === 'post' ) {
$Collection[] = new Post($Entry->toArray())->with('comments');
}else{
$Collection[] = new Picture($Entry->toArray())->with('comments');
}
}
return $Collection;