Laravel6.X收藏功能开发

收藏功能就是收藏文章或者商品等内容,在用户面板上显示收藏以便用户随时查看或者购买。为了达到这个功能,我们需要创建用户和内容相对应的表,一个用户可以收藏很多内容,很多内容也可以被很多用户收藏。表里的结构应该是,收藏ID,用户ID,内容ID,收藏时间等等。下面我们就来开发这个功能:

1.创建表

执行命令:

php artisan make:migration create_user_favorites_table --create=user_favorites

生成迁移文件,--create这个后缀是设定表名。假设我们让用户收藏文章,有一个articles这个表。我们来编辑一下生成的迁移文件:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUserFavoritesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('user_favorites', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('user_id');
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->unsignedBigInteger('article_id'); $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('user_favorites');
    }
}

注意一下外键的写法:foregin=>referrences=>on=>onDelete
执行迁移:

php artisan migrate

2.关联模型文件

在App\User模型文件里增加这句:

public function favoriteArticles()
    {
        return $this->belongsToMany(Article::class, 'user_favorites')
            ->withTimestamps()
            ->orderBy('user_favorites.created_at', 'desc');
    }

belongsToMany说明是多对多的关联,第二个参数是中间表的表名,withTimestamps()表明中间表有时间戳的字段,orderBy('user_favorites.created_at', 'desc')代表默认的时间排序方式是中间表的创建时间倒序排序。

3.在控制器里写接口逻辑

逻辑很简单,用户可以收藏,也可以取消收藏,如果收藏了就不必重复收藏,如果取消收藏了就不必再取消,如果收藏了才能取消收藏。在AritclesController里面写具体方法:

public function favor(Article $article, Request $request)
    {
        $user = $request->user();
        if ($user->favoriteProducts()->find($article->id)) {
            return [];
        }
//当前用户是否已经收藏了此文章,如果已经收藏则不做任何操作直接返回

        $user->favoriteArticles()->attach($article);

//attach() 方法将当前用户和此商品关联起来, 参数可以是模型的 id,也可以是模型对象本身,因此这里还可以写成 attach($article->id)。
        return [];
    }

接下来是取消收藏的接口方法:

public function disfavor(Article $article, Request $request)
    {
        $user = $request->user();
        $user->favoriteProducts()->detach($product);
//detach() 方法用于取消多对多的关联,接受的参数个数与 attach() 方法一致
        return [];
    }

4.路由设置

Route::group(['middleware' => ['auth', 'verified']], function() {
     //中间件auth, verified是必须要登录和验证邮箱的中间件
    Route::post('articles/{article}/favorite', 'ArticlesController@favor')->name('articles.favor');
    Route::delete('articles/{article}/favorite', 'ArticlesController@disfavor')->name('article.disfavor');
});

5.前端收藏按钮

$(document).ready(function () {
    // 监听收藏按钮的点击事件
    $('.favor-btn').click(function () {
      // 发起一个 post ajax 请求,请求 url 通过后端的 route() 函数生成。
      // 这里用的是axios框架
      axios.post('{{ route('articles.favor', ['article' => $article->id]) }}')
        .then(function () { // 请求成功会执行这个回调
          swal('操作成功', '', 'success');
          swal是一个封装的模态提示窗口
        }, function(error) { // 请求失败会执行这个回调
          // 如果返回码是 401 代表没登录
          if (error.response && error.response.status === 401) {
            swal('请先登录', '', 'error');
          } else if (error.response && (error.response.data.msg || error.response.data.message)) {
            // 其他有 msg 或者 message 字段的情况,将 msg 提示给用户
            swal(error.response.data.msg ? error.response.data.msg : error.response.data.message, '', 'error');
          }  else {
            // 其他情况应该是系统挂了
            swal('系统错误', '', 'error');
          }
        });
    });
  });
</script>

6.取消收藏按钮

接下来我们要在页面添加取消收藏按钮及其功能,对于已经收藏了当前文章的用户,我们要展示取消收藏按钮,因此需要在控制器中把收藏状态注入到模板中,此时我们返回的是一个布尔值。用户未登录时返回的是null, 用户登录而且文章被收藏的情况下返回的也是false,也就是取消收藏按钮。

先做控制器ArticlesController.php逻辑:

public function show(Article $article, Request $request)
    {
        $favored = false;
        // 用户未登录时返回的是 null,已登录时返回的是对应的用户对象
        if($user = $request->user()) {
            // 从当前用户已收藏的文章中搜索 id 为当前文章的 id
            // boolval() 函数用于把值转为布尔值
            $favored = boolval($user->favoriteArticles()->find($article->id));
        }

        return view('articles.show', ['article' => $article, 'favored' => $favored]);
    }

这里我们是把原来的单页文章的show方法修改了下。

7.修改收藏按钮的显示方式

我们主要是要判断传递的$favored这个变量是否是true。

 <div class="buttons">
          @if($favored)
            <button class="btn btn-danger disfavor-btn">取消收藏</button>
          @else
            <button class="btn btn-success favor-btn">❤ 收藏</button>
          @endif
 </div>

然后我们在把取消收藏的ajax写一下:

$(document).ready(function () {
    $('disfavor-btn').click(function () {
      axios.delete('{{ route('articles.disfavor', ['article' => $product->id]) }}')
        .then(function () {
          swal('操作成功', '', 'success')
            .then(function () {
              location.reload();
            });
        });
    });

  })
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容

  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,389评论 0 17
  • 每天进步一点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点~~从开始只能写几句话、模仿别人的观点,到现...
    一个帅气的名字呀阅读 18,072评论 4 31
  • 骑公路车的骚年对我说,只要破风够帅,她就能回到从前, 山吧大佬曾对我说,只要穿梭得够快,就能骗过匆匆流逝的时光。 ...
    初恋_8e2b阅读 142评论 0 0
  • 独自走在幽深的路上,会让人着迷的是,两旁的风景 而正在玩乐的少年们,保持着心态去努力的结果,要多于你...
    鲲鹏万里_5948阅读 128评论 0 2
  • 音乐如虹 一 如果说彩虹有七种颜色,那下面的七组歌手便是我对音乐最美的感触。 红色:东方神起。 不可否认,当今的韩...
    水草肃Gloria阅读 348评论 0 0