Laravel 5.4 vue 实现收藏

laravel 5.4 vue 收藏文章#

最终实现效果#

file

创建项目#

本环境使用 Laragon 集成 php-7.1.1nginx-1.10.1mariadb-10.2.3composernodejs
file

1. 安装 Laravel 项目#

安装 laravel#

参考 Laravel 5.4 文档

laravel new favorites

file
file

我们安装 Laravel 的版本
file

安装 npm 模块#

file

创建模型#

创建文章和收藏表。-m 参数可以在创建模型的同时创建数据库迁移文件

php artisan make:model Post -m
php artisan make:model Favorite -m

file
我们分别编辑两个数据库迁移文件

posts#

Schema::create('posts', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('user_id')->unsigned();
        $table->string('title');
        $table->text('body');
        $table->timestamps();
    });

Favorite#

Schema::create('favorites', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('user_id')->unsigned();
        $table->integer('post_id')->unsigned();
        $table->timestamps();
    });

编辑.env 文件链接数据库#

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=favorite
DB_USERNAME=root
DB_PASSWORD=

创建数据库#

create database favorite  default charset utf8;

file

执行数据库迁移#

php artisan migrate

file

创建测试数据#

database/factories/ModelFactory.php 下添加

// database/factories/ModelFactory.php

$factory->define(App\Post::class, function (Faker\Generator $faker) {
    // Get a random user
    $user = \App\User::inRandomOrder()->first();

    // generate fake data for post
    return [
        'user_id' => $user->id,
        'title' => $faker->sentence,
        'body' => $faker->text,
    ];
});

执行

php artisan make:seeder UsersTableSeeder
php artisan make:seeder PostsTableSeeder

编辑 database/seeds/UsersTableSeeder.phprun 方法

    public function run()
    {
        factory(App\User::class, 5)->create();
    }

编辑 database/seeds/PostsTableSeeder.phprun 方法

 public function run()
    {
       factory(App\Post::class, 10)->create();
    }

编辑 database/seeds/PostsTableSeeder.phprun 方法

public function run()
    {
        $this->call(UsersTableSeeder::class);
        $this->call(PostsTableSeeder::class);
    }

创建测试数据

php artisan db:seed

file
file

一个用户可以收藏多个帖子,一个帖子可以被多个用户收藏。所以其关系为一对多对多。在 User 模型中添加 favorite 方法

修改 User 的控制器

// app/User.php

/**
 * Get all of favorite posts for the user.
 */
public function favorites()
{
    return $this->belongsToMany(Post::class, 'favorites', 'user_id', 'post_id')->withTimeStamps();
}

创建用户认证#

php artisan auth

file
file

创建路由#

Route::get('/', 'PostsController@index');

Route::post('favorite/{post}', 'PostsController@favoritePost');
Route::post('unfavorite/{post}', 'PostsController@unFavoritePost');

Route::get('my_favorites', 'UsersController@myFavorites')->middleware('auth');

创建控制器#

Post#

php artisan make:controller PostsController

编辑 PostsControllerindex 方法

// app/Http/Controllers/PostsController.php

// remember to use the Post model
use App\Post;

/**
 * Display a paginated list of posts.
 *
 * @return Response
 */
public function index()
{
    $posts = Post::paginate(5); //分页每页5条
    return view('posts.index', compact('posts'));
}

User#

php artisan make:controller UsersController

编辑

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class UsersController extends Controller
{
    public function myFavorites()
    {
        $myFavorites = Auth::user()->favorites;

        return view('users.my_favorites', compact('myFavorites'));
    }
}

视图#

resources\views\layouts\add.blade.php 模板中的 <title> 添加#

 <title>{{ config('app.name', 'Laravel') }}</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />

logout 添加我的收藏夹#

<li>
      <a href="{{ route('logout') }}"
          onclick="event.preventDefault();
                   document.getElementById('logout-form').submit();">
          Logout
      </a>

      <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
          {{ csrf_field() }}
      </form>
 </li>
 <li>
      <a href="{{ url('my_favorites') }}">My Favorites</a>
 </li>

创建 resources/views/posts/index.blade.php#

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="page-header">
                <h3>All Posts</h3>
            </div>
            @forelse ($posts as $post)
                <div class="panel panel-default">
                    <div class="panel-heading">
                        {{ $post->title }}
                    </div>

                    <div class="panel-body">
                        {{ $post->body }}
                    </div>
                    @if (Auth::check())
                        <div class="panel-footer">
                            <favorite
                                :post={{ $post->id }}
                                :favorited={{ $post->favorited() ? 'true' : 'false' }}
                            ></favorite>
                        </div>
                    @endif
                </div>
            @empty
                <p>No post created.</p>
            @endforelse

            {{ $posts->links() }}
        </div>
    </div>
</div>
@endsection

创建 resources/views/users/my_favorites.blade.php#

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="page-header">
                <h3>My Favorites</h3>
            </div>
            @forelse ($myFavorites as $myFavorite)
                <div class="panel panel-default">
                    <div class="panel-heading">
                        {{ $myFavorite->title }}
                    </div>

                    <div class="panel-body">
                        {{ $myFavorite->body }}
                    </div>
                    @if (Auth::check())
                        <div class="panel-footer">
                            <favorite
                                :post={{ $myFavorite->id }}
                                :favorited={{ $myFavorite->favorited() ? 'true' : 'false' }}
                            ></favorite>
                        </div>
                    @endif
                </div>
            @empty
                <p>You have no favorite posts.</p>
            @endforelse
         </div>
    </div>
</div>
@endsection

最后页面代码#

PostController#

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use App\Post;

class PostsController extends Controller
{
    public function index()
    {
        $posts = Post::paginate(5);
        return view('posts.index', compact('posts'));
    }
    /**
     * Favorite a particular post
     *
     * @param  Post $post
     * @return Response
     */
    public function favoritePost(Post $post)
    {
        Auth::user()->favorites()->attach($post->id);

        return back();
    }

    /**
     * Unfavorite a particular post
     *
     * @param  Post $post
     * @return Response
     */
    public function unFavoritePost(Post $post)
    {
        Auth::user()->favorites()->detach($post->id);

        return back();
    }
}

Post.php#

<?php

namespace App;

use App\Favorite;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public function favorited()
    {
        return (bool) Favorite::where('user_id', Auth::id())
                            ->where('post_id', $this->id)
                            ->first();
    }
}

vue 配置#

1. 在 resources/assets/js/components 创建 Favorite.vue#

<template>
    <span>
        <a href="#" v-if="isFavorited" @click.prevent="unFavorite(post)">
            <i  class="fa fa-heart"></i>
        </a>
        <a href="#" v-else @click.prevent="favorite(post)">
            <i  class="fa fa-heart-o"></i>
        </a>
    </span>
</template>

<script>
    export default {
        props: ['post', 'favorited'],

        data: function() {
            return {
                isFavorited: '',
            }
        },

        mounted() {
            this.isFavorited = this.isFavorite ? true : false;
        },

        computed: {
            isFavorite() {
                return this.favorited;
            },
        },

        methods: {
            favorite(post) {
                axios.post('/favorite/'+post)
                    .then(response => this.isFavorited = true)
                    .catch(response => console.log(response.data));
            },

            unFavorite(post) {
                axios.post('/unfavorite/'+post)
                    .then(response => this.isFavorited = false)
                    .catch(response => console.log(response.data));
            }
        }
    }
</script>

2. 在 vue 中注册#

Vue.component('favorite', require('./components/Favorite.vue'));

3. 编译#

npm run dev

file

最后在浏览器中访问,我们新建在 Laragon 中的 www 目录下的文件夹,Laragon 都会自动给我们创建了可以浏览的虚拟域名。直接访问
file

代码 https://github.com/ammezie/laravel-vue-fav...#

翻译参考 https://scotch.io/tutorials/implement-a-fa...#

本作品采用《CC 协议》,转载必须注明作者和本文链接
持续做一件事,必定有所成就
本帖由系统于 6年前 自动加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 10
hanzhao

感谢楼主分享,不过少了一段哈 :sweat_smile:,User Model 中需要添加如下方法

// app/User.php

/**
 * Get all of favorite posts for the user.
 */
public function favorites()
{
    return $this->belongsToMany(Post::class, 'favorites', 'user_id', 'post_id')->withTimeStamps();
}
8年前 评论

@hanzhao 多谢指出。已修改

8年前 评论
Destiny

非常不错的教学文章

8年前 评论

刚 clone, 没有.env.example

7年前 评论

@lazyou 哦哦,没有也没有关系,只要是.env 就可以用,你可以使用你项目中的就可以

7年前 评论

gif 是用什么做的?

7年前 评论

编辑 database/seeds/PostsTableSeeder.php 的 run 方法 重复了,下面 call 方法调用应该在 DatabaseSeeder.php 里面修改吧

7年前 评论

感谢,,有地方不明白,有一步是在: 在 vue 中注册# 怎么注册啊,哎 vue 没学过

7年前 评论

非常不错的文章!

7年前 评论
elesos

请问下 gif 是用什么做的?

5年前 评论