給大家提供一些 laravel 使用的小技巧, 當然你有任何想法歡迎 PR !
Github 地址:https://github.com/LaravelDaily/laravel-tips
控制器
單行為控制器
當你的控制器僅有一個方法的時候,不妨嘗試下 __invoke() 方法來,讓當前控制器變身為 “invokable” 控制器。
想要了解單行為控制器的好處以及用法請參考:
單行為控制器的簡單使用:
定義路由,如下:
Route::get('user/{id}', 'ShowProfile');
通過命令創建單行為控制器:
php artisan make:controller ShowProfile --invokable
修改控制器代碼,如下:
class ShowProfile extends Controller { public function __invoke($id) { return view('user.profile', [ 'user' => User::findOrFail($id) ]); } }
重定向到指定控制器的指定方法
你可以通過 redirect() 重定向到某個路由或者某個鏈接,但是當你希望重定向到一個特定方法,并且需要攜帶一些參數的時候,action 方法可以幫你實現,代碼如下:
return redirect()->action('SomeController@method', ['param' => $value]);
接口操作成功而無返回的簡單處理
當你在接口執行了某些邏輯,但是不需要返回內容的時候,你可以直接返回 204 狀態碼。 在 Laravel 中這很容易實現:
public function reorder(Request $request) { foreach ($request->input('rows', []) as $row) { Country::find($row['id'])->update(['position' => $row['position']]); } return response()->noContent(); }
模型
Eloquent 的日期篩選
Laravel 的 Eloquent Orm 提供了 whereDay(), whereMonth(), whereYear(), whereDate() 和 whereTime() 供你對日期進行篩選。簡單例子:
$products = Product::whereDate('created_at', '2018-01-31')->get(); $products = Product::whereMonth('created_at', '12')->get(); $products = Product::whereDay('created_at', '31')->get(); $products = Product::whereYear('created_at', date('Y'))->get(); $products = Product::whereTime('created_at', '=', '14:13:58')->get();
Inter 類型數據的便捷操作 Increments(增加) 和 decrements(減少)
你如果僅僅是操作數字類型字段的增加(減少),你可以嘗試下 ?increment()(decrement()) 方法:
Post::find($post_id)->increment('view_count'); User::find($user_id)->increment('points', 50);
獲取設置當前用戶登錄的信息
你可以使用 make:observer 來創建一個觀察者,然后通過修改模型事件 creating() 來設定當前用戶的信息,代碼如下 :
翻譯:Laravel 應用設計:單行為控制器的魅力
class PostObserver { public function creating(Post $post) { $post->user_id = auth()->id(); } }
軟刪除后的數據批量恢復
當使用軟刪除刪除數據之后,你可以通過以下方法批量恢復刪除的數據:
Post::withTrashed()->where('author_id', 1)->restore();
特定模型字段的返回
默認的 Model::all() 會返回所有字段,不管你是否有需要,當然你也可以通過給 all() 傳遞參數來指定返回的列。如下:
$users = User::all(['id', 'name', 'email']);
失敗或者成功的查詢
findOrFail() 方法,可以在查詢沒有符合條件數據的時候直接拋出異常。
$user = User::where('email', 'povilas@laraveldaily.com')->firstOrFail();
數據返回的列名稱的自定義
在 Eloquent 查詢中使用 select 可以設置查詢的字段,然后你可以通過 “as” 給字段重命名為你想要的名稱:
$users = DB::table('users')->select('name', 'email as user_email')->get();
查詢結果的 Map 處理
由于 Eloquent 中,get 方法將返回 Collection 類型的數據,所以在通過 get 方法獲取數據之后,你可以直接通過 map() 方法來處理:
$users = User::where('role_id', 1)->get()->map(function (User $user) { $user->some_column = some_function($user); return $user; });
不使用 timestamps 相關字段
默認的,laravel 會在 migration 以及 model 中添加 timestamps 相關字段(created_at,updated_at),如果你不想使用他,你可以在migrate 中移除相關字段,或者在 model 中設置 timestamps屬性,將該屬性設置為 false 即可實現:
class Company extends Model { public $timestamps = false; }
修改默認時間字段
當你想要在已存在的數據庫中使用 Laraevl 的 Eloquent Orm的時候,你的時間字段又不同于 Laravel 默認字段,這時候怎么處理呢?你可以通過給以下常量重新賦值來設置當前使用的時間戳字段:
class Role extends Model{ const CREATED_AT = 'create_time'; const UPDATED_AT = 'update_time'; }
快速通過 created_at 排序
在此之前你是這樣實現的:
User::orderBy('created_at', 'desc')->get();
當然,你也可以使用更簡單的方式:
User::latest()->get();
默認 latest() 會通過 created_at 進行排序。
這里還有個反方法可以用: oldest() ?將會通過 created_at 字段進行升序排序。
User::oldest()->get();
當然你也可以通過傳遞參數來執行想要進行排序的字段,如下:
$lastUpdatedUser = User::newest('updated_at')->first();
創建記錄時的自增
當你在創建記錄的時候,你同時希望對某個字段進行自增操作的時候,你可以在 ?boot() ?方法中注冊 creating 方法來實現。舉個例子,現在你有個 “position” 字段,你希望在你完成新增操作的時候同時對該字段 +1 ,實現代碼如下:
class Country extends Model { protected static function boot() { parent::boot(); Country::creating(function($model) { $model->position = Country::max('position') + 1; }); } }
使用 whereRaw() 使查詢效率更快
使用 whereRaw() 方法,通??梢允共樵冃矢?。例如你想獲取 30+ 天未登錄的用戶,你可以通過以下實現:
User::where('active', 1) ->whereRaw('TIMESTAMPDIFF(DAY, created_at, updated_at) > ?', 30) ->get();
多個作用域
你可以同時創建多個作用域,當然可以在一個查詢中使用多個作用域。
模型中定義:
public function scopeActive($query) { return $query->where('active', 1); } public function scopeRegisteredWithinDays($query, $days) { return $query->where('created_at', '>=', now()->subDays($days)); }
controller 中使用:
$users = User::registeredWithinDays(30)->active()->get();
Carbon自動轉換
如果你想使用 whereDate() 查詢今天的記錄,你可以通過直接 now() 而無需進行 ->toDateString(),因為他會自動轉換。
// Instead of $todayUsers = User::whereDate('created_at', now()->toDateString())->get(); // 不需要轉換 now() $todayUsers = User::whereDate('created_at', now())->get();
通過首字符分組
你可以通過任意你想實現的方式進行分組,下面是通過對姓名首字符的分組方法:
$users = User::all()->groupBy(function($item) { return $item->name[0]; });
限制數據列的更新
如果你希望設置一個不可更新的列,你可以通過以下方式實現:
class User extends Model { public function setEmailAttribute($value) { if ($this->email) { return; } $this->attributes['email'] = $value; } }
查詢多個
Eloquent 方法 find() 可以通過傳遞數組參數實現多個記錄的查詢:
// Will return Eloquent Model $user = User::find(1); // Will return Eloquent Collection $users = User::find([1,2,3]);
使用 UUID 替代 自增列
如果你不想在數據表中使用自增列要怎么辦?下面叫你如何實現
數據遷移:
Schema::create('users', function (Blueprint $table) { // $table->increments('id'); $table->uuid('id')->unique(); });
模型:
class User extends Model { public $incrementing = false; protected $keyType = 'string'; protected static function boot() { parent::boot(); User::creating(function ($model) { $model->setId(); }); } public function setId() { $this->attributes['id'] = Str::uuid(); } }
模型關聯
可排序的模型關聯
你可以在你的關聯中使用 orderBy對關聯進行排序:
public function products() { return $this->hasMany(Product::class); } public function productsByName() { return $this->hasMany(Product::class)->orderBy('name'); }
有條件的模型關聯
如果你在使用模型關聯的時候經常需要額外的進行 where 查詢,你可以直接通過對關聯進行條件查詢,實現方式如下:
Model:
public function comments() { return $this->hasMany(Comment::class); } public function approved_comments() { return $this->hasMany(Comment::class)->where('approved', 1); }
對結果的篩選:havingRaw()
你可以在各種地方使用 RAW DB 查詢,包括 ?groupBy() ?和 havingRaw() 后面:
Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get();
Eloquent has() 方法可以作用于深層的關聯
Eloquent has() 方法可以通過 books.ratings 的方式,而使查詢可以做用于更深層的關聯上!
// Author -> hasMany(Book::class); // Book -> hasMany(Rating::class); $authors = Author::has('books.ratings')->get();
通過 Has 方法對 hasMany 數據限制
在一對多關聯中, hasMany() 允許通過 has() 方法進行關聯數據條數的限制:
// Author -> hasMany(Book::class) $authors = Author::has('books', '>', 5)->get();
模型默認值
你可以通過 belongsTo 關聯, to avoid fatal errors when calling it like {{ $post->user->name }} if $post->user doesn’t exist.
public function user() { return $this->belongsTo('AppUser')->withDefault(); }
一次性創建多條關聯記錄
如果你定義了 hasMany() ?關聯,你可以通過 saveMany() 來一次性創建多條關聯數據:
$post = Post::find(1); $post->comments()->saveMany([ new Comment(['message' => 'First comment']), new Comment(['message' => 'Second comment']), ]);
快速且精確的加載
通過 with 你可以獲取關聯表甚至特定字段信息:
$users = AppBook::with('author:id,name')->get();
你可以使用他獲取更深一層次的關聯:
$users = AppBook::with('author.country:id,name')->get();
上級信息的級聯更新
例如你想在更新評論信息的時候想同時更新上級關聯的帖子信息的 updated_at 字段,你可以通過指定 $touch 屬性實現:
class Comment extends Model{ protected $touches = ['post']; }
總是檢測關聯是否存在
永遠不要在未檢測關聯是否存在的情況下使用 $model->relationship->field 。
It may be deleted for whatever reason, outside your code, by someone else’s queued job etc.
可以通過 if-else,在 Blade 中使用 {{ $model->relationship->field ?? ” }} , 或者 {{ optional($model->relationship)->field }} 進行檢測。
使用 withCount() 獲取記錄條數
如果你定義了 hasMany() 關聯,當你想要統計關聯數據的數量的時候,嘗試下 withCount 吧。例子, 假如你有一個 Post 模型,該模型會有多個 Comments 關聯,看下如何使用 withCount() 吧:
public function index(){ $users = User::withCount(['posts', 'comments'])->get(); return view('users', compact('users')); }
然后在模板文件中使用 ?{relationship}_count 屬性就可以獲取相應的數據統計了:
@foreach ($users as $user) <tr> <td>{{ $user->name }}</td> <td class="text-center">{{ $user->posts_count }}</td> <td class="text-center">{{ $user->comments_count }}</td> </tr> @endforeach
關聯查詢的篩選條件
如果你想要在加載關聯的時候做一些條件限制,可以通過回調函數實現。例如你想獲取國家的前3個城市,可以通過以下代碼實現:
$countries = Country::with(['cities' => function($query) { $query->orderBy('population', 'desc'); $query->take(3);}])->get();
始終加載關聯
你即可以通過 $with 屬性設置模型始終會加載的關聯,也可以在構造函數中動態處理加載項:
class ProductTag extends Model { protected $with = ['product']; public function __construct() { parent::__construct(); $this->with = ['product']; if (auth()->check()) { $this->with[] = 'user'; } } }
belongsTo 和 hasMany 的使用
定義 belongsTo 關聯和 hasMany 關聯,這樣可以在創建關聯數據的時候有由系統填充關聯字段信息:
// 如果定義了 Post -> belongsTo(User), and User -> hasMany(Post)... // 以前你需要這樣創建文章信息... Post::create([ 'user_id' => auth()->id(), 'title' => request()->input('title'), 'post_text' => request()->input('post_text'), ]); // 現在,你可以這樣 auth()->user()->posts()->create([ 'title' => request()->input('title'), 'post_text' => request()->input('post_text'), ]);
自定義歸屬關聯名稱
使用 as 可以重命名您的關聯:
模型中定義:
public function podcasts() { return $this->belongsToMany('AppPodcast') ->as('subscription') ->withTimestamps(); }
控制器中使用:
$podcasts = $user->podcasts();foreach ($podcasts as $podcast) { // instead of $podcast->pivot->created_at ... echo $podcast->subscription->created_at; }
數據遷移
遷移執行順序
通過修改遷移文件的時間戳前綴可以達到排序遷移執行數據的目的。例如:將2018_08_04_070443_create_posts_table.php 修改為 2018_07_04_070443_create_posts_table.php ( 修改 2018_08_04 為 2018_07_04 ).
Migration 設定時間戳時區
遷移中 timestamps() 和 timestampsTz() 都可以設定時區。
Schema::create('employees', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email'); $table->timestampsTz(); });
另外還有 dateTimeTz(), timeTz(), timestampTz(), softDeletesTz().
數據 Migrations 類型
一些特定值得遷移類型:
$table->geometry('positions'); $table->ipAddress('visitor'); $table->macAddress('device'); $table->point('position'); $table->uuid('id');
更多類型查閱: 翻譯:Laravel 應用設計:單行為控制器的魅力.
默認時間戳
通過 timestamp() 設定列為時間戳類型,通過
useCurrent() 設定該列的默認值。
$table->timestamp('created_at')->useCurrent(); $table->timestamp('updated_at')->useCurrent();
視圖
foreach 中 $loop 的使用
通過 $loop 判斷該數據是否是最先/最后的數據:
@foreach ($users as $user) @if ($loop->first) This is the first iteration. @endif @if ($loop->last) This is the last iteration. @endif <p>This is user {{ $user->id }}</p> @endforeach
當然他還有其他可用屬性例如: $loop->iteration 和$loop->count.
詳情閱讀: 翻譯:Laravel 應用設計:單行為控制器的魅力.
如何判斷 View 是否存在?
在你加載 view 之前你可以判斷 view 是否存在,從而避免不必要的錯誤顯示。
if (view()->exists('custom.page')) { // Load the view }
你可以提供多個 view 供選擇:
return view()->first(['custom.dashboard', 'dashboard'], $data);
錯誤模板頁面
快速創建特定錯誤的頁面,你只要以該錯誤code命名并創建相應的 blade 即可。例如: 500(resources/views/errors/500.blade.php)/403(resources/views/errors/403.blade.php),系統會通過相應的 code 自動匹配錯誤顯示頁面。
直接使用 view
可以直接在路由中綁定需要顯示的 view:
// 在 controller 綁定 view Route::get('about', 'TextsController@about'); class TextsController extends Controller { public function about() { return view('texts.about'); } } // 直接在路由中綁定 Route::view('about', 'texts.about');
Blade 翻譯:Laravel 應用設計:單行為控制器的魅力
在 Blade 中直接使用 auth() 可以判斷以及獲取當前登錄的用戶信息:
例子:
@if(auth()->user()) // 用戶已登錄 @endif
或者更簡單的方式:
@auth // 鑒權通過 @endauth
相反的方法 @guest:
@guest // 鑒權未通過 @endguest
Blade中循環嵌套中使用 $loop
Blade 循環嵌套,可以通過 $loop 獲取上層數據:
@foreach ($users as $user) @foreach ($user->posts as $post) @if ($loop->parent->first) This is first iteration of the parent loop. @endif @endforeach @endforeach
自定義 Blade 指令
Laravel 提供了簡單的方式自定義 Blade 指令,只需在 ?app/Providers/AppServiceProvider.php 注冊自己的指令即可。例子:你想要使用新的標簽替換
標簽:
<textarea>@br2nl($post->post_text)</textarea>
將該指令添加到 AppServiceProvider 的 ?boot() 方法中:
public function boot() { Blade::directive('br2nl', function ($string) { return "<?php echo preg_replace('/<br(s*)?/?>/i', "n", $string); ?>"; }); }
Blade 指令說明: IncludeIf, IncludeWhen, IncludeFirst
當你不確定 Blade 的組件是否存在的時候可以使用一下方法:
僅僅在存在時加載該組件:
@includeIf('partials.header')
僅僅在有權限的時候加載該組件
@includeWhen(auth()->user()->role_id == 1, 'partials.header')
當該組件不存在時,會加載默認組件:
@includeFirst('adminlte.header', 'default.header')
路由
路由組嵌套
路由組可以使用嵌套:
Route::group(['prefix' => 'account', 'as' => 'account.'], function() { Route::get('login', 'AccountController@login'); Route::get('register', 'AccountController@register'); Route::group(['middleware' => 'auth'], function() { Route::get('edit', 'AccountController@edit'); }); });
子域通配符
你可以通過動態子域名創建相應的路由:
Route::domain('{username}.workspace.com')->group(function () { Route::get('user/{id}', function ($username, $id) { // }); });
What’s behind the routes?
Auth::routes() 下包含了那些路由呢?
你可以在 /vendor/laravel/ui/src/AuthRouteMethods.php 找到:
public function auth() { return function ($options = []) { // Authentication Routes... $this->get('login', 'AuthLoginController@showLoginForm')->name('login'); $this->post('login', 'AuthLoginController@login'); $this->post('logout', 'AuthLoginController@logout')->name('logout'); // Registration Routes... if ($options['register'] ?? true) { $this->get('register', 'AuthRegisterController@showRegistrationForm')->name('register'); $this->post('register', 'AuthRegisterController@register'); } // Password Reset Routes... if ($options['reset'] ?? true) { $this->resetPassword(); } // Password Confirmation Routes... if ($options['confirm'] ?? class_exists($this->prependGroupNamespace('AuthConfirmPasswordController'))) { $this->confirmPassword(); } // Email Verification Routes... if ($options['verify'] ?? false) { $this->emailVerification(); } }; }
Laravel 7 之前, 存在與文件 /vendor/laravel/framework/src/illuminate/Routing/Router.php。
路由注入綁定
你可以通過綁定 user 參數 Route::get(‘api/users/{user}’, function (AppUser $user) { … } – 不僅僅可以通過自增 ID 字段篩選,也可以使用 {user} 的 username 字段篩選,只要在模型中這樣處理即可:
public function getRouteKeyName() { return 'username'; }
快速定義路由控制器
在此之前,你可能這樣寫:
Route::get('page', 'PageController@action');
上面寫法在編輯器中無法從 route 直接跳轉到相應的 controller 中,嘗試一下方法:
Route::get('page', [AppHttpControllersPageController::class, 'action']);
現在你可以在編輯器中直接點擊 PageController 編輯器會根據路徑自動找到相關文件(這需要你的編輯器支持,像 phpstorm)。
路由默認值
如果你你不想在路由匹配失敗時顯示 404 錯誤頁面,你可以通過回調函數設置默認顯示內容,這樣在路由匹配失敗的時候會直接顯示你自定義的內容:
Route::group(['middleware' => ['auth'], 'prefix' => 'admin', 'as' => 'admin.'], function () { Route::get('/home', 'HomeController@index'); Route::resource('tasks', 'AdminTasksController'); }); // 其他路由 Route::fallback(function() { return 'Hm, why did you land here somehow?'; });
使用正則驗證路由參數
我們可以直接在路由定義時使用 ?“where” 方法驗證路由參數。一個非常典型的情況是在路由的前面加上語言設置, 像 fr/blog 和 en/article/333 這樣。我們如何確保這兩個首字母不用于語言以外的其他字符串?
routes/web.php:
Route::group([ 'prefix' => '{locale}', 'where' => ['locale' => '[a-zA-Z]{2}'] ], function () { Route::get('/', 'HomeController@index'); Route::get('article/{id}', 'ArticleController@show'); });
全局,訪客,用戶的限流
你可以通過 throttle:60,1 來限制單位時間內請求某個可連接的此處:
Route::middleware('auth:api', 'throttle:60,1')->group(function () { Route::get('/user', function () { // }); });
你可以針對不同用戶組進行不同限制:
// maximum of 10 requests for guests, 60 for authenticated users Route::middleware('throttle:10|60,1')->group(function () { // });
Also, you can have a DB field users.rate_limit and limit the amount for specific user:
Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () { Route::get('/user', function () { // }); });
路由的Query params 參數設置
你可以通過 route 方法第二個參數,以數組的形式將query 參數綁定到路由:
Route::get('user/{id}/profile', function ($id) { // })->name('profile'); $url = route('profile', ['id' => 1, 'photos' => 'yes']); // Result: /user/1/profile?photos=yes
驗證
圖片驗證
你可以驗證上傳圖片的尺寸:
['photo' => 'dimensions:max_width=4096,max_height=4096']
自定義驗證錯誤消息
可以自定義現有規則的錯誤消息,只需要創建相應的語言文件即可 resources/lang/xx/validation.php :
'custom' => [ 'email' => [ 'required' => 'We need to know your e-mail address!', ], ],
時間驗證中的 “now” 和 “yesterday”關鍵字
您可以通過 before/after 規則來驗證日期,并將各種字符串作為參數傳遞,例如:tomorrow, now, yesterday。 例如:’start_date’ => ‘after:now’。 它在底層使用 strtotime() 驗證。
$rules = [ 'start_date' => 'after:tomorrow', 'end_date' => 'after:start_date' ];
有條件的驗證規則
如果你的驗證規則需要同時滿足額外的條件,在 ?FormRequest 方法中定義 withValidator() ?添加你的條件即可:
use IlluminateValidationValidator; class StoreBlogCategoryRequest extends FormRequest { public function withValidator(Validator $validator) { if (auth()->user()->is_admin) { $validator->addRules(['some_secret_password' => 'required']); } } }
自定義驗證消息
通過FormRequest 的 messages() 方法,你可以自定義驗證錯誤提示信息:
class StoreUserRequest extends FormRequest { public function rules() { return ['name' => 'required']; } public function messages() { return ['name.required' => 'User name should be real name']; } }
驗證前置操作
驗證前置操作,如果你需要在驗證之前對某些字段做一些處理, prepareForValidation() 可以實現該功能:
protected function prepareForValidation() { $this->merge([ 'slug' => IlluminateSupportStr::slug($this->slug), ]); }
遇到錯誤時終止驗證
默認情況下,laraevl 會在處理完成所有驗證規則之后,將錯誤信息一并返回;當然如果你想在遇到第一個錯誤的時候就終止繼續往下的驗證你可以通過添加一下規則: bail
$request->validate([ 'title' => 'bail|required|unique:posts|max:255', 'body' => 'required', ]);
Policies
一次性檢測多個權限
@can Blade 指令可以檢測當前用戶是否有某個權限,但是當場景復雜點要怎么處理?比如當我在同時擁有多個權限才能進行某個操作的時候? @canany 指令了解下:
@canany(['update', 'view', 'delete'], $post) // 當前用戶擁有以下其權限: 更新,顯示或者刪除文章 @elsecanany(['create'], AppPost::class) // 當前用戶無法創建文章 @endcanany
集合
不要在集合過濾中使用 NULL
你可以在 Eloquent 中使用 Null ?過濾,但是在集合( collection )中,Null 過濾將不會生效:
// 這樣可以 $messages = Message::where('read_at is null')->get(); // 這樣無法正常返回 $messages = Message::all(); $unread_messages = $messages->where('read_at is null')->count(); // 這樣也可以 $unread_messages = $messages->where('read_at', '')->count();
在集合上使用自定義 groupBy 回調
如果你想根據某些條件對結果進行分組處理,并且該條件列并非數據庫字段,你可以通過 GroupBy 回調實現。
例如,如果你想按注冊日期對用戶進行分組,代碼如下:
$users = User::all()->groupBy(function($item) { return $item->created_at->format('Y-m-d'); });
?? Notice: User::all() 將返回集合類型數據,因此這是在集合上進行的 GroupBy 操作
集合的復用
當你在查詢結果上使用 ?->all() 或者 ->get() 方法的時候,該操作是針對結果集合進行的操作,不會再額外的進行查詢操作。
$users = User::all(); echo 'Max ID: ' . $users->max('id'); echo 'Average age: ' . $users->avg('age'); echo 'Total budget: ' . $users->sum('budget');
鑒權
你鏈接 Auth::once() 嗎?
Auth::once() 可以用于構建無狀態請求,他不會產生任何 cookie信息,這很有利于接口的開發:
if (Auth::once($credentials)) { // }
更新密碼同時更新用戶 token
在更新用戶密碼的同時更新用戶 token 很有必要:
模型:
public function setPasswordAttribute($value){ $this->attributes['password'] = $value; $this->attributes['api_token'] = Str::random(100); }
郵件
將測試郵件存儲到 laravel.log
開發過程中,你可能需要測試郵件發送,但是你有不希望測試郵件真正發送到客戶郵箱,這時候你可以通過配置 .env 參數 MAIL_DRIVER=log 這樣,郵件將會以文本的形式存儲到 storage/logs/laravel.log ,而不會真正發送出去。
郵件預覽
如果你使用 Mailables 為發送郵件提供服務,那么你可以直接在瀏覽器中瀏覽郵件預覽,而不必真正的發送:
Route::get('/mailable', function () { $invoice = AppInvoice::find(1); return new AppMailInvoicePaid($invoice); });
Laravel 通知的默認主題(subject)
如果你在使用 toMail() 發送郵件通知的時候,未指定相關主題(subject)laravel 提供了默認參數可以使用:
因此,你只需要有:
class UserRegistrationEmail extends Notification { // }
然后你就可以在注冊完成收到一封注冊郵件提醒。
發送通知
你可以通過 $user->notify() 發送通知給特定用戶,你也可以通過 Notification::route() 發送給任何其他需要通知的地方:
Notification::route('mail', 'taylor@example.com') ->route('nexmo', '5555555555') ->route('slack', 'https://hooks.slack.com/services/...') ->notify(new InvoicePaid($invoice) );
Artisan
Artisan 命令參數
當我們創建我們的 Artisan 命令的時候,可以通過 $this->confirm(), $this->anticipate(), $this->choice() ?等方法詢問并要求輸入參數:
// 確認框 if ($this->confirm('Do you wish to continue?')) { // } // 附加可選項 $name = $this->anticipate('What is your name?', ['Taylor', 'Dayle']); // 附加默認值 $name = $this->choice('What is your name?', ['Taylor', 'Dayle'], $defaultIndex);
維護模式
頁面維護模式實現如下:
php artisan down
執行上面命令后,再訪問站點的時候會得到 503 錯誤信息。
你也可以通過提供參數實現而外的效果:
- message 參數指定顯示信息
- retry 參數設定頁面重載時間
- allow 允許訪問的 IP
php artisan down --message="Upgrading Database" --retry=60 --allow=127.0.0.1
當維護完成,運行一下命令上線吧!
php artisan up
數據工廠
Factory 的回調方法
有時候,你某些數據的插入/修改需要基于其他數據的完成,這時你可以通過回調方法實現,例子如下:
$factory->afterCreating(AppUser::class, function ($user, $faker) { $user->accounts()->save(factory(AppAccount::class)->make()); });
通過 Seeds/Factories 生成圖片
Faker能生成的不僅僅是文本,還可以生成指定大小的圖像:
$factory->define(User::class, function (Faker $faker) { return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, 'email_verified_at' => now(), 'password' => bcrypt('password'), 'remember_token' => Str::random(10), 'avatar' => $faker->image(storage_path('images'), 50, 50) ]; });
日志和調試
給日志記錄傳遞參數
你可以通過 Log::info() 來記錄日志,或者 info() 快捷方法可以實現同樣的效果。
Log::info('User failed to login.', ['id' => $user->id]);
更方便的方法 DD
你可以直接通過在查詢結果之后的 ->dd() 操作來打印結果。
// Instead of $users = User::where('name', 'Taylor')->get(); dd($users); // Do this $users = User::where('name', 'Taylor')->get()->dd();
【相關推薦:翻譯:Laravel 應用設計:單行為控制器的魅力】