实现收藏的流程
打赏作者

kanjiushi

这里后面应该再加一节ajax吧?

sswowo

收藏一下 或者 取消收藏 必须 刷新 这点没讲 新手可能蒙逼的

sswowo

其实 你应该好好讲讲 lists(); attach(); sync(); 这些 方法…

JellyBool

OK,我后面接着讲吧 @sswowo

liudong0763

老师,谢谢你一直的认真解答,我想给你的视频提点小小的建议,我希望每个系列的视频以及每个小视频的开头,能花一些时间大概讲一下实现的原理及流程,然后再进入实战敲代码阶段,这样我觉得对视频的质量,教学的效果以及我们学员对视频的学习理解我认为会好很多,希望老师能考虑。

Kwong Yan Chan 回复 liudong0763

这个我也同意啊。 先粗略说一说 流程原理,然后在来敲一下代码 会理解更快,赞一个

Kwong Yan Chan

代码逻辑体有点出入,但不管了 。至少最后效果是一致的

Kwong Yan Chan

02:实现收藏流程

  • 页面上增加收藏按钮,
@extends('app')
@section('content')
    {--chunk(3)这里实现的是每一行显示三个,就是把一个大数据分整3个一组的大二维数组--}
    @foreach( $lessons->chunk(3) as $row )
        <div class="row">
        @foreach( $row as $lesson )
            <article class="col-md-4">
                <h2>
                    { $lesson->title }
                </h2>
                <img src="{$lesson->image}" width="360" alt="">
                <div class="body">
                    <form action="/favorite" method="post">
                        { csrf_token() }
                        <input type="hidden" name="lesson_id" value="{ $lesson->id }">
                        <button type="submit" class="btn btn-primary">收藏</button>
                    </form>
                    {--下面增加--}

                    { $lesson->intro }
                </div>
            </article>
            @endforeach
        </div>
    @endforeach
    {!! $lessons->appends( ['type'=>'article'] )->render() !!}
    @stop
  • 终端命令生成控制器
php artisan make:controller FavoritesController
  • 注册路由
Route::resource( '/favorite','FavoritesController' );
  • 收藏控制器中store方法增加代码
public function store(Request $request)
{
    Auth::user()->favorites()->attach( $request->get( 'lesson_id' ) );

    return redirect()->back();
}
  • 到这一步测试,遇到三个问题,分别解决
    • 第一个问题,是页面token问题,我直接使用的是表单,并没有使用FORM那个插件,页面token使用错误,更正为:
    <form action="/favorite" method="post">
        { csrf_field() }
        <input type="hidden" name="lesson_id" value="{ $lesson->id }">
        <button type="submit" class="btn btn-primary">收藏</button>
    </form>
    
    • 第二个问题,传入控制器报错Auth没有找到,更改为:
    public function store(Request $request)
    {
    //Auth前面加反斜杠,问题解决,顺利入库
        \Auth::user()->favorites()->attach( $request->get( 'lesson_id' ) );
    
        return redirect()->back();
    }
    
    • 第三个问题,视频中提到的需要把created_atupdated_at也需要写入数据库,在用户模型方法中的favorites修改为:
    public function favorites()
    {
        return $this->belongsToMany(Lesson::class,'favorites')->withTimestamps();//后面再增加一个链式操作
    }
    
  • 增加收藏样式,由于没有使用字体图标,所以直接判断,使用bt样式进行变色
<form action="/favorite" method="post">
    { csrf_field() }
    <input type="hidden" name="lesson_id" value="{ $lesson->id }">
    <button type="submit" class="btn { in_array( $lesson->id,$favorites ) ? 'btn-success' : 'btn-primary' }">收藏</button>
</form>
  • 刷新页面,报错favorites变量没定义,路由处定义
$favorites = \App\Favorite::where( 'user_id',Auth::user()->id )
                            ->lists('lesson_id')->ToArray();
return view( 'lessons.index',compact('lessons','favorites'));
  • 定义好后,刷新页面,竟然报lessons未定义
    • 最后找不到解决办法,已经开始怀疑传值的compact有问题,开始怀疑一个对象集一个是数组集合,这样使用compact传值是不是有问题,后来并没有找到相关资料
    • 解决办法,我使用了with数组传值解决这一错误,
    Route::get('/lessons',function(){
    $lessons = \App\Lesson::latest()->paginate(15);#根据最近时间文章排序,取出每页15行数据
    $favorites = \App\Favorite::where( 'user_id',Auth::user()->id )
                            ->lists('lesson_id')->ToArray();
    //使用compact传两个参数错误,怀疑是一个对象一个只是数组出错[自我怀疑,没有搜索到资料证实]
    //使用with传值,无错误
        return view( 'lessons.index')->with(['lessons'=>$lessons,'favorites'=>$favorites]);
    });
    
  • 重新定义页面,增加判断,加入取消收藏表单,直接表单,没有使用视频中讲师的插件包
@extends('app')
@section('content')
    @foreach( $lessons->chunk(3) as $row )
        <div class="row">
        @foreach( $row as $lesson )
            <article class="col-md-4">
                <h2>
                    { $lesson->title }
                </h2>
                <img src="{$lesson->image}" width="360" alt="">
                <div class="body">
                    @if( in_array( $lesson->id,$favorites )  )
                        <form action="/favorite/{$lesson->id}" method="POST">
                            <input type="hidden" name="_method" value="DELETE">
                    @else
                        <form action="/favorite" method="post">
                    @endif
                            { csrf_field() }
                            <input type="hidden" name="lesson_id" value="{ $lesson->id }">
                            <button type="submit" class="{ in_array( $lesson->id,$favorites ) ? 'btn btn-success' : 'btn btn-primary' }">收藏</button>
                        </form>
                    { $lesson->intro }
                </div>
            </article>
            @endforeach
        </div>
    @endforeach
    {!! $lessons->render() !!}
    @stop
  • 控制器删除方法增加代码
public function destroy($id)
{
    \Auth::user()->favorites()->detach( $id );

    return redirect()->back();
}
  • 为了实现登录限制,所以
    • 登录后才能显示收藏按钮,页面增加判断
    @if( Auth::check() )
    //收藏表单html代码
    @endif
    
    • 控制器增加构造方法
    public function __construct()
    {
        $this->middleware('auth');
    }
    
    • 同事也需要修改路由判断
    Route::get('/lessons',function(){
        $lessons = \App\Lesson::latest()->paginate(15);#根据最近时间文章排序,取出每页15行数据
        //检查是否登录,跟视频会有出入,但效果实现一致
        if( Auth::check() ){
            $favorites = \App\Favorite::where( 'user_id',Auth::user()->id )
                ->lists('lesson_id')->ToArray();
            //使用compact传两个参数错误,怀疑是一个对象一个只是数组出错
            //使用with传值,无错误
            return view( 'lessons.index')->with(['lessons'=>$lessons,'favorites'=>$favorites]);
        }else{
            return view( 'lessons.index')->with('lessons',$lessons);
    
        }
    });
    
  • 显示用户自己的收藏列表,具体就需要自己做列表显示了,这里忽略
public function index()
{
    \Auth::user()->favorites();
}
  • 最后测试收藏与取消收藏
    • 按钮颜色变换:成功
    • 数据库增减数据:成功
    • PS:嗯,整体效果跟视频一样
hweining 回复 Kwong Yan Chan

很好啊 分析很详细

Kwong Yan Chan 回复 hweining

大哥当然纤细了啊 。 跟着视频做的 并且写笔记了

JellyBool 回复 Kwong Yan Chan

这波没毛病!

JoouA

教主,显示个人收藏的文章的顺序如何根据收藏的时间先后来进行排序展示啊

JellyBool 回复 JoouA

直接 latest() 应该就可以了,或者 orderBy 也是ok 的

JoouA 回复 JellyBool

latest()和orderBy()都是判断的posts这个表中的时间,和收藏的时间没关系。我是想按照favourites这个表的时间来排列文章,favorites表中有id、user_id、post_id、created_at、updated_at这四个字段,我想根据created_at这个时间来显示收藏的文章顺序。

JellyBool 回复 JoouA

类似这样的代码:

$user->favotites()->orderBy('created_at');
// 或者
$user->favorites()->latest('created_at')