如何快速上手 Laravel ?100 個實用小技巧分享

2022-09-27 22:00:26

Laravel 9 保姆級視訊教學,想學不會都難!進入學習

給大家提供一些 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 中這很容易實現:

Tips: 204 狀態碼說明

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 中的模型事件與 Observer

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', '[email protected]')->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('App\User')->withDefault();
}
登入後複製

一次性建立多條關聯記錄

如果你定義了 hasMany() 關聯,你可以通過 saveMany() 來一次性建立多條關聯資料:

$post = Post::find(1);
$post->comments()->saveMany([
    new Comment(['message' => 'First comment']),
    new Comment(['message' => 'Second comment']),
]);
登入後複製

快速且精確的載入

通過 with 你可以獲取關聯表甚至特定欄位資訊:

$users = App\Book::with('author:id,name')->get();
登入後複製

你可以使用他獲取更深一層次的關聯:

$users = App\Book::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)

    {{ $user->name }}
    {{ $user->posts_count }}
    {{ $user->comments_count }}

@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('App\Podcast')
        ->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_042018_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');
登入後複製

更多型別查閱: official documentation.

預設時間戳

通過 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

     

This is user {{ $user->id }}

@endforeach
登入後複製

當然他還有其他可用屬性例如: $loop->iteration$loop->count.
詳情閱讀: official documentation.

如何判斷 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 @auth

在 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 註冊自己的指令即可。例子:你想要使用新的標籤替換 <br> 標籤:

登入後複製

將該指令新增到 AppServiceProvider 的 boot() 方法中:

public function boot()
{
    Blade::directive('br2nl', function ($string) {
        return "<?php echo preg_replace('/\";
    });
}
登入後複製

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', 'Auth\LoginController@showLoginForm')->name('login');
        $this->post('login', 'Auth\LoginController@login');
        $this->post('logout', 'Auth\LoginController@logout')->name('logout');
        // Registration Routes...
        if ($options['register'] ?? true) {
            $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
            $this->post('register', 'Auth\RegisterController@register');
        }
        // Password Reset Routes...
        if ($options['reset'] ?? true) {
            $this->resetPassword();
        }
        // Password Confirmation Routes...
        if ($options['confirm'] ?? class_exists($this->prependGroupNamespace('Auth\ConfirmPasswordController'))) {
            $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 (App\User $user) { … } - 不僅僅可以通過自增 ID 欄位篩選,也可以使用 {user}username 欄位篩選,只要在模型中這樣處理即可:

public function getRouteKeyName() {
    return 'username';
}
登入後複製

快速定義路由控制器

在此之前,你可能這樣寫:

Route::get('page', 'PageController@action');
登入後複製

上面寫法在編輯器中無法從 route 直接跳轉到相應的 controller 中,嘗試一下方法:

Route::get('page', [\App\Http\Controllers\PageController::class, 'action']);
登入後複製

現在你可以在編輯器中直接點選 PageController 編輯器會根據路徑自動找到相關檔案(這需要你的編輯器支援,像 phpstorm)。

路由預設值

如果你你不想在路由匹配失敗時顯示 404 錯誤頁面,你可以通過回撥函數設定預設顯示內容,這樣在路由匹配失敗的時候會直接顯示你自定義的內容:

Route::group(['middleware' => ['auth'], 'prefix' => 'admin', 'as' => 'admin.'], function () {
    Route::get('/home', 'HomeController@index');
    Route::resource('tasks', 'Admin\TasksController');
});

// 其他路由
Route::fallback(function() {
    return 'Hm, why did you land here somehow?';
});
登入後複製

使用正則驗證路由引數

我們可以直接在路由定義時使用 「where」 方法驗證路由引數。一個非常典型的情況是在路由的前面加上語言設定, 像 fr/blogen/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 Illuminate\Validation\Validator;
class StoreBlogCategoryRequest extends FormRequest {
    public function withValidator(Validator $validator) {
        if (auth()->user()->is_admin) {
            $validator->addRules(['some_secret_password' => 'required']);
        }
    }
}
登入後複製

自定義驗證訊息

通過FormRequestmessages() 方法,你可以自定義驗證錯誤提示資訊:

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' => Illuminate\Support\Str::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'], \App\Post::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 = App\Invoice::find(1);
    return new App\Mail\InvoicePaid($invoice);
});
登入後複製

Laravel 通知的預設主題(subject)

如果你在使用 toMail() 傳送郵件通知的時候,未指定相關主題(subject)laravel 提供了預設引數可以使用:

因此,你只需要有:

class UserRegistrationEmail extends Notification {
    //
 }
登入後複製

然後你就可以在註冊完成收到一封註冊郵件提醒。

傳送通知

你可以通過 $user->notify() 傳送通知給特定使用者,你也可以通過 Notification::route() 傳送給任何其他需要通知的地方:

Notification::route('mail', '[email protected]')
        ->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(App\User::class, function ($user, $faker) {
    $user->accounts()->save(factory(App\Account::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 ?100 個實用小技巧分享的詳細內容,更多請關注TW511.COM其它相關文章!