26.显示动作流
- 本系列文章为
laracasts.com
的系列视频教程 ——Let's Build A Forum with Laravel and TDD 的学习笔记。若喜欢该系列视频,可去该网站订阅后下载该系列视频, 支持正版 ;- 视频源码地址:github.com/laracasts/Lets-Build-a-...;
- 本项目为一个 forum(论坛)项目,与本站的第二本实战教程 《Laravel 教程 - Web 开发实战进阶》 类似,可互相参照。
本节说明#
- 对应视频第 26 小节:How to Construct an Activity Feeds Part 2
本节内容#
本节我们重新构建个人页面,将动作流显示出来。首先我们修改控制器:
forum\app\Http\Controllers\ProfilesController.php
<?php
namespace App\Http\Controllers;
use App\User;
class ProfilesController extends Controller
{
public function show(User $user)
{
$activities = $user->activity()->with('subject')->get();
return view('profiles.show',[
'profileUser'=> $user,
'activities' => $activities
]);
}
}
进行模型关联:
forum\app\User.php
.
.
public function activity()
{
return $this->hasMany(Activity::class);
}
}
修改个人页面:
forum\resources\views\profiles\show.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-offset-2">
<div class="page-header">
<h1>
{{ $profileUser->name }}
<small>注册于{{ $profileUser->created_at->diffForHumans() }}</small>
</h1>
</div>
@foreach($activities as $activity)
@include("profiles.activities.{$activity->type}")
@endforeach
</div>
</div>
</div>
@endsection
我们根据不同的动作类型,引入不同类型动作的局部视图:
@include("profiles.activities.{$activity->type}")
目前我们的动作有 2 个:created_reply
和 created_thread
,所以当前的局部视图有两个。
forum\resources\views\profiles\activities\created_reply.blade.php
<div class="panel panel-default">
<div class="panel-heading">
<div class="level">
<span class="flex">
{{ $profileUser->name }} 发表了回复
</span>
</div>
</div>
<div class="panel-body">
{{ $activity->subject->body }}
</div>
</div>
forum\resources\views\profiles\activities\created_thread.blade.php
<div class="panel panel-default">
<div class="panel-heading">
<div class="level">
<span class="flex">
{{ $profileUser->name }} 发表了话题
</span>
</div>
</div>
<div class="panel-body">
{{ $activity->subject->body }}
</div>
</div>
查看个人页面:
尝试回复某个话题:
我们把最新的显示在最前面,所以按照日期倒序:
forum\app\Http\Controllers\ProfilesController.php
.
.
$activities = $user->activity()->latest()->with('subject')->get();
.
.
刷新页面:
ok,现在进行下一步,优化个人页面显示的信息:
forum\resources\views\profiles\activities\created_thread.blade.php
<div class="panel panel-default">
<div class="panel-heading">
<div class="level">
<span class="flex">
{{ $profileUser->name }} 发表了
<a href="{{ $activity->subject->path() }}">{{ $activity->subject->title }}</a>
</span>
</div>
</div>
<div class="panel-body">
{{ $activity->subject->body }}
</div>
</div>
在当前页面,$activity->subject
代表的是 thread
实例,所以我们可以使用 path()
方法来获取链接。再修改另一个局部视图:
forum\resources\views\profiles\activities\created_reply.blade.php
<div class="panel panel-default">
<div class="panel-heading">
<div class="level">
<span class="flex">
{{ $profileUser->name }} 回复了
<a href="{{ $activity->subject->thread->path() }}">{{ $activity->subject->thread->title }}</a>
</span>
</div>
</div>
<div class="panel-body">
{{ $activity->subject->body }}
</div>
</div>
如我们在之前说的,在这里 $activity->subjec
代表的是 reply
实例。我们使用 thread
关联关系来获取 thread
,所以要建立关联关系:
forum\app\Reply.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Reply extends Model
{
use Favoritable,RecordsActivity;
protected $guarded = [];
protected $with = ['owner','favorites'];
public function owner()
{
return $this->belongsTo(User::class,'user_id'); // 使用 user_id 字段进行模型关联
}
public function thread()
{
return $this->belongsTo(Thread::class);
}
}
刷新页面;
我们看到页面按照倒序逐条显示动作流,让我们来动点小手段,让动作流按日期分组:同一天的动作流显示在一起。修改控制器:
forum\app\Http\Controllers\ProfilesController.php
.
.
public function show(User $user)
{
$activities = $user->activity()->latest()->with('subject')->get()->groupBy(function ($activity){
return $activity->created_at->format('Y-m-d');
});
return view('profiles.show',[
'profileUser'=> $user,
'activities' => $activities
]);
}
.
.
修改显示页面:
forum\resources\views\profiles\show.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-offset-2">
<div class="page-header">
<h1>
{{ $profileUser->name }}
</h1>
</div>
@foreach($activities as $date => $activity)
<h3 class="page-header">{{ $date }}</h3>
@foreach($activity as $record)
@include("profiles.activities.{$record->type}",['activity' => $record])
@endforeach
@endforeach
</div>
</div>
</div>
@endsection
刷新页面查看效果:
我们已经说过,以后我们会有其他类型的动作流,所以我们的动作局部视图需要修改,因为局部视图中都是重复的代码。我们将这部分重复的代码封装成一个可复用的组件,也就是 Components :
forum\resources\views\profiles\activities\activity.blade.php
<div class="panel panel-default">
<div class="panel-heading">
<div class="level">
<span class="flex">
{{ $heading }}
</span>
</div>
</div>
<div class="panel-body">
{{ $body }}
</div>
</div>
重构两个局部视图:
forum\resources\views\profiles\activities\created_reply.blade.php
@component('profiles.activities.activity')
@slot('heading')
{{ $profileUser->name }} 回复了
<a href="{{ $activity->subject->thread->path() }}">{{ $activity->subject->thread->title }}</a>
@endslot
@slot('body')
{{ $activity->subject->body }}
@endslot
@endcomponent
forum\resources\views\profiles\activities\created_thread.blade.php
@component('profiles.activities.activity')
@slot('heading')
{{ $profileUser->name }} 发表了
<a href="{{ $activity->subject->path() }}">{{ $activity->subject->title }}</a>
@endslot
@slot('body')
{{ $activity->subject->body }}
@endslot
@endcomponent
刷新页面,一切正常:
嗯,也许我们只想显示最近的 50 个工作流。这取决于你的设计,但是我们设成取出最近的 50 条记录:
forum\app\Http\Controllers\ProfilesController.php
<?php
namespace App\Http\Controllers;
use App\User;
class ProfilesController extends Controller
{
public function show(User $user)
{
return view('profiles.show',[
'profileUser'=> $user,
'activities' => $this->getActivity($user)
]);
}
/**
* @param User $user
* @return static
*/
protected function getActivity(User $user)
{
return $user->activity()->latest()->with('subject')->take(50)->get()->groupBy(function ($activity) {
return $activity->created_at->format('Y-m-d');
});
}
}
再次刷新页面:
推荐文章: