實作了資料的撰寫,也實作了針對資料庫的測試。但是還沒有滿足上次我們說的需求!
還記得的話,上次我們說的,是只有登入用戶才能夠撰寫文章。
但是前幾天,我們沒有考慮到的是,編輯文章應該「只有當初的作者才能做到」。
今天,我們就來實作寫入文章的權限吧!
首先,我們要先用 Laravel 提供的 Auth::user()
函式,來取得用戶登入的身份。
如果使用者沒有登入,那麼就不會有對應的 User
物件,Auth::user()
會回傳 null
只要檢查這個函式的回傳是不是 null
,我們就可以知道現在的使用者是不是已經登入囉。
現在,只要使用者沒有登入的話,我們就把他導回到 route('login')
,也就是登入頁面裡面
public function create()
{
if (is_null(Auth::user())) {
return redirect(route('login'));
}
return view('posts.create');
}
現在,在沒有登入的情況下嘗試進入 http://127.0.0.1/posts/create ,應該都會被導回到 http://127.0.0.1/login 囉!
接著,我們來為編輯文章加上限制
要限制只有當初撰寫文章的人才可以編輯,那麼每篇文章勢必得要紀錄當初的編輯者是誰。
所以,我們要修改一下資料庫的內容,幫 Post
類別加上 user_id
(還有印象的讀者可以先不看「修改文章資料庫」和「增加一對多關係」這幾段,自己實作看看。
再回來看看做法是不是一樣!)
$ php artisan make:migration add_user_id_to_posts_table
Created Migration: 2019_09_24_133820_add_user_id_to_posts_table
接著,我們改寫 migration 如下
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddUserIdToPostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->bigInteger('user_id')->after('subject_id')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->dropColumn('user_id');
});
}
}
再來就是我們熟悉的 php artisan migrate
了,運作之後記得到資料庫檢查看看 posts
是否成功的多了一欄 user_id
。
再來,就是加上在 Post
和 User
的關係。
我們在 Post
類別裡面加上
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
在 User
類別裡面加上
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function posts()
{
return $this->hasMany(Post::class);
}
這樣就好囉!
自己動手做的讀者,做法是不是和文章裡面一樣呢?
接著,是要在新增文章時,幫文章加上 user_id
user_id
要加上 user_id
,我們可以透過 Auth::id()
這個函式,取得現在的用戶 id
。
我們改寫一下 PostController
裡面的 store()
public function store(Request $request)
{
$post = new Post;
$post->content = $request->input('content');
$post->subject_id = 0;
$post->user_id = Auth::id();
$post->save();
return redirect(route('posts.index'));
}
好了!各位可以嘗試新增文章看看,如果成功的話,現在新增文章之後,新文章的 user_id
應該會有值了!
接著,就是要撰寫編輯的權限控管了!不過在這之前,我們要先學一個新的東西:Laravel Policy!
簡單的說,Laravel Policy 就是像我們這次的需求一樣,針對一個 Model 或者資源限制權限的時候,可以使用的機制。
首先,我們利用 artisan
來幫我們建立 PostPolicy
php artisan make:policy PostPolicy --model=Post
Policy created successfully.
我們就可以看到建立好的 app/Policies/PostPolicy
類別了!
進去看看,會看到 Laravel 很貼心的幫我們建立好了許多函式,參數也很聰明地幫我們加上了 Post
物件。
這次我們需要的是 update
相關的權限,我們找到 update()
來修改一下條件
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
接著,我們記得到 app/Providers/AuthServiceProvider
裡面,註冊剛剛建立好的 PostPolicy
protected $policies = [
// 'App\Model' => 'App\Policies\ModelPolicy',
Post::class => PostPolicy::class,
];
做好之後,我們就可以實際使用看看囉!
我們改寫 PostController
的 edit()
函式,透過使用 cant()
這個函式
讓用戶如果不具有修改這篇文章的權限,就導回文章列表頁面
public function edit(Post $post)
{
$user = Auth::user();
if(is_null($user) || $user->cant('update', $post)){
return redirect(route('posts.index'));
}
return view('posts.edit', ['post' => $post]);
}
好囉!我們連線 http://127.0.0.1/posts/1/edit 看看,如果 id 為 1 的 Post
所帶的 user_id
和現在登入的用戶不對應的話,那麼就會被導回 http://127.0.0.1/posts 。
到這邊,我們所做的用戶驗證就成功囉!
小小總結一下今天我們學到的東西。
今天我們學到怎麼利用 Laravel 的 Policy,以及 User
類別的許多函式,來實作登入才能編輯文章,以及只有是文章作者才能編輯文章,這幾個權限。
希望各位覺得今天有學到新東西,我們明天見!