Laravel 5.4 vue 实现收藏
laravel 5.4 vue 收藏文章
最终实现效果
创建项目
本环境使用 Laragon
集成 php-7.1.1
、nginx-1.10.1
、mariadb-10.2.3
、composer
、nodejs
。
1. 安装 Laravel
项目
安装laravel
laravel new favorites
我们安装Laravel
的版本
安装npm
模块
创建模型
创建文章和收藏表。-m
参数可以在创建模型的同时创建数据库迁移文件
php artisan make:model Post -m
php artisan make:model Favorite -m
我们分别编辑两个数据库迁移文件
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;
执行数据库迁移
php artisan migrate
创建测试数据
在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.php
的run
方法
public function run()
{
factory(App\User::class, 5)->create();
}
编辑database/seeds/PostsTableSeeder.php
的run
方法
public function run()
{
factory(App\Post::class, 10)->create();
}
编辑database/seeds/PostsTableSeeder.php
的run
方法
public function run()
{
$this->call(UsersTableSeeder::class);
$this->call(PostsTableSeeder::class);
}
创建测试数据
php artisan db:seed
一个用户可以收藏多个帖子,一个帖子可以被多个用户收藏。所以其关系为一对多对多。在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
创建路由
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
编辑PostsController
的index
方法
// 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
最后在浏览器中访问,我们新建在Laragon
中的www
目录下的文件夹,Laragon
都会自动给我们创建了可以浏览的虚拟域名。直接访问
代码 https://github.com/ammezie/laravel-vue-fav...
翻译参考 https://scotch.io/tutorials/implement-a-fa...
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 6年前 自动加精
感谢楼主分享,不过少了一段哈 :sweat_smile:,User Model 中需要添加如下方法
@hanzhao 多谢指出。已修改
非常不错的教学文章
刚 clone, 没有
.env.example
@lazyou 哦哦,没有也没有关系,只要是.env就可以用,你可以使用你项目中的就可以
gif是用什么做的?
编辑database/seeds/PostsTableSeeder.php的run方法 重复了,下面call方法调用应该在DatabaseSeeder.php里面修改吧
感谢,,有地方不明白,有一步是在: 在vue中注册# 怎么注册啊,哎vue没学过
非常不错的文章!
请问下 gif 是用什么做的?