Laravel 基礎(chǔ)學(xué)習(xí) 第五天

使用 intended 訪問之前的頁面

需求:用戶直接輸入 ../user/10/edit 進(jìn)入編輯界面,由于 中間件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ù)

在項(xiàng)目開發(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)系其實(shí)存在于 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ù)進(jìn)行具體操作:因此我們可以在 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();
    
  • 總結(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

# 增加一個表格項(xiàng)
{{-- 判斷當(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();
}
  • 其實(shí)我們還可以:
    • 定義 UserPolicy@delete 策略
    public function delete(User $user, User $model)
    {
        if($user->is_admin) {
            return true;
        }
    }
    
    • 然后在 UserController@delete 中
    // 驗(yàn)證用戶是不是admin
    $this->authorize('delete', $user);
    
    // 然后再刪除
    

第一階段結(jié)束總結(jié)和優(yōu)化

  • 前5天,我們學(xué)會了配置路由 /routes/web.php
  • 學(xué)會了定義控制器 包括 restful控制器
  • 學(xué)會了使用 migration / modelFactory / Seeder 來管理數(shù)據(jù)庫
  • 學(xué)會了使用在資源控制器中對某一些資源進(jìn)行 CURD 操作
  • 學(xué)會了使用 auth 對用戶進(jìn)行認(rèn)證、使用 Policy 對用戶進(jìn)行權(quán)限控制
  • 學(xué)會了在視圖上的插值、判斷、循環(huán)。以及配合 session flash 發(fā)送臨時消息。
  • 學(xué)會了使用 composer 命令安裝中文包等。
  • 最后我們優(yōu)化一下,因?yàn)闆]有用過 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'
// });
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容