Laravel6.X收藏功能开发

2019-12-29  本文已影响0人  前端组件库

收藏功能就是收藏文章或者商品等内容,在用户面板上显示收藏以便用户随时查看或者购买。为了达到这个功能,我们需要创建用户和内容相对应的表,一个用户可以收藏很多内容,很多内容也可以被很多用户收藏。表里的结构应该是,收藏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();
            });
        });
    });

  })
上一篇 下一篇

猜你喜欢

热点阅读