使用 intended 訪問之前的頁面
需求:用戶直接輸入 ../user/10/edit 進入編輯界面证杭,由于 中間件auth 的管理星掰,會將用戶彈回登陸界面怠蹂。
但此時瘾晃,用戶如果登陸成功蓝晒,則會返回網(wǎng)站根腮出。
先要求:用戶不登陸,訪問編輯界面芝薇,跳轉(zhuǎn)到登陸界面胚嘲,登陸之后,跳轉(zhuǎn)回編輯界面剩燥。
類似于 “發(fā)表評論” 等場景
- 非常簡單:使用
return redirect()->intended()
跳轉(zhuǎn)即可慢逾,在 LoginController.php 中
return redirect()->intended(route('home')); // intended() 可以填寫一個參數(shù)為如果沒有歷史記錄(比如我是直接訪問的登陸頁面),則默認(rèn)跳轉(zhuǎn)的地址(我設(shè)置為跳轉(zhuǎn)到首頁)
使用模型工廠填充數(shù)據(jù)
在項目開發(fā)時灭红,比如現(xiàn)在侣滩,我即將學(xué)習(xí)如何在頁面上分頁展示數(shù)據(jù)列表。但此時变擒,我沒有多少數(shù)據(jù)君珠,我想虛擬出來很多數(shù)據(jù),難道要使用 sql語句 一條一條插入嗎娇斑?當(dāng)然不用策添,使用模型工廠即可。
- 模型工廠位于 /database/factories/
- 創(chuàng)建模型工廠使用命令
php artisan make:factory XxFactory --model=Xx
=> 創(chuàng)建模型工廠毫缆,最好指定一個具體被操作的模型唯竹。 - 模型工廠自帶一個 UserFactory.php
$factory->define(App\User::class, function (Faker $faker) { //這里的 Faker類 是用來創(chuàng)建模擬的數(shù)據(jù)的
return [
'name' => $faker->name, //使用 faker 生成一個虛擬的用戶名
'email' => $faker->unique()->safeEmail,
'password' => bcrypt('laravelstudy'), // bcrypt() => Hash::make()
'remember_token' => str_random(10),
];
});
- 在 tinker 模式下使用模型工廠
php artisan tinker
# 調(diào)用全局 factory() 函數(shù)后鏈?zhǔn)胶瘮?shù)調(diào)用 ->make(); 來虛擬一條新的數(shù)據(jù)
factory(App\User::class)->make(); // factory() 第一參數(shù)使用 UserFactory 定義的第一參數(shù)。 make() 只會虛擬數(shù)據(jù)苦丁,不會插入數(shù)據(jù)庫
# 調(diào)用 create() 插入數(shù)據(jù)
factory(App\User::calss, 20)->create(); // factory() 第二參數(shù)是你要插入的數(shù)據(jù)條數(shù)
結(jié)合 Seeder 完成數(shù)據(jù)填充
- Seeder 都位于 /database/seeds/ 下
- 創(chuàng)建一個 Seeder
php artisan make:seeder XxSeeder
- 默認(rèn)有一個 DatabaseSeeder.php => 可以理解為所有 Seeder 的入口浸颓。
public function run() //調(diào)用該方法即可調(diào)用內(nèi)部我們插入虛擬數(shù)據(jù)的方法
{
// $this->call(UsersTableSeeder::class); //這里給我們舉了一個如何調(diào)用其他Seeder的例子
$this->call(UserSeeder::class); //調(diào)用我們的UserSeeder
}
假如我們有一個 文章表 n:1 用戶表 的數(shù)據(jù)表關(guān)系,我們應(yīng)該在 DetabaseSeeder 中通過先后關(guān)系聲明 => 先插入關(guān)于用戶表的虛擬數(shù)據(jù),再插入文章表的虛擬數(shù)據(jù)产上。
- 注意棵磷,打開 UserSeeder.php 你會發(fā)現(xiàn)該文件沒有命令空間:它們的結(jié)構(gòu)關(guān)系其實存在于 composer.json 中
"autoload": {
"classmap": [
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
- 因此,最好執(zhí)行一次
composer dumpautoload
來更新一下classmap晋涣。 - 編輯 UserSeeder.php @ run()
<?php
use Illuminate\Database\Seeder;
use App\User; //這里引用一下我們的 App\User
class UserSeeder extends Seeder
{
public function run()
{
// 創(chuàng)建100條數(shù)據(jù)
factory(User::class, 100)->create();
// 找到 id=1 的數(shù)據(jù)
$user = User::find(1);
// 將他設(shè)置為我們可以用的數(shù)據(jù)
$data = [
'name' => 'liuhaoyu',
'email' => 'seederstudy@laravel.com',
'password' => bcrypt('liuhaoyu')
];
// 更新
$user->update($data);
}
}
有時候仪媒,我們需要一條可用的數(shù)據(jù)進行具體操作:因此我們可以在 run() 方法中再定義一次針對莫數(shù)據(jù)的 update() 操作。
調(diào)用 seed
php artisan db:seed
=> 找 DatabaseSeeder.php 根據(jù)它的 run() 方法來按順序調(diào)用里面的其他 Seeder 的 run() 方法使用
php artisan migrate:refresh --seed
命令 重構(gòu)整個數(shù)據(jù)庫(表刪完再重建)--seed 即調(diào)用一次 db:seed 命令
總結(jié)一下模擬填充數(shù)據(jù)
- /database/factories/ 下存放的都是模型工廠的文件谢鹊,它們定義了我們將怎樣插入數(shù)據(jù)(幫我們虛擬出 sql 語句)
- 模型工廠使用了 Faker 類幫我們虛構(gòu)數(shù)據(jù)
- 創(chuàng)建模型工廠使用
php artisan make:factory XxFactory --model=Model
- 可以使用全局函數(shù)
factory(模型工廠名::class, 創(chuàng)建條數(shù))->create()
來往數(shù)據(jù)表中插入數(shù)據(jù)算吩。->make()
可以看看具體虛擬的數(shù)據(jù)。 可以在php artisan tinker
模型下調(diào)試這些命令撇贺。
- /database/seeds/ 下幫我們存放了 Seeder 文件 => 幫助我們自動在多表生成模擬數(shù)據(jù)的文件
- DataBaseSeeder.php => 可以理解為
php artisan db:seed
調(diào)用的文件 - 在定義 DataBaseSeeder 的時候赌莺,注意區(qū)分一下多張數(shù)據(jù)表的關(guān)系,比如 “多篇文章 belongsTo 一個用戶”松嘶,我們應(yīng)該先虛擬插入用戶數(shù)據(jù),再插入文章的數(shù)據(jù)挎扰。因此再 run() 方法中翠订,需要先
$this->call(用戶Seeder)
再 call() 文章Seeder - 創(chuàng)建其他Seeder 使用命令
php artisan make:seeder XxSeeder
- 我們需要定義 XxSeeder@run
public function run() { // 在內(nèi)部通過調(diào)用 factory() 來生成數(shù)據(jù) factory(User::class, 100)->create(); }
- 有時候我們需要在模擬了很多條數(shù)據(jù)之后,弄一個可用的 (比如我模擬很多用戶遵倦,但是得有一條我可以用作登陸的)
// 1 引用模型 ... use App\User; // 2 在 run() 方法中更新某條數(shù)據(jù) ... $user = User::find(1); //找到第1條數(shù)據(jù) $user->name = 'najiuyuanzou'; $user->email = 'najiuyuanzou@test.com'; $user->password = bcrypt('najiuyuanzou'); // bcrypt() = Hash::make() $user->save();
- DataBaseSeeder.php => 可以理解為
- 總結(jié)整個過程就是:
php artisan db:seed
=> 調(diào)用 DatabaseSeeder@run => DatabaseSeeder 調(diào)用它聲明先后順序的其他 Seeder@run => 將虛擬數(shù)據(jù)插入數(shù)據(jù)表 - 有時候我們需要將數(shù)據(jù)庫重來一次 =>
php artisan migrate:refresh
=> 全部回滾尽超,然后重新生成數(shù)據(jù)表并清空數(shù)據(jù)。如果加上--seed
參數(shù)梧躺,則會重新生成并且插入我們定義好的模擬的數(shù)據(jù)似谁。 - 總體來說 根/Database/ 就是一個幫助我們管理數(shù)據(jù)庫的文件夾。
- migrations => 數(shù)據(jù)庫遷移 (數(shù)據(jù)庫版本管理)
- factories => 模型工廠 (偽造Sql語句)
- seeds => “播種工具” (執(zhí)行模型工廠中為多表打造的偽造的sql語句)
- DatabaseSeeder => 入口
- XxSeeder, ... => 針對其他表的其他Seeder
seeds 這個播種工具是我自己瞎取的掠哥。巩踏。。
分頁展示所有用戶
- 確定路由和控制器: UserController@index => 展示用戶列表续搀。 路由則是 resource 直接幫我們定義好了的
- 在 _navbar.blade.php 中添加一個超鏈接展示 “用戶列表”
<ul class="navbar-nav mr-auto">
<li class="nav-item"><a class="nav-link" href="{{ route('user.index') }}">會員列表</a></li>
<li class="nav-item"><a class="nav-link disabled" href="#">不可用</a></li>
</ul>
- 在 UserController@index 中查詢數(shù)據(jù)并分頁然后跳轉(zhuǎn)到視圖
// 定義 where 條件
$where = [
['id', '>', 0],
['created_at', '>', time()],
];
// 查詢數(shù)據(jù)并分頁
$users = User::where($where) // where(查詢條件)
->orderBy('id', 'desc') // orderBy('字段', 'desc | asc')
->orderBy('created_at', 'desc') // 多個需要 orderBy 的字段可以寫多條
->paginate(30); // paginate(每頁頁數(shù))
return view('user.index', [
'users' => $users, //可以通過 view('視圖名稱', ['變量1'=>$變量1, '變量2'=>$變量2,]); 來抓取視圖并分配變量
]);
- 在視圖遍歷數(shù)據(jù)并分頁
{{-- foreach 遍歷 $users --}}
@foreach ($users as $user)
<tr>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>{{ $user->created_at }}</td>
</tr>
@endforeach
{{-- 生成分頁鏈接 --}}
{{ $users->links() }}
刪除用戶
- 我們需要給用戶表添加一個 boolean 字段 'is_admin'塞琼, 由此值來判斷用戶是不是管理員。因此新建遷移文件
php artisan make:migration add_is_admin_user --table=users
=> 我把名字取名叫做--table=users
指明我們要編輯的數(shù)據(jù)表禁舷。
// up()
Schema::table('users', function (Blueprint $table) {
$table->boolean('is_admin')->default(false); //添加 布爾類型 字段 'is_admin' 默認(rèn)值為 false
});
// down()
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('is_admin'); // 回滾時 刪除該字段
});
- 執(zhí)行一次遷移
php artisan migrate
=> users 表中增加了 'is_admin' 字段彪杉,可以編輯一下1號用戶,設(shè)置它的is_admin = true
但是這樣太麻煩了牵咙,并且如果我們下次執(zhí)行刷新遷移的時候派近,又需要再來修改一次 is_admin 字段的值,所以我們改一改Seeder的邏輯
- 編輯一下 UserSeeder 讓1號用戶為管理員
public function run()
{
// 創(chuàng)建100條數(shù)據(jù)
factory(User::class, 100)->create();
// 找到 id=1 的數(shù)據(jù)
$user = User::find(1);
// 將他設(shè)置為我們可以用的數(shù)據(jù)
$data = [
'name' => 'liuhaoyu',
'email' => 'seederstudy@laravel.com',
'password' => bcrypt('liuhaoyu'),
'is_admin' => true // 這里使1號用戶為管理員
];
// 更新
$user->update($data);
}
執(zhí)行
php artisan migrate:refresh --seed
處理視圖 user.index.blade.php
# 增加一個表格項
{{-- 判斷當(dāng)前用戶是否是admin洁桌,是則顯示 --}}
@if (Auth::user()->is_admin)
{{-- 這里調(diào)用一個“刪除確認(rèn)”的函數(shù) --}}
<a href="javascript:deleteConfirm();" class="btn btn-danger btn-sm">刪除</a>
{{-- 刪除表單 --}}
<form id="delete-user-from" method="POST" action="{{ route('user.destroy', $user->id) }}">
{{-- 注明csrf_token --}}
@csrf
{{-- 偽造表單 method="DELETE" --}}
@method('DELETE')
</form>
@endif
# 刪除確認(rèn)的函數(shù)
function deleteConfirm() {
var confirm = window.confirm('確定要刪除這個用戶嗎渴丸?');
if(confirm === true) {
$("#delete-user-from").submit(); //提交表單
}else {
window.alert('您選擇不刪除。');
}
}
- 完成 UserController@destroy 邏輯
public function destroy(User $user)
{
// 判斷當(dāng)前用戶是否是 admin
if(!Auth::user()->is_admin) {
session()->flash('danger', '只有管理員可以刪除用戶!');
return redirect()->back();
}
// 刪除用戶
$user->delete();
session()->flash('success', '用戶刪除成功');
return redirect()->back();
}
- 其實我們還可以:
- 定義 UserPolicy@delete 策略
public function delete(User $user, User $model) { if($user->is_admin) { return true; } }
- 然后在 UserController@delete 中
// 驗證用戶是不是admin $this->authorize('delete', $user); // 然后再刪除
第一階段結(jié)束總結(jié)和優(yōu)化
- 前5天曙强,我們學(xué)會了配置路由 /routes/web.php
- 學(xué)會了定義控制器 包括 restful控制器
- 學(xué)會了使用 migration / modelFactory / Seeder 來管理數(shù)據(jù)庫
- 學(xué)會了使用在資源控制器中對某一些資源進行 CURD 操作
- 學(xué)會了使用 auth 對用戶進行認(rèn)證残拐、使用 Policy 對用戶進行權(quán)限控制
- 學(xué)會了在視圖上的插值、判斷碟嘴、循環(huán)溪食。以及配合 session flash 發(fā)送臨時消息。
- 學(xué)會了使用 composer 命令安裝中文包等娜扇。
- 最后我們優(yōu)化一下错沃,因為沒有用過 Vue,所以在 /resources/assets/js/app.js中取消引用 Vue
# 注銷他們
// window.Vue = require('vue');
// Vue.component('example-component', require('./components/ExampleComponent.vue'));
// const app = new Vue({
// el: '#app'
// });