17/08/2018, 20:24

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

0