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 协议》,转载必须注明作者和本文链接
持续做一件事,必定有所成就
本帖由系统于 2年前 自动加精
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 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();
}
4年前 评论

@hanzhao 多谢指出。已修改

4年前 评论
Destiny

非常不错的教学文章

4年前 评论

刚 clone, 没有.env.example

4年前 评论

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

4年前 评论

gif是用什么做的?

4年前 评论

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

4年前 评论

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

3年前 评论

非常不错的文章!

3年前 评论
elesos

请问下 gif 是用什么做的?

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!