最近写Laravel,发现很多工具用起来的时候都得现查,现在在这备份一下省得之后还得查。
Eloquent ORM数据库迁移模型
利用php脚本建立数据表
-
创建迁移模型
$ php artisan make:migration create_表名
-
将主键设置为UUID
$table->uuid('id');
-
完整迁移脚本样例
<?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('users', function (Blueprint $table) { $table->uuid('id'); $table->string('user_name'); $table->string('user_email'); $table->string('user_password'); $table->string('user_type'); $table->string('user_status'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } }
-
启动迁移
$ php artisan migrate
-
数据库创建后的结构(以上面的user脚本为例)
字段名 类型 长度 约束 备注 id varchar 36 非空 36位长uuid user_name varchar 255 非空 用户名 user_email varchar 255 非空 用户邮箱 user_password varchar 255 非空 用户密码(使用随机盐哈希加密) user_type varchar 255 非空 用户类型 user_status varchar 255 非空 用户状态 created_at timestamp 0 创建时间(由laravel自动生成并管理) updated_at timestamp 0 修改时间(由laravel自动生成并管理) -
数据填充seeder
a. 创建seeder类$ php artisan make:seeder
b. 将数据脚本写入run
public function run() { DB::beginTransaction(); try { $user = new User(); ... $user->save(); $user_profile = new UserProfile(); ... $user_profile->save(); }catch (\Exception $e){ DB::rollBack(); echo $e; } DB::commit(); }
c. 将seeder加入DatabaseSeeder.php
public function run() { $this->call([ AddAdminUserSeeder::class, ]); }
d. 执行迁移
$ php artisan db:seed
数据库与持久层
-
数据库事务
... //需要引入DB门面 use Illuminate\Support\Facades\DB; ... class xxx extend Controller{ public function xxx(Request $request){ //事务的开启 DB::beginTransaction(); ... //事务的提交 DB::commit(); ... //事务的回滚 DB::rollBack(); } }
-
数据对象ORM
a. 通过脚手架创建数据对象(Model)$ php artisan make:model ModelName
b. 数据对象结构
<?php namespace App\Models; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { use HasApiTokens, HasFactory, Notifiable; //批量赋值时的白名单 protected $fillable = [ 'user_name', 'user_email', 'user_password', ]; //查询返回的json中不出现的字段 protected $hidden = [ 'user_password', ]; //表名 protected $table="users"; //是否自增(当主键为uuid时为否) public $incrementing = false; //主键类型(当主键为uuid时为string) protected $keyType = 'string'; //自动管理时间戳(如果使用unix时间戳或不添加created_at与updated_at字段为false) public $timestamps = false; }
-
数据对象查询(以User.php为例)
//通过持久层拼接Where语句,返回为数据对象数组 $user = User::query() ->where("user_name", $username) ->orWhere("email", $username) ->get(); //假定只有一条数据,获取其用户名,多条foreach循环即可 $name = $user[0]->user_name;
-
新增或编辑数据对象(以User.php为例)
//事务开启 DB::beginTransaction(); //新增为new对象,编辑则直接修改从数据库中返回的对象即可 $user = new User(); //uuid使用见下节 $user->id = Uuid::generate(); //随机盐哈希加密见下节 $user->user_password = password_hash("rasmuslerdorf", PASSWORD_DEFAULT); //...其他省略 //异常捕获 try { $user->save(); } catch (\Exception $e) { //如果异常则回滚 DB::rollBack(); throw $e; } DB::commit();
随机盐的哈希加密
- 获取加密后的密码
$password_hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);
- 验证原密码与加密后的密码是否匹配,返回布尔
$verify=password_verify('password_string', $password_hash)
UUID插件
- 安装Uuid拓展
$ composer require webpatser/laravel-uuid
- 添加app别名注册(config/app.php)
'aliases' => [ ... 'Uuid' => Webpatser\Uuid\Uuid::class, ],
- uuid使用
//引入 use Webpatser\Uuid\Uuid; //生成 $uuid=Uuid::generate();
Redis插件安装与使用
-
Redis安装
Laravel自带Redis引擎,但是用不惯,我习惯切换成predis$ composer require predis/predis
-
Redis配置
修改redis配置文件,在config/database.php文件中'redis' => [ //引擎配置,默认为phpredis,可以改为predis 'client' => env('REDIS_CLIENT', 'phpredis'), 'options' => [ 'cluster' => env('REDIS_CLUSTER', 'redis'), //此处为在redis中key的前缀,为.env配置文件中的name,可自行修改 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), ], //默认配置,无需修改 'default' => [ 'url' => env('REDIS_URL'), 'host' => env('REDIS_HOST', '127.0.0.1'), 'password' => env('REDIS_PASSWORD', null), 'port' => env('REDIS_PORT', '6379'), 'database' => env('REDIS_DB', '0'), ], //自定义设置,在.env中配置即可 'cache' => [ 'url' => env('REDIS_URL'), 'host' => env('REDIS_HOST', '127.0.0.1'), 'password' => env('REDIS_PASSWORD', null), 'port' => env('REDIS_PORT', '6379'), 'database' => env('REDIS_CACHE_DB', '1'), ], ],
-
Redis使用
引入门面use Illuminate\Support\Facades\Redis;
代码中使用
//设置字符串值 Redis::set("key","value") //设置带有过期时间的值(单位为秒) Redis::setex("key",$expiredTime,"value"); //获取字符串值 Redis::get("key") //读取后通过json格式解码(用于value是php array格式的情况) $value=json_decode(Redis::get("key"),true);
缓存
- 缓存Cache默认使用文件驱动,可改为Redis驱动数据库驱动或其他,我一般用文件驱动来代替当Redis不存在的情况
//添加缓存,过期时间可为空,为过期时间点,并非时长 Cache::put("key" , "value" ,$expiredAt); //获取缓存 Cache::get("key");
mews/captcha验证码
-
安装
a. 通过composer安装$ composer require mews/captcha
b. 配置config/app.php
'providers' => [ //新增 Mews\Captcha\CaptchaServiceProvider::class, ], 'aliases' => [ //新增 'Captcha' => Mews\Captcha\Facades\Captcha::class, ],
c. 通过脚手架生成配置文件(config/captcha.php)
$ php artisan vendor:publish
-
使用(接口方式)
由于原方法使用的是hash加解方法,也就是说可以通过同一个hash串重复请求,所以需要在本地缓存。(这里我重写了验证方法,因为我下完包之后死活也验证不了hash正确性,一直都是false)
a. 创建自定义工具类:CustomCaptcha.php<?php namespace App\Http\Utils; use Mews\Captcha\Captcha; class CustomCaptcha extends \Mews\Captcha\Captcha { /** * @param array $code */ //构造方法,传入建好的验证码对象 public function __construct(Captcha $captcha) { parent::__construct($captcha->files, $captcha->config, $captcha->imageManager, $captcha->session, $captcha->hasher, $captcha->str); parent::create('flat', true); } //获取验证码的真实值 public function getCode() { return implode($this->text); } //获取BASE64格式图片 public function getImg() { return $this->image->encode('data-url')->encoded; } }
b. 在控制器中使用:
//获取验证码的方法(接口控制器) function getCaptcha(Request $request, Captcha $captchaBuilder) { //获取laravel的session token,这里的思想是通过缓存token与验证码值来验证以避免重复提交同一hash问题 $key = $request->cookie(app()->getNamespace() . "session"); //创建自定义验证码对象,需要将构建器传入 $captcha = new CustomCaptcha($captchaBuilder); //设置过期时间。我设置了两分钟 $expiredAt = now()->addMinute(2); //将验证码值,session token放入缓存并设置过期时间 Cache::put($key, ['captcha' => $captcha->getCode()], $expiredAt); //构建返回数组,包括有效期截止时间和BASE64格式图片 $result = [ 'expired_at' => $expiredAt->toDateTimeString(), 'captcha_img' => $captcha->getImg() ]; //返回201 Created return response()->json($result)->setStatusCode(201); } //验证用户提交的验证码,返回值bool(私有方法) private function check_captcha($captcha,$session):bool{ //通过传入的session获取缓存中的验证码对象,不存在则返回验证失败 $captchaData = Cache::get($session); Cache::forget($session); if ($captchaData == null) { return false; } //判断传入的验证码与缓存是否相等 if ($captcha == $captchaData['captcha']){ return true; }else{ return false; } } //具体使用验证码的方法,接口控制器 function check_captcha(Request $request) { //通过request获取到session token后通过上面的方法验证是否正确 if (!$this->check_captcha($request->get("captcha"), $request->cookie(app()->getNamespace() . "session"))) { //这里的R类是我自定义的返回类 return R::error(HTTP_CODE::UNAUTHORIZED_CAPTCHA); } return R::ok(); }
自定义返回类
- 用于返回json格式接口R.php
<?php namespace App\Http\Controllers; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Routing\Controller as BaseController; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; class R extends BaseController { use AuthorizesRequests, DispatchesJobs, ValidatesRequests; //返回成功的方法 static public function ok($data = []) { return response()->json([ 'status' => true, //这里只支持200,201等其他代码可以用error方法 'code' => 200, //这里用了翻译文件来返回,如果不需要翻译可以直接加一个参数赋在这里 'message' => trans('http_codes.code')[200], 'data' => $data, ]); } //返回错误的方法 static public function error($code, $data = []) { return response()->json([ 'status' => false, 'code' => $code, 'message' => trans('http_codes.code')[(int)$code], 'data' => $data, ]); } }
路由
-
路由位置
页面路由在routes/web.php中,访问路径为host/xxx
接口路由在routes/api.php中,接口路由默认路径为host/api/xxx -
添加路由
//路由单例,/index为地址,view('index')为返回index.blade.php模板生成的页面 //访问路径为域名host/index Route::get("/index",function (){ return view('index'); }); //路由群组。/test为群组访问uri //三个链接分别是 host/test/1,host/test/2,host/test/3 Route::group(['prefix'=>'/test'],function (){ Route::get("/1",function (){ return view('index'); }); Route::get("/2",function (){ return view('login'); }); Route::get("/3",function (){ return view('register'); }); }); //中间件,在参数中添加middleware,指向为添加在中间件配置中的别名,见下节 Route::group(['prefix'=>'/','middleware'=>MiddleWares::Alias],function (){ Route::get("/test",function (){ return view('test'); }); }); //接口控制器 //当路由为接口时,可以返回控制器 //为一个数组,前面为控制器文件,后面为执行的控制器方法 //该接口链接为host/api/user/login Route::post('/user/login', [LoginController::class,"login"]);
中间件Middleware
可用于登录验证,非法请求拦截,xss filter等
-
利用脚手架生成中间件
$ php artisan make:middleware TestMiddleware
-
注册中间件别名
将中间件别名加入config/app.php... 'aliases' => [ ... "xxxMiddleware"=>XxxMiddleware::class, ];
-
中间件实例
<?php namespace App\Http\Middleware\System; ...引入包 class AuthMiddleware { //中间件句柄 public function handle(Request $request, Closure $next) { ...中间件处理方法 //直接跳转至某页面 if(xxx){ return redirect('/login'); } //将数据通过header向下传递 $request->attributes->add(["key":"vaule"]); //向下继续执行 return $next($request); } }
控制器Controller
-
通过脚手架生成控制器
$ php artisan make:controller TestController
-
控制器实例
<?php namespace App\Http\Controllers\User; ...引入包 class LoginController extends Controller { //控制器方法,可在路由中调用 function login(Request $request) { ...业务代码 return R::ok(); } function logout(Request $request) { ...业务代码 return R::error(xxx); } }
cookie
laravel的cookie都是以jwt形式加密的,使用前需要将之cookie加密中间件添加进内核,否则cookie无法生效
//app/Http/Kernel.php
...
protected $middlewareGroups = [
...
"web"=>[
...
\App\Http\Middleware\EncryptCookies::class,
]
...
"api"=>[
...
\App\Http\Middleware\EncryptCookies::class,
]
...
],
...
卸载自带认证器
$ composer remove laravel/sanctum
$ composer remove laravel/passport
自动代码补全
- 安装Laravel Plugin插件
- 安装IDE助手
# 补全工具 $ composer require --dev barryvdh/laravel-ide-helper # 模型注释工具 $ composer require doctrine/dbal # 复制配置文件,进入config/ide-helper.php中将include_fluent改为true来支持自动链式操作 $ php artisan vendor:publish --provider="Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider" --tag=config # 清除bootstrap/compiled.php $ php artisan clear-compiled # Facades 注释 $ php artisan ide-helper:generate # 数据模型注释 $ php artisan ide-helper:models # 工厂模式 $ php artisan ide-helper:meta
本篇内容为原创内容,采用CC BY-NC-SA 4.0协议许可
2021-08-31 16:47
UtopiaXC
于北京
Comments | NOTHING