laravel+react實戰打造企業級高併發分佈式電商小程序(二)--權限管理

laravel+react實戰打造企業級高併發分佈式電商小程序(二)

整體使用laravel7+react打造整個電商小程序。裏面會涉及到高併發的知識,mysql的分庫分表,主從讀寫分離的配置,redis集羣的使用,緩存系統的使用,隊列系統的使用等。

先初始化一個laravel的項目。然後配置好.env文件。

權限管理

既然是電商肯定有後臺,要做權限管理這塊。

先創建表,這裏使用laravelmigration。下面是後臺用戶表。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('auth_users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name', 100)->unique();
            $table->string('email', 100)->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('auth_users');
    }
}

下面是角色表


<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateRolesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('auth_roles', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name', 100)->unique();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('auth_roles');
    }
}


下面是權限表

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePermissionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('auth_permissions', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name',100)->unique();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('auth_permissions');
    }
}

下面是用戶角色關聯表


<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUserRolesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('auth_user_roles', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->bigInteger('user_id');
            $table->bigInteger('role_id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('auth_user_roles');
    }
}


下面是角色和權限關聯表


<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateRolePerimissionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('auth_role_permissions', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->bigInteger('user_id')->default(0);
            $table->bigInteger('role_id');
            $table->bigInteger('perimission_id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('auth_role_permissions');
    }
}

下面這張是系統錯誤信息表,這裏會返回錯誤信息,這些錯誤信息全部存放在這張表裏。


<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateSysErrorsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('sys_errors', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('code',100)->unique()->comment('錯誤編碼');
            $table->string('msg')->comment('錯誤信息');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('sys_errors');
    }
}

創建完這些執行遷移命令就可以了。

php artisan migrate

當然了,在這之前確保你的.env文件已經配置好了數據庫連接。

我們有了後臺數據還需要一個管理員賬戶,使用seed填充。


<?php

use App\Models\Auth\UserModel;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run(UserModel $user)
    {
        $user->name = 'admin';
        $user->email = '[email protected]';
        $user->password = Hash::make('123456');
        $user->save();

    }
}

運行填充命令

php artisan db:seed

控制器

這裏我們使用一個laravel的擴展包,使用composer安裝他

composer require thepatter/query-common

安裝完後查看我的這個文章來使用這個包,根據文章裏面做完之後再回來看下面的內容。

https://blog.csdn.net/Thepatterraining/article/details/105408363

接下來使用artisan命令創建我們的控制器。

php artisan make:queryController Auth/UserController

創建完之後在創建model

php artisan make:model Models/Auth/UserModel

修改剛纔的Auth/UserModel,在裏面增加table屬性。


<?php

namespace App\Models\Auth;

use Illuminate\Database\Eloquent\Model;

class UserModel extends Model
{
    //
    protected $table = 'auth_users';
}

修改剛纔的Auth/UserController控制器。


<?php

namespace App\Http\Controllers\Auth;

use QueryCommon\QueryController;
use App\Models\Auth\UserModel;
use App\Models\Auth\UserRoleModel;

class UserController extends QueryController
{
    /**
     * 字典數組
     * ['表裏的字段名' => '字典code',...]
     */
    protected $dicArr = [];

    /**
     * 字段映射 可選,不填默認轉成下劃線格式
     * ['搜索字段' => '表字段',...]
     */
    protected $filedsAdapter = [];

    /**
     * 創建時候的字段映射 可選,不填默認轉成下劃線格式
     * ['輸入字段' => '表字段']
     */
    protected $createAdapter = [
        'name' => 'name',
        'email' => 'email',
    ];

    //定義表名 格式: table as t
    protected $shortTableName;


    protected function getModel() {
        $this->model = new UserModel;
        return $this->model;
    }

}


這時候我們對用戶的增刪改查操作就完成了,是不是超級簡單呢。這主要依賴於我們的query-common擴展包。

我們接下來只需要添加對應的路由就可以了。在routes下面創建Api/Auth文件夾。在裏面創建index.php路由文件。


<?php
use Illuminate\Support\Facades\Route;


Route::prefix('auth')->namespace('Auth')->group(function () {
    //後臺創建用戶
    Route::post('user', 'UserController@createInfo');

    //後臺查詢管理員列表
    Route::get('users', 'UserController@queryList');

    //後臺更新管理員信息
    Route::put('user/{id}', 'UserController@updateInfo');

    //後臺刪除管理員
    Route::delete('user/{id}', 'UserController@deleteInfo');

});

添加完路由文件後我們需要自動加載路由文件,請看我的這篇文章,路由自動加載。

https://blog.csdn.net/Thepatterraining/article/details/105386868

接下來可以使用postman來測試了。

獲取用戶列表

在這裏插入圖片描述

其他的就不放圖了。

角色

有了用戶就有角色了,我們的角色表在之前已經創建好了,我們現在同樣的方法創建controller和model。

執行下面的命令。-m參數是model,這裏指定model後,如果model不存在會自動創建。

php artisan make:queryController Auth/RoleController -m Models/Auth/RoleModel

修改剛纔的Auth/RoleModel,在裏面增加table屬性。


<?php

namespace App\Models\Auth;

use Illuminate\Database\Eloquent\Model;

class RoleModel extends Model
{
    //
    protected $table = 'auth_roles';
}

app/Http/Controllers/Auth/RoleController文件內容如下


<?php

namespace App\Http\Controllers\Auth;

use QueryCommon\QueryController;
use App\Models\Auth\RoleModel;

class RoleController extends QueryController
{
    /**
     * 字典數組
     * ['表裏的字段名' => '字典code',...]
     */
    protected $dicArr = [];

    /**
     * 字段映射 可選,不填默認轉成下劃線格式
     * ['搜索字段' => '表字段',...]
     */
    protected $filedsAdapter = [];

    /**
     * 創建時候的字段映射 可選,不填默認轉成下劃線格式
     * ['輸入字段' => '表字段']
     */
    protected $createAdapter = [];

    //定義表名 格式: table as t
    protected $shortTableName;


    protected function getModel() {
        $this->model = new RoleModel();
        return $this->model;
    }

}

接着在剛纔的routes/Api/Auth/index路由文件中增加下面的內容


//後臺查詢角色列表
    Route::get('roles', 'RoleController@queryList');

    //創建角色
    Route::post('role', 'RoleController@createInfo');

    //更新角色
    Route::put('role/{id}', 'RoleController@updateInfo');

    //刪除角色
    Route::delete('role/{id}', 'RoleController@deleteInfo');

增加後是下圖這樣

在這裏插入圖片描述

同樣使用postman測試。

在這裏插入圖片描述

用戶和角色關聯

有了用戶和角色就要把這兩個關聯起來了,我們通過在創建用戶和修改用戶的時候關聯角色,在這時候就要更改之前的Auth/UserController了。

增加下面的函數。


    /**
     * 創建完用戶後執行的操作
     */
    protected function createAfter($id) {
        $this->userRole($id);
    }

    //更新完主表之後可以進行的操作
    protected function updateAfter($id) {
        //更新完用戶信息需要更新用戶角色關聯
        //先刪除所有關聯,再重新創建
        UserRoleModel::where('user_id', $id)->delete();

        $this->userRole($id);

    }


    /**
     * 用戶角色操作,先刪除用戶的所有角色,再創建角色關聯
     * @param int $id 用戶id
     */
    private function userRole($id) {
        $ids = $this->request->input('roleIds');
        //組織數據
        $insertDatas = [];
        foreach ($ids as $roleId) {
            $insertData = [];
            $insertData['user_id'] = $id;
            $insertData['role_id'] = $roleId;
            $insertData['created_at'] = date('Y-m-d H:i:s');
            $insertDatas[] = $insertData;
        }
        //一次性插入
        UserRoleModel::insert($insertDatas);
    }

createAfter方法是在創建完用戶後執行的,updateAfter方法是更新完用戶信息後執行的。傳入用戶id。我們在這裏刪除之前的用戶和角色關聯,把新的循環添加到數組中,一次性插入數據庫。因爲循環插入會進行多次數據庫io操作,而數據庫io是比較耗費資源和時間的,所以我們儘可能少進行數據庫操作。

在創建和更新時候我們還需要驗證參數,我們再添加下面的方法。


    /**
     * 在創建之前調用,用來驗證參數
     */
    protected function createBefore() {
        //檢測頁碼和每頁數量
        $rules = [
            'name' => 'required|unique:auth_users,name',
            'email' => 'required|email|unique:auth_users,email',
            'password' => 'required',
            'roleIds' => 'required|array',
        ];
        $messages = [
            'name.required' => '用戶名爲必填項',
            'name.unique' => '用戶已經存在',
            'email.required' => '郵箱爲必填項',
            'email.unique' => '郵箱已經存在',
            'email.email' => '請輸入正確的郵箱格式',
            'password.required' => '密碼爲必填項',
            'roleIds.required' => '角色爲必填項',
            'roleIds.array' => '角色必須是數組類型',
        ];
        $this->valid($rules, $messages);

        //判斷角色數組是不是在數據庫都存在
        $roleNum = RoleModel::whereIn('id', $this->request->roleIds)->count();
        if ($roleNum != count($this->request->roleIds)) {
            //角色id不對
            throw new CommonException(ErrorModel::ROLE_NOT_FOUND);
        }
    }

    /**
     * 在創建之前調用,用來驗證參數
     */
    protected function updateBefore() {
        //檢測頁碼和每頁數量
        $rules = [
            'name' => 'required',
            'email' => 'required|email',
            'roleIds' => 'required|array',
        ];
        $messages = [
            'name.required' => '用戶名爲必填項',
            'email.required' => '郵箱爲必填項',
            'email.email' => '請輸入正確的郵箱格式',
            'roleIds.required' => '角色爲必填項',
            'roleIds.array' => '角色必須是數組類型',
        ];
        $this->valid($rules, $messages);

        //判斷角色數組是不是在數據庫都存在
        $roleNum = RoleModel::whereIn('id', $this->request->roleIds)->count();
        if ($roleNum != count($this->request->roleIds)) {
            //角色id不對
            throw new CommonException(ErrorModel::ROLE_NOT_FOUND);
        }
    }

createBefore方法在創建用戶之前調用,updateBefore方法在更新之前調用,用來驗證參數信息。驗證角色在數據庫中不存在後要返回錯誤,直接throw拋出異常即可,因爲在外部已經用try catch捕獲了,這裏返回的是一個error code,在Sys/ErrorModel中定義一個錯誤信息。爲了方便管理,所有的錯誤以常量的方式定義在errorModel裏面。真正的錯誤信息在我們一開始創建的sys_error數據表中。我們在數據表中添加一條錯誤信息,code是100002的,msg是角色未定義!


const ROLE_NOT_FOUND = '100002'; //角色未定義!

我們可以傳一些錯誤的角色id給到接口中,使用postman來測試一下。因爲這個用戶已經創建了,所以返回了用戶已經存在的錯誤信息。

在這裏插入圖片描述

權限

我們使用同樣的方式創建權限的controllermodel

php artisan make:queryController Auth/PermissionController -m Models/Auth/PermissionModel

和上面一樣,修改剛纔的Auth/PermissionModel,在裏面增加table屬性。後面的就不再說這裏了。


<?php

namespace App\Models\Auth;

use Illuminate\Database\Eloquent\Model;

class PermissionModel extends Model
{
    //
    protected $table = 'auth_permissions';
}

增加路由。


    //後臺查詢權限列表
    Route::get('permissions', 'PermissionController@queryList');

    //創建權限
    Route::post('permission', 'PermissionController@createInfo');

    //更新權限
    Route::put('permission/{id}', 'PermissionController@updateInfo');

    //刪除權限
    Route::delete('permission/{id}', 'PermissionController@deleteInfo');

使用postman測試。

在這裏插入圖片描述

現在呢,我們權限管理的後端接口就算做完了,當然了,後面還會根據需要調整。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章