Menu

26.显示动作流

本节说明

  • 对应视频第 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_replycreated_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>

查看个人页面:
file
尝试回复某个话题:
file
我们把最新的显示在最前面,所以按照日期倒序:
forum\app\Http\Controllers\ProfilesController.php

.
.
$activities = $user->activity()->latest()->with('subject')->get();
.
.

刷新页面:
file
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);
    }
}

刷新页面;
file
我们看到页面按照倒序逐条显示动作流,让我们来动点小手段,让动作流按日期分组:同一天的动作流显示在一起。修改控制器:
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

刷新页面查看效果:
file
我们已经说过,以后我们会有其他类型的动作流,所以我们的动作局部视图需要修改,因为局部视图中都是重复的代码。我们将这部分重复的代码封装成一个可复用的组件,也就是 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

刷新页面,一切正常:
file
嗯,也许我们只想显示最近的 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');
        });

    }
}

再次刷新页面:
file

本文章首发在 Laravel China 社区
上一篇 下一篇
讨论数量: 0
发起讨论


暂无话题~