composer create-project --prefer-dist laravel/laravel projectname chmod -R a+w storage bootstrap/cache # 設定目錄權限 php artisan key:generate # 生成加密祕鑰 confit/app.php配置timezone=>Asia/Shanghai, locale=>zh * 服務器解析到`public`目錄上 *
.env
配置文件、phpunit.xml env
變量設定 會被加載至兩處
phpunit.xml env
配置失效)PHP $_ENV
變量env()
讀取的是系統環境變量.env
文件在Docker
容器啓動時被加載到容器的系統環境變量App::environment()
App\Exceptions\Handler
處理
report()
(默認是記錄日誌)render()
abort(404 [,'error msg'])
resources/views/errors/404.blade.php
APP_DEBUG=true
Monolog
日誌
APP_LOG=single
(single、daily、syslog、errorlog
)APP_LOG_LEVEL=debug
\Log::debug|info|notice|warning|error|critical|alert|emergency('xxx', Array $context)
(錯誤級別降序)php artisan make:provider XxxServiceProvider
(自動註冊於 config/app.php
)Provider
的register
完畢後才調用boot
Provider
protected $defer = true;
provides
方法返回延遲加載服務的類名綁定javascript
* 僅當須要修改容器中綁定的對象時才進行手工綁定 * $this->app->bind(類名, 閉包); # 簡單綁定 $this->app->bind(接口名, 類名); # 接口實現綁定 $this->app->singleton(類名, 閉包); # 單例綁定 $this->app->instance(類名, 對象); # 實例綁定 $this->app->when(類名)->needs(類名)->give(閉包); # 場景綁定 $this->app->when(類名)->needs('$變量名')->give(變量值); # 數據綁定
解析php
* $this->app->make(類名); * app(類名) * resolve(類名); * 自動依賴注入
容器事件css
* 每當服務容器解析一個對象前就會觸發一個事件 - 前置回調 * $this->app->resolving(function ($object, $app) { // 解析任何類型的對象時都會調用該方法... }); $this->app->resolving(HelpSpot\API::class, function ($api, $app) { // 解析「HelpSpot\API」類型的對象時調用... });
\Cache
\Illuminate\Support\Facades\Cache
Illuminate\Support\Facades\Facade
類,並實現getFacadeAccessor
方法返回容器綁定key路由方法html
get、post、put、patch、delete、options
- 匹配基本請求類型Route::get(路徑, 控制器@方法, ['except'=>[..], 'only'=>[..]]) ->where(正則約束) ->middleware('') ->name('')
match
- 匹配多個請求類型any
- 匹配全部請求類型resource
- 處理Rest請求
index、create、store、show、edit、update、destroy
Route::resource(路徑, 控制器, ['except'=>[..], 'only'=>[..]])
$url = route('profile', Array $context) # 從命名路由生成url return redirect()->route('profile'); # 重定向到命名路由 ## 當前路由信息 ## $route = Route::current(); $name = Route::currentRouteName(); $action = Route::currentRouteAction(); ## 控制器中調用路由參數 ## $this->route('ParaName') ## 表單方法僞造 ## {{ method_field('PUT') }} # 生成路由緩存(僅對基於控制器實現的路由有效) php artisan route:clear php artisan route:cache
app/Http/Kernel.php
bootstrap/app.php
BeforeMiddleware
BeforeMiddleware
$router->middleware('xxx', ...)
(別名或全名)Route::group(['middleware' => ['xxx', ...]], Closure);
$this->middleware('xxx')->only()->except()
terminate($request, $response)
方法(響應被髮送到瀏覽器以後才運行)$middlewareGroups
屬性->middleware('中間件名:參數1,參數2,...');
{{ csrf_field() }}
自動觸發 VerifyCsrfToken
中間件<meta name="csrf-token" content="{{ csrf_token() }}">
$.ajaxSetup({headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}});
public function __invoke
方法(路由不指定Action
)php artisan make:controller XxxController --resource
$request->get|input(xxx)
$request->all()
_method
指定HTTP類型 {{ method_field('PUT') }}
return response()->json(array $data)[->withCallback($jsonpCallbackName)]
return response()->download($pathToFile [, $name, $headers])->deleteFileAfterSend(true) #文件名必須ascii
return response()->file($pathToFile [, $headers])
# 嵌套視圖路徑用點隔開 - 常規視圖:return view($viewName, $data)[->with($key, $value)](或者View::make()) - 定製頭部:return response()->view($viewName, $data, $statuCode)->header($field, $value) View::exists($viewName) #檢查視圖是否存在 View::share($key, $value) #設定所有視圖共享的數據,AppServiceProvider::boot()中 ## 視圖編排ViewComposers(在視圖輸出前作修飾)## # 定義composer類 class MyComposer { public function compose(View $view) { $view->.... } } # 視圖綁定composer View::composer($viewName|$viewNames|*, $composer::Class|function($view){}) ## ViewCreator(視圖一建立就執行修飾) ## View::creator($viewName|$viewNames|*, $creator::Class|function($view){})
$response = response($content, $statusCode) $response->header($field, $value)->withHeaders(array $headers) $response->cookies($name, $value, $minutes [, $path, $domain, $secure, $httpOnly]) #中間件EncryptCookies::$except中配置不加密簽名的cookie項
- 常規跳轉:return redirect($url) - 帶session閃存跳轉:return redirect($url)->with($name, $value) - 跳至命名路由:return redirect()->route($routeName [, array $routeParams]) - 回到上一頁:return back()->withInput(); #基於session實現的 - 跳至控制器方法:return redirect()->action('Controller@action' [, array $params])
細節前端
blade
註釋不會html
輸出{{-- 註釋內容 --}}
@php xxx @endphp
@push(棧名) xxx @endpush
,調用@stack(棧名)
@inject('varName', My::class)
,調用{{ $varName }}
佈局和區塊vue
@extends(區塊名)
@section(區塊名, 'content')
@section(區塊名) @parent xxx @endsection
#@parant
指令引入繼承區塊的內容@yield(區塊名)
組件和插槽
用於視圖組件的重用java
{{ $slot }}
{{ $varname }}
component(組件視圖名 [, array $data]) @slot('varname') 命名插槽數據 @endslot 默認插槽數據 endcomponent
子視圖webpack
@include(視圖名 [, $data])
@includeif(視圖名 [, $data])
@each(視圖名, $collection, 'itemName', 集合空的候選視圖)
數據輸出laravel
{{ $var }}
{!! $var !!}
{{ func() }}
@{{ $var }}
(最終結果雙括號保留,@符剔除)@verbatim xxx @endverbatim
控制流web
@if (bool) xxx @elseif (bool) xxx @else xxx @endif
@unless (bool) xxx @endunless
@isset(bool) xxx @endisset
@empty(bool) xxx @endempty
@for ($i = 0; $i < 10; $i++) xxx @endfor
@foreach () xxx @endforeach
@forelse () xxx @empty yyy @endforelse
@while (bool) xxx @endwhile
@continue
@continue(bool)
@break
@break(bool)
*循環變量$loop->index
$loop->first
$loop->last
$loop->count
$loop->parent
自定義指令
php artisan view:clear
Blade::directive('directName', function ($expression) { return "<?php echo xxx; ?>"; });
resources/lang/zh/file.php
config/app.php
App::setLocale($locale)
App::getLocale(); App::isLocale('en');
__('[filename.]lanKey' [, array $data])
($data
可替換翻譯中的:xxx
佔位符)@lang('[filename.]lanKey')
|
隔開{0}xxx|[1,10]yyy|[11,*]zzz
trans_choice('[filename.]lanKey', $num)
resources/lang/vendor/{package}/{locale}
前端移除 可選移除前端腳手架 php artisan preset none
Mix運行
npm install #安裝package.json中的依賴 # 執行構建任務 npm run dev npm run production # 監控文件變更自動從新構建 npm run watch npm run watch-poll #自動監控無效可用這個命令
Mix構建定義 - 基於webpack
定義構建任務(webpack.mix.js
)
# 構建基礎 mix.webpackConfig({}) #部分調整webpack配置(亦可整個重置webpack.config.js) .less|sass|js($from, $to, {$settings}) .options({processCssUrls:false}) .extract(['vue', ...]) #將指定依賴庫導出到vendor.js文件 .version() #version後變名資源加載可經過 `mix(資源路徑)` .disableNotifications() #關閉編譯通知 .sourceMaps() # css|js文件合併 mix.styles|scripts([$fromPaths], $targetPath) # 文件|目錄拷貝 mix.copy|copyDirectory($from, $to) # 使用編譯的js(順序加載) <script src="/js/manifest.js"></script> <script src="/js/vendor.js"></script> <script src="/js/app.js"></script> # `npm run環境`的檢測 mix.inProduction()
browserSync支持
1. mix.browserSync(域名|{詳細配置}) #瀏覽器:3000 -> browserSyn -> WebServer -> 文件監控 2. npm run watch
環境變量
.env
中MIX_
打頭的變量process.env.變量名
redirect
至先前位置ajax
請求返回json錯誤信息
及422狀態碼flash
至 session
MessageBag $errors
自動被 ShareErrorsFromSession
中間件綁定到視圖bail
先決規則(任意規則校驗失敗後,該字段後續規則再也不進行)sometimes
規則(有則校驗)校驗方式
$this->validate($request, array $rules)
$validator = Validator::make($request->all(), array $rules); $validator->validate(); # 校驗失敗將自動跳轉 $validator->fails(); $validator->after(function($validator){}); #驗證後鉤子
Request
php artisan make:request MyRequest
- 路徑app/Http/Requests
MyRequet
實現rules()+messages()、authorize()
邏輯MyRequest
後會自動在方法執行前進行驗證錯誤消息
/** $return Illuminate\Support\MessageBag */ $errors = $validator->errors(); $errors->has('FieldName'); # 檢查指定字段時候出錯 $errors->first('FieldName'); # 指定字段第一個錯誤提示 $errors->get('FieldName'); # 指定字段全部錯誤提示 $errors->all(); # 所有錯誤
底層
# 讀寫分離配置 database鏈接配置下新增read、write鍵並配置相應db集羣 DB::connection(鏈接名)->select(...); # 數據庫切換 DB::connection()->getPdo(); # 得到底層pdo實例 ## 數據庫事務 ## - 自動模式 DB::transaction(Closure); - 手動模式 DB::beginTransaction(); DB::rollBack(); DB::commit(); ## 數據庫鎖 ## $builder->sharedLock(); # 共享鎖(鎖住寫入) $builder->lockForUpdate(); # 悲觀所(鎖住讀寫)
QueryBuilder
* 查詢結果`Illuminate\Support\Collection`集合中的每一個實例都是`StdClass`類型 * DB::get|first|select|insert|update|delete|statement($sql, array $params); # 原生sql查詢 $builder = DB::table('tableName'); # 查詢構造器 $builder->insert($row | $rows); # 批量插入 $builder->chunk($perPage, function($records){...}); # 查詢結果分塊,閉包若返回false則將中止處理後續結果 $builder->distinct(); # 去重 $builder->->increment('field' [, $step]; # 遞增 $builder->whereColumn('field1', '=', 'field2'); # 列比較 # 字段值 $builder->value(FieldName); # 獲取一行記錄的字段值 $builder->pluck(FieldName); # 獲取集合的一列字段字段值 $builder->pluck(KeyField, $ValueField); # 獲取集合的兩列鍵值字段 # 字段選取 $builder->select('field1', 'xxx as filed2'); $builder->select(DB::raw('field1, xxx as filed2')); # 參數分組(經過where的閉包進行) $builder->where(function($query){ $query->where ... }); # exist查詢 $builder->whereExists(function($query){ $query->select('xx')->from('xx')->where('child.parent_id = parent.id')... }); ## 子查詢構建 $builder = DB::table(DB::raw("({$childQuery->toSql()}) as tmp"))->->mergeBindings($childQuery->getQuery());
分頁
# 系統默認當前頁碼?page=參數 # 直接返回分頁器, 將被框架自動轉成JSON # 建立分頁 $builder|Model->paginate($perPage) // Illuminate\Pagination\LengthAwarePaginator 帶完整分頁信息 $builder|Model->simplePaginate($perPage) // Illuminate\Pagination\Paginator 不查詢分頁狀況(僅知道先後頁的簡單分頁) # 內部集合數據 $paginator->getCollection() $paginator->setCollection($collection) # 分頁助手方法 ->links(【'view.自定義分頁模板'】) # 分頁連接(php artisan vendor:publish --tag=laravel-pagination) ->setPath($uri) # 設定基礎uri ->appends(Array) # 分頁連接加參數
Migration
php artisan make:migration create_xxxs_table --create|table=xxxs # migration建表 php artisan migrate:rollback 【--step=num】 # 回滾上次數據庫變更涉及的migration操做 php artisan migrate:reset # 回滾全部migration php artisan migrate:refresh 【--step=num】 # 先重置後重載migration Schema::hasTable($tableName) # 結構檢查 Schema::hasColumn($colName1, ...) Schema::connection('foo') # 切換連接 Schema::rename($from, $to) # 重命名 Schema::drop|dropIfExists($tableName) # 刪除 # 表定義 $table->increments('id'); $table->字段類型(字段名)->unsigned()->nullable()->default(默認值)->after(列名)->comment(註釋); #字段定義 $table->timestamps(); #created_at & updated_at $table->softDeletes(); #軟刪除deleted_at $table->索引類型(字段名 [, 索引名稱]); #索引定義(複合索引則傳入字段數組) # 雜項表處理 $table->engine = 'InnoDB'; $table->....->change(); #更新已有字段 $table->renameColumn('from', 'to'); #重命名字段 $table->dropColumn($colName); #刪除字段 $table->dropIndex($index); #刪除索引 # !注意事項! # SQLite 在單個Schema下只支持處理一個Column
基礎查詢
php artisan make:model Models/ModelName -m # 查 $builder = Model::query() | $model->newQuery() $builder->get() $builder->first|firstOrFail() $builder->chunk($num, function($rows{ }); Model::all() #表中全部記錄 Model::find|findOrFail($id | $ids) # 遊標查詢 foreach($builder->cursor() as $item) # 一次查一條,節約內存 # 增 $model=new MyModel;$model->save(); Model::create($data); Model::firstOrCreate($data); Model::firstOrNew($data); # 刪 $builder->delete(); # 批量刪除 $model->delete(); Model::destroy($ids); # 改 $model->save(); $builder->update($data); # 批量更新
模型定製屬性
protected $connection = 'connectionName'; # 重定向鏈接名 protected $table = 'tableName'; # 重定向表名(默認使用模型的SnakeCase複數形式爲表名) protected $primaryKey = 'fieldName'; # 重定向主鍵名(默認爲整型id) public $incrementing = false; # 聲明主鍵爲非遞增、非數字 # 默認的created_at、updated_at字段被轉換成Carbon protected $dates = [created_at', 'updated_at', 'deleted_at']; # 指定哪些字段被自動Carbon轉換 protected $dateFormat = 'Y-m-d H:i:s'; # 設定日期字段存儲或序列化的格式 const CREATED_AT = 'createtimeName'; # 重指定默認建立時間字段 const UPDATED_AT = 'updatetimeName'; # 重指定默認ge時間字段 public $timestamps = false; # 禁止自動維護時間字段(默認的單個模型save()方法調用時自動更新兩個時間字段) # 調用create()批量賦值前配置下面屬性之一(Mass-Assignment批量賦值保護) protected $guarded = []; # 黑名單,空數組則全部屬性可被批量賦值 protected $fillable = []; # 白名單 # belongsTo、belongsToMany關係 更新父級時間戳 protected $touches = [關聯名]; # 屬性類型轉換,支持integer,real,float,double,string,boolean,object,array,collection,date,datetime,timestamp protected $casts = [字段 => 目標數據類型]; # 特點使用:json字段array類型轉換爲數組 # 字段顯示與隱藏(影響toArray、toJson方法) protected $hidden = ['password']; protected $visible = ['id', 'name']; # 臨時修改字段可見性 $model->makeVisible/makeHidden('field')->toArray(); # array/json輸出追加訪問器字段 protected $appends = ['is_admin']; public function getIsAdminAttribute() { return (bool)this->attributes['admin']; } # 動態重定向鏈接名 public function getConnectionName() { return app()->environment('testing') ? 'DatabaseName' : config('database.default'); } # 字段值修飾器 - 區別於`eloquence`中的`Mappable, Mutable` - accessor —— 修飾器方法取名爲 「get字段駝峯式Attribute($value)」 - mutator —— 修飾器方法取名爲 「get字段駝峯式Attribute($value)」
軟刪除
# migration建立軟刪除字段 $table->softDeletes(); # 模型聲明軟刪除(deleted_at非空時認定爲記錄已被刪除) use SoftDeletes; protected $dates = ['deleted_at']; $model->trashed(); # 判斷是否被軟刪除 $model->forceDelete(); # 強制徹底刪除 # 恢復被軟刪除的數據 $model->restore(); # 單個恢復 $builder->restore(); # 批量恢復 # 默認軟刪除數據不在查詢結果中 Model::withTrashed() # 聲明包含軟刪除數據 Model::onlyTrashed() # 聲明只查詢軟刪除數據
查詢做用域(增長查詢約束條件)
## 全局做用域 ## class CustomScope implenments Scope { public function apply(Builder $builder, Model $model) { return $builder->where... } } class CustomModel extends Model { protected static function boot() { parent::boot(); # 模型綁定全局做用域類 static::addGlobalScope(new AgeScope); # 模型綁定全局域閉包 static::addGlobalScope('age', function(Builder $builder) { $builder->where... }); } } # 臨時解除全局做用域 Model::withoutGlobalScope(...) ## 本地做用域 ## class CustomModel extends Model { public function scopeXxx($query【, $params】) { return $query->where... } } # 本地做用域(臨時做用) $builder->Xxx([$params])... CustomModel::Xxx([$params])
打印SQL
/* @var \Illuminate\Database\Eloquent\Builder $query */ $query->toSql(); \DB::enableQueryLog(); # SQL查詢 dd(\DB::getQueryLog());
模型事件
# 模型生命週期事件 creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored # 監聽模型事件 AppServiceProvider->boot() { # 監聽sql查詢事件 \DB::listen(function ($query) { dump($query->sql, $query->bindings); }); # 註冊模型單一事件監聽器 XxxModel::creating(function ($xxxModel) { # 返回false將取消 save / update 操做 return boolean; }); # 用observer管理模型一組事件監聽器 XxxModel::observe(XxxObserver::class); } class XxxObserver { public function created(XxxModel $Xxx){ ... } }
關聯定義
多對多關聯是個綁定關係 & 其餘關聯是個衍生關係 ## 正向關係 ## - 子模型外鍵參考爲「snake父模型名_主鍵」 - 父模型本地鍵參考爲「主鍵」 $this->hasOne(子模型, 外鍵, 本地鍵) #一對一 $this->hasMany(子模型, 外鍵, 本地鍵) #一對多 ## 反向關係 ## - 子模型外鍵參考爲「snake關聯方法名_主鍵」 - 父模型其餘鍵參考爲「主鍵」 $this->belongsTo(父模型, 外鍵, 其餘鍵) #一對一 $this->belongsTo(父模型, 外鍵, 其餘鍵) #多對一 ## 多對多 ## - 中間表名參考爲「字母順序排列組合的下劃線表名」 - 中間表上的外鍵: * 當前模型外鍵參考爲「snake當前模型名_主鍵」 * 關聯模型外鍵參考爲「snake關聯模型名_主鍵」 $this->belongsToMany(關聯模型, 中間表, 當前模型外鍵, 關聯模型外鍵) ->using(中間表模型) #可選,自定義中間表模型(繼承Illuminate\Database\Eloquent\Relations\Pivot) ->wherePivot|wherePivotIn() #可選,過濾中間表字段 ->withPivot($field1, ...) #可選,聲明中間表包含的外鍵之外的字段 ## 遠程一對多 ## 一對多兩級放大 - 中間模型外鍵參考爲「snake模型名_主鍵」 - 遠程模型外鍵參考爲「snake模型名_主鍵」 - 當前模型本地鍵參考爲「snake模型名_主鍵」 $this->hasManyThrough(遠程模型, 中間模型, 中建模型外鍵, 遠程模型外鍵, 本地鍵) ## 一對多morph多態 ## 多個一衍生針對同組多 - 可選關聯名參考爲「關聯方法名」,必選關聯名建議爲「子模型名able」 - type字段名參考爲「關聯名_type」 - id字段名參考爲「關聯名_id」 - 本地鍵參考爲「主鍵」 正向s: $this->morphMany(子模型, 必選關聯名, [type字段名, id字段名, 本地鍵]) 反向able:$this->morphTo([可選關聯名, type字段名, id字段名]) - 默認「type字段值」參考爲「完整命名空間指定模型名」 - 自定義type字段值需註冊多態映射到AppServiceProvider::boot use Illuminate\Database\Eloquent\Relations\Relation; Relation::morphMap([type => 模型]); ## 多對多morph多態 ## 多個一跨中間表綁定共享同一組多 多對多關聯基礎上,其中一端多進行多態化 正向s: $this->morphToMany(父模型, 必選關聯名) 多個反向s: $this->morphedByMany(子模型, 必選關聯名)
查詢關聯
################ 查詢關聯數據 - 懶加載 ################ 直接經過動態屬性訪問關聯是「懶加載」,在訪問關聯數據屬性時才加載關聯 查詢: - $model->$relation #直接動態屬性訪問關聯 - $model->$relation->pivot #pivot屬性訪問中間表(多對多關聯場景,且默認只能訪問到外鍵字段) ################ 查詢關聯數據 - 預加載 ################ 使用with方法「EagerLoad預加載」,在查詢父數據時即加載關聯(其`WhereIn`機制解決了`N+1`問題,減小總查詢至2次) 聲明: - 模型::with($relation1, ...) #加載多個關聯 - 模型::with($relation1.$relation1_a, ...) #加載嵌套關聯 - 模型::with([$relation => function($query){ $query->關聯數據約束、排序等 }])->... #約束關聯數據 - $collection|$model->load($relation1, ... | [$relation1 => function])#延遲預加載(手動預加載) 查詢: - $model->$relation #with聲明後動態屬性訪問關聯 ################ 查詢關聯計數 ################ 只統計不加載數據 聲明: - 單個關聯計數 模型::withCount(關聯名)->... - 別名關聯計數 模型::withCount('關聯名 AS 別名')->... - 多個關聯計數 模型::withCount([關聯1, 關聯2])->... - 約束關聯計數 模型::withCount([關聯 => function($query){ $query->where(關聯數據約束) }])->... 查詢: - $model->$relation_count #動態屬性訪問計數 ######## 關聯過濾(過濾條件施加到關聯數據上) ######## ## 查詢結果 - 關聯數據 ## - 模型::with([$relation => function($query){ $query->關聯數據約束、排序等 }])->... #with聲明時關聯過濾 - $model->$relation()->where #關聯結果進一步過濾 ## 查詢結果 - 主對象 ## #1. 關聯數據存在性 約束 - 模型::has(關聯名 [,比較符, 數量])->... #關聯名中可進一步使用點語法來聲明關聯數據下屬數據的存在性 - 模型::whereHas|orWhereHas(關聯名, function($query){ $query->where(關聯數據約束) })->... #2. 關聯數據不存在性 約束 - 模型::doesntHave(關聯名)->... - 模型::whereDoesntHave(關聯名, function($query){ $query->where(關聯數據約束) })->...
插入/更新 關聯數據
## 正向關係 ### $parent->relations()->save($child) $parent->relations()->saveMany(array $childs) $parent->relations()->create(array $child1_data) ## 反向關係 ## $child->relation()->associate($parent) && $child->save() $child->relation()->dissociate($parent) && $child->save() ## 多對多關聯 ## --經過id處理-- - $modelA->relations()->attach($modelB_ID | $modelB_IDS [, array 中間表更新]) #中間表追加綁定關係 - $modelA->relations()->detach($modelB_ID | $modelB_IDS) #中間表解除綁定關係 - $modelA->relations()->detach() #中間表解除A的全部綁定 - $modelA->relations()->sync($modelB_IDS) #中間表重置綁定關係 - $modelA->relations()->syncWithoutDetaching($modelB_IDS) #中間表重置綁定關係(可是不解除已有綁定) - $modelA->relations()->toggle($modelB_IDS) #中間表切換綁定關係(已綁的解綁, 未綁的綁定) --經過對象處理-- - 使用正向關係裏的全部方法 - $modelA->relations()->save($modelB [, array 中間表更新]) #中間表追加綁定關係 - $modelA->relations()->updateExistingPivot($modelB_ID , array 中間表更新) #更新中間表某條綁定關係的數據
普通集合 - Illuminate\Support\Collection
類
$collection|$model->toArray()
$collection|$model->toJson()
collect($array)
contains,each,every,filter,first,map,partition,reject,sortBy,sortByDesc,sum
ORM集合 - Illuminate\Database\Eloquent\Collection
Cache::store($storeType)->...;# 切換緩存的store驅動 Cache->get($key【, $default】); Cache->put($key, $value, $minutes|$expiresAt); Cache::forget($key); //刪除緩存 Cache::flush(); //清空全部緩存 Cache->add($key, $value, $minutes|$expiresAt); //不存在時才更新,實際寫入時返回true Cache->forever($key【, $default】); //永久緩存 Cache::has($key); Cache::increment|decrement($key【, $step】); Cache::remember($key, $minutes, Closure); //獲取值,不存在則閉包更新 Cache::pull($key); // 一次性獲取而後刪除 # 緩存標籤 Cache::tags(array $tags)->put($key, $value, $minutes); Cache::tags(array $tags)->get($key); Cache::tags(array $tags)->flush(); # EventServiceProvider中可註冊監聽緩存事件
綁定
EventServiceProvider->listen
中註冊綁定* 根據綁定配置自動建立 `php artisan event:generate` * protected $listen = [ 事件類 => [ 監聽器類1, .... ], ];
EventServiceProvider::boot()
中註冊public function boot() { parent::boot(); # 單一事件監聽 Event::listen('event.事件名', function($data){}); # 全局事件監聽 Event::listen('event.*', function($eventName, array $eventData){}); }
單事件監聽器
handle
中返回false
將會ShouldQueue
接口public $connection|$queue
定製 鏈接&隊列public function failed(OrderShipped $event, $exception)
中處理FailedJob
多事件訂閱者
EventServiceProvider $subscribe
中註冊
namespace App\Listeners; class MyEventSubscriber { public function onMyAction($event){...} # 處理訂閱邏輯 public function subscribe($events) { $events->listen(事件類, 'MyEventSubscriber@onMyAction'); } }
派發事件 event(new MyEvent())
快速搭建
php artisan make:auth
生成認證相關的路由、視圖、home示例php artisan migrate
數據表準備config/auth.php
配置
web session、api token
兩種)Eloquent、Database
兩種)
remember_token
字段(用於記住我)username()
(默認email
字段)use ThrottlesLogins
(認證字段+IP限流試登次數/Min)Auth控制器定製
$redirectTo | redirectTo()
(默認/home
)Guard
認證模式guard()
登陸檢查
Auth::check()
auth
路由中間件檢查
guard
:->middleware('auth')
guard
:->middleware('auth:api')
獲取用戶
$request->user(); Auth::user(); Auth::id();
自主認證
$credentials = ['email' => $email, 'password' => $password, ...] #憑據 Auth::[guard('web')]->attempt($credentials [, $boolRememberMe]) #登陸(返回bool,登陸成功則啓動認證session) Auth::logout() #登出(清除session登陸信息) Auth::once($credentials) #僅認證一次當前請求(no session) return redirect()->intended(備用地址) #跳至被認證中間件截斷的原先意向頁面 Auth::viaRemember() #檢查用戶是否經過`RememberMe cookie`登陸(返回bool)
模擬身份
# 登入爲指定用戶 Auth::[guard('web')]->login($user [, $boolRemember]) Auth::[guard('web')]->loginUsingId($userId [, $boolRememberMe])
自定義Guard
# 定義 Illuminate\Contracts\Auth\Guard # AuthServiceProvider::boot()下注冊 Auth::extend('my_guard_driver', function($app, $name, array $config){ return new MyGuard(Auth::createUserProvider($config['provider'])); }); # config('auth.guards')下配置 'guards' => [ 'my_guard' => [ 'driver' => 'my_guard_driver', 'provider' => 'users', ], ],
自定義Providor
# 定義 Illuminate\Contracts\Auth\UserProvider # AuthServiceProvider::boot()下注冊 Auth::provider('my_provider_dirver', function($app, array $config) { return new MyProvider($app->make('riak.connection')); }); # config('auth.guards')下配置 'providers' => [ 'my_provider' => [ 'driver' => 'my_provider_dirver', ], ],
認證事件
# Illuminate\Auth\Events空間下事件 - Registered - Attempting - Authenticated - Login - Failed - Logout - Lockout
密碼重置
內建帳戶系統的重置機制
User
模型配置
use Notifiable
implement CanResetPassword
(use CanResetPassword
來實現)reset token
表ForgotPasswordController|ResetPasswordController::broker()
定製Password Broker
User::sendPasswordResetNotification()
定製重置郵件的通知類加密解密
APP_KEY
)
encrypt|decrypt()
(支持字符串、對象、數組)\Crypt::encryptString|decryptString()
(支持字符串)HASH
Hash
提供Bcrypt
散列處理(默認用於內建帳戶系統的密碼存儲)\Hash::make($str);
\Hash::check($str, $hashedStr);
Gate鑑權 簡易、閉包式、資源無關的 鑑權(定義在AuthServiceProvider::boot())
## 定義 ## Gate::define(權限名, function ($user [, $model]) { return bool }); Gate::define(權限名, '策略類@操做') Gate::resource(資源名, 策略類名) #資源式Gate(默認 資源.view、create、update、delete) ## 鑑權 ## Gate::allows|denies(權限名 [, $model]) #默認當前用戶 Gate::forUser($user)->allows|denies(權限名 [, $model]) #明確指定用戶
Policy鑑權 鑑權特定資源的幾個操做
## 定義 ## php artisan make:policy MyPolicy [--model=My] AuthServiceProvider::$policies #註冊以關聯 策略&資源 MyPolicy::before($user, $ability) #策略過濾以預鑑權(返回null才進入policy鑑權) ## 鑑權 ## $user->can|cant(權限名, $model|Model::class) #未經過則返回false Controller->authorize(權限名, $model|Model::class) #未經過則拋出AuthorizationException ## Blade模板鑑權 ## can|cannot(權限名, $model|Model::class) xxx elsecan|elsecannot(權限名, $model|Model::class) xxx endcan|endcannot
建立命令
php artisan make:command 命令名
(默認目錄app/Console/Commands
){name=default}
{name?}
{name*}
{--opt}
(選項簡寫{--O|opt}
){--opt=default}
{--opt*}
: description
null
)
$this->argument('name')
、全部參數$this->arguments()
$this->option('name')
、全部選項$this->options()
交互
$answer = $this->ask('question?');
$answer = $this->secret('question?');
if ($this->confirm('Are you sure?'))
$name = $this->anticipate('Whats your name?', ['Tom', 'Jim']);
$name = $this->choice('Whats your name?', ['Tom', 'Jim'], 'defaultName');
輸出
$this->line()
$this->info()
$this->error()
$this->question()
$this->comment()
$this->table([$field1...], [$value1...])
$bar = $this->output->createProgressBar($num); $bar->advance(); $bar->finish();
註冊命令
$this->load(__DIR__.'/Commands');
Kernel::$commands
編程調用命令
Artisan::call($command, array $args);
Artisan::queue($command, array $args)->onConnection(鏈接名)->onQueue(隊列名);
$this->call($command, array $args);
$this->callSilent($command, array $args);
其餘命令
routes/console.php
Artisan::command('sig:nature {arg}' function($arg){...})->describe(命令描述);
php artisan serve # 啓動本地開發服務器localhost:8000 php artisan down --message='系統升級中' # 進入維護模式:關閉服務、隊列(默認視圖resources/views/errors/503.blade.php) php artisan up # 服務重啓
App\Console\Kernel::schedule(Schedule $schedule)
* * * * * php 項目路徑/artisan schedule:run >> /dev/null 2>&1
調度模式
$schedule->call(function(){. . .})->daily();
$schedule->command('xxx:yyy --force')->daily(); $schedule->command(XxxCommand::class, ['--force'])->daily();
$schedule->exec('echo HelloWorld')->daily();
調度頻率
->cron('* * * * * *') #自定義頻率 ->everyMinute() ->hourly() | ->hourlyAt(20) ->daily() | ->dailyAt('13:00') ->weekly() ->monthly() | ->monthlyOn(4, '15:00') ->quarterly() ->yearly()
額外約束
->when(閉包) ->at('13:00') ->between('8:00', '17:00') ->>mondays|weekdays|sundays|...() ->timezone('America/New_York') #設置時區
任務輸出
# 只適用於 $schedule->command() 方法 ->appendOutputTo|sendOutputTo|emailOutputTo($filePath)
任務鉤子
->before|after(閉包)
Ping
鉤子 ->pingBefore|thenPing(閉包)
(依賴Guzzle
)特殊設定
->withoutOverlapping()
->evenInMaintenanceMode()
覆蓋面:
# mock數據(視狀況可選) $mock = \Mockery::mock(XxxRepository::class); $mock->shouldReceive($methodName)->andReturn($model); $this->app->instance(XxxRepository::class, $mock); #容器針對某類綁定到mock實例 # 發起請求 $this->get/post($api [, array $headers]); # 測試響應 $this->seeStatusCode(200); $this->seeHeader($headName【, $headVal】); $this->seeJsonStructure(array $structure); $this->seeJsonContains(array $structure); $this->seeJsonEquals(array $structure); # 要求完整數據結構 $this->seeInDatabase($tableName, array $data); $this->assertCount($num, array $testData);
config/filesystems.php
中配置文件系統鏈接及其相應驅動
Public文件系統 - 公共訪問磁盤
local
驅動(根路徑storage/app
)public/storage->storage/app/public
(php artisan storage:link
)asset('storage/myfile.txt')
FTP文件系統
'ftp' => [ 'driver' => 'ftp', 'host' => 'ftp.example.com', 'username' => 'your-username', 'password' => 'your-password', // 'port' => 21, // 'root' => '', // 'passive' => true, // 'ssl' => true, // 'timeout' => 30, ],
文件系統操做
$storage = Storage::disk(文件系統鏈接); ->url|get|exists|size|lastModified|getVisibility($path) ->copy|move($fromPath, $toPath) ->delete($filePath|$files) ->put|prepend|append($path, $content|$resource) //大文件建議使用資源句柄 # 自動流式處理,返回完整文件名路徑 * ->putFile($saveDir, Illuminate\Http\File|Illuminate\Http\UploadedFile) #自動生成文件名 * ->putFileAs($saveDir, Illuminate\Http\File|Illuminate\Http\UploadedFile,$saveName) #指定文件存儲名 # 上傳文件處理,返回完整文件名路徑 * Illuminate\Http\UploadedFile $request->file($name)->store($saveDir [, 文件系統鏈接]) #自動生成文件名 * Illuminate\Http\UploadedFile $request->file($name)->storeAs($saveDir, $saveName [, 文件系統鏈接]) #指定文件存儲名 # 目錄 ->files|directories($dir) #不含子目錄 ->allFiles|allDirectories($dir) #包含子目錄 ->makeDirectory|deleteDirectory($dir) #目錄增刪
增長文件系統驅動
1. composer 安裝驅動包 2. 新建ServiceProvidor,boot方法中拓展文件系統驅動 public function boot() { Storage::extend($fileDriverName, function ($app, $config) { $client = new XxxClient(); return new Filesystem(new XxxAdapter($client)); }); }、 3. 基於新驅動配置新文件系統鏈接
國內雲存儲驅動
composer require yangyifan/upload:v0.2.1
php artisan cache:clear
(注意把redis
緩存庫 和 隊列、session
庫分離開)php artisan config:cache
php artisan route:cache
classmap
生成php artisan optimize --force
composer dumpautoload --optimize
Redis
存儲Session
OpCache