Laravel rating các bài post
1. Mở đầu Hôm này mình sẽ làm một ví dụ demo cách rating các bài post sử dụng Laravel Rateable composer package kết hợp với bootstrap-star-rating jquery plugin Ảnh demo 2. Tiến hành Code Bước 1: cài đặt project Laravel rating-demo composer create-project --prefer-dist ...
1. Mở đầu
Hôm này mình sẽ làm một ví dụ demo cách rating các bài post sử dụng Laravel Rateable composer package kết hợp với bootstrap-star-rating jquery plugin
Ảnh demo 2. Tiến hành Code
Bước 1: cài đặt project Laravel rating-demo
composer create-project --prefer-dist laravel/laravel rating-demo
Bước 2: cài đặt laravel rateable package
composer require laravel-rateable
Sau đó ở file app.php trong folder config ta thêm đoạn sau
<?php return [ .... 'providers' => [ .... willvincentRateableRateableServiceProvider::class, ], ....
Sau khi cài đặt xong chúng ta chạy lệnh sau để tạo file migration cho table rating
php artisan rateable:migration
Bước 3: tạo đăng ký, đăng nhập người dùng bằng auth
php artisan make:auth
Bước 4: tạo migration và model cho table posts
Tạo migration bằng lệnh sau
php artisan make:migration create_posts_table
Sau lệnh trên sẽ tạo ra file với đường dẫn là database/migrations, chỉnh sửa file trên như sau
<?php use IlluminateSupportFacadesSchema; use IlluminateDatabaseSchemaBlueprint; use IlluminateDatabaseMigrationsMigration; class CreatePostsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('posts', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('posts'); } }
Sau đó chạy lệnh dưới đây để tạo chạy các file migration
php artisan migrate
Tạo model post bằng việc chạy lệnh sau
php artisan make:model Post
Tìm đến app/Post.php đặt code dưới đây vào file Post.php
<?php namespace App; use IlluminateDatabaseEloquentModel; use willvincentRateableRateable; class Post extends Model { use Rateable; }
Bước 5: tạo route
Mở file routes/web.php thêm đoạn code dưới đây
Route::get('posts', 'HomeController@posts')->name('posts'); Route::post('posts', 'HomeController@postPost')->name('posts.post'); Route::get('posts/{id}', 'HomeController@show')->name('posts.show');
Bước 6: tạo controller tên là HomeController
php artisan make:controller HomeController
Thêm các phương thức sau vào
<?php namespace AppHttpControllers; use IlluminateHttpRequest; use AppPost; class HomeController extends Controller { /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('auth'); } /** * Show the application dashboard. * * @return IlluminateHttpResponse */ public function index() { return view('home'); } public function posts() { $posts = Post::all(); return view('posts',compact('posts')); } public function show($id) { $post = Post::find($id); return view('postsShow',compact('post')); } public function postPost(Request $request) { request()->validate(['rate' => 'required']); $post = Post::find($request->id); $rating = new willvincentRateableRating; $rating->rating = $request->rate; $rating->user_id = auth()->user()->id; $post->ratings()->save($rating); return redirect()->route("posts"); } }
Bước 7: tạo các view sau
resources/views/posts.blade.php
@extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-12"> <div class="panel panel-default"> <div class="panel-heading">Posts</div> <div class="panel-body"> <table class="table table-bordered"> <tr> <th>Id</th> <th>Name</th> <th awidth="400px">Star</th> <th awidth="100px">View</th> </tr> @if($posts->count()) @foreach($posts as $post) <tr> <td>{{ $post->id }}</td> <td>{{ $post->name }}</td> <td> <input id="input-1" name="input-1" class="rating rating-loading" data-min="0" data-max="5" data-step="0.1" value="{{ $post->averageRating }}" data-size="xs" disabled=""> </td> <td> <a href="{{ route('posts.show',$post->id) }}" class="btn btn-primary btn-sm">View</a> </td> </tr> @endforeach @endif </table> </div> </div> </div> </div> </div> <script type="text/javascript"> $("#input-id").rating(); </script> @endsection
resources/views/postsShow.blade.php
@extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-12"> <div class="panel panel-default"> <div class="panel-body"> <form action="{{ route('posts.post') }}" method="POST"> {{ csrf_field() }} <div class="card"> <div class="container-fliud"> <div class="wrapper row"> <div class="preview col-md-6"> <div class="preview-pic tab-content"> <div class="tab-pane active" id="pic-1"><img src="https://dummyimage.com/500x450/000/fff" /></div> </div> </div> <div class="details col-md-6"> <h3 class="product-title">Laravel 5.5 Ratting System</h3> <div class="rating"> <input id="input-1" name="rate" class="rating rating-loading" data-min="0" data-max="5" data-step="1" value="{{ $post->userAverageRating }}" data-size="xs"> <input type="hidden" name="id" required="" value="{{ $post->id }}"> <span class="review-no">422 reviews</span> <br/> <button class="btn btn-success">Submit Review</button> </div> <p class="product-description">Suspendisse quos? Tempus cras iure temporibus? Eu laudantium cubilia sem sem! Repudiandae et! Massa senectus enim minim sociosqu delectus posuere.</p> <h4 class="price">current price: <span>$180</span></h4> <p class="vote"><strong>91%</strong> of buyers enjoyed this product! <strong>(87 votes)</strong></p> <h5 class="sizes">sizes: <span class="size" data-toggle="tooltip" title="small">s</span> <span class="size" data-toggle="tooltip" title="medium">m</span> <span class="size" data-toggle="tooltip" title="large">l</span> <span class="size" data-toggle="tooltip" title="xtra large">xl</span> </h5> <h5 class="colors">colors: <span class="color orange not-available" data-toggle="tooltip" title="Not In store"></span> <span class="color green"></span> <span class="color blue"></span> </h5> <div class="action"> <button class="add-to-cart btn btn-default" type="button">add to cart</button> <button class="like btn btn-default" type="button"><span class="fa fa-heart"></span></button> </div> </div> </div> </div> </div> </form> </div> </div> </div> </div> </div> <script type="text/javascript"> $("#input-id").rating(); </script> @endsection
Bước 8: tạo các file css sau
thêm file css vào tron file : resources/views/layouts/app.blade.php
<link href="{{ asset('css/app.css') }}" rel="stylesheet"> <link href="http://netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-star-rating/4.0.2/css/star-rating.min.css" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-star-rating/4.0.2/js/star-rating.min.js"></script> <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet"> <link href="{{ asset('css/preview.css') }}" rel="stylesheet">
public/css/preview.css
img { max-awidth: 100%; } .preview { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; } @media screen and (max-awidth: 996px) { .preview { margin-bottom: 20px; } } .preview-pic { -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; } .preview-thumbnail.nav-tabs { border: none; margin-top: 15px; } .preview-thumbnail.nav-tabs li { awidth: 18%; margin-right: 2.5%; } .preview-thumbnail.nav-tabs li img { max-awidth: 100%; display: block; } .preview-thumbnail.nav-tabs li a { padding: 0; margin: 0; } .preview-thumbnail.nav-tabs li:last-of-type { margin-right: 0; } .tab-content { overflow: hidden; } .tab-content img { awidth: 100%; -webkit-animation-name: opacity; animation-name: opacity; -webkit-animation-duration: .3s; animation-duration: .3s; } .card { background: #eee; padding: 3em; line-height: 1.5em; } @media screen and (min-awidth: 997px) { .wrapper { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } } .details { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; } .colors { -webkit-box-flex: 1; -webkit-flex-grow: 1; -ms-flex-positive: 1; flex-grow: 1; } .product-title, .price, .sizes, .colors { text-transform: UPPERCASE; font-weight: bold; } .checked, .price span { color: #ff9f1a; } .product-title, .rating, .product-description, .price, .vote, .sizes { margin-bottom: 15px; } .product-title { margin-top: 0; } .size { margin-right: 10px; } .size:first-of-type { margin-left: 40px; } .color { display: inline-block; vertical-align: middle; margin-right: 10px; height: 2em; awidth: 2em; border-radius: 2px; } .color:first-of-type { margin-left: 20px; } .add-to-cart, .like { background: #ff9f1a !important; padding: 1.2em 1.5em !important; border: none; text-transform: UPPERCASE; font-weight: bold; color: #fff !important; -webkit-transition: background .3s ease; transition: background .3s ease; } .add-to-cart:hover, .like:hover { background: #b36800; color: #fff; } .not-available { text-align: center; line-height: 2em; } .not-available:before { font-family: fontawesome; content: "f00d"; color: #fff; } .orange { background: #ff9f1a; } .green { background: #85ad00; } .blue { background: #0076ad; } .tooltip-inner { padding: 1.3em; }
3. Link source code
https://github.com/quanghv96/rating-demo
4. Nguồn tham khảo
https://github.com/willvincent/laravel-rateable
https://github.com/kartik-v/bootstrap-star-rating