laravel 基礎(chǔ)教程 —— Eloquent

Eloquent: 起步

簡(jiǎn)介

Laravel 的 Eloquent ORM 提供了一種漂亮簡(jiǎn)潔的關(guān)系映射的模型來與數(shù)據(jù)庫進(jìn)行交互。所有的數(shù)據(jù)庫表都有相應(yīng)的模型,這些模型被用來與表進(jìn)行交互。模型允許你直接查詢數(shù)據(jù)庫表中的數(shù)據(jù),及插入新的記錄到數(shù)據(jù)表中。

在開始之前,你需要確保完成了 config/database.php 配置文件中的數(shù)據(jù)庫配置。對(duì)于更多的配置數(shù)據(jù)庫相關(guān)的信息,請(qǐng)參考 文檔。

定義模型

在開始之前,讓我們先來創(chuàng)建一個(gè) Eloquent 模型。模型通常存放在 app 目錄下,但是你也可以自由的放置在任何地方,只要它能夠根據(jù)你的 composer.json 文件的指導(dǎo)進(jìn)行自動(dòng)的加載。所有的 Eloquent 模型都繼承自 Illuminate\Database\Eloquent\Model 類。

最簡(jiǎn)單的創(chuàng)建一個(gè)模型類的方式就是使用 make:model Artisan 命令:

php artisan make:model User

如果你希望在你生成模型的同時(shí)生成一份數(shù)據(jù)庫遷移,你可以使用 --migration 或者 -m 選項(xiàng):

php artisan make:model User --migration

php artisan make:model User -m

Eloquent 模型約定

現(xiàn)在,讓我們來看一個(gè) Flight 模型的示例,我們將通過它獲取和存儲(chǔ)數(shù)據(jù)庫中 flights 表的數(shù)據(jù):

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
  //
}

表名稱

你需要注意我們上面的代碼中并沒有指出 Flight 模型使用哪個(gè)數(shù)據(jù)庫的表。如果你沒有明確的指出模型所對(duì)應(yīng)的表,那么 Eloquent 將使用類的蛇形命名的復(fù)數(shù)形式來使用相應(yīng)的數(shù)據(jù)表。所以,在這個(gè)例子中,Eloquent 將會(huì)假定 Flight 模型存儲(chǔ)的記錄被放在 flights 表中。你可以使用 table 屬性來指定表名:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
  /**
   * The table associated with the model.
   *
   * @var string
   */
   protected $table = 'my_flights';
}

主鍵

Eloquent 也會(huì)假定所有表的主鍵列名為 id。你也可使用 $primaryKey 屬性來手動(dòng)的指定表的主鍵。

另外,Eloquent 也會(huì)假定主鍵是一個(gè)自增的整型值,這意味著,在默認(rèn)情況下主鍵會(huì)被自動(dòng)的轉(zhuǎn)為 int。如果你希望使用非自增或者非數(shù)字的主鍵,那么你需要在模型中將公開的 $incrementing 屬性設(shè)置為 false。

時(shí)間戳

默認(rèn)的,Eloquent 期望模型表中存在 created_atupdated_at 列,如果你不希望 Eloquent 自主的管理這兩列,你可以在模型中設(shè)置 $timestamps 屬性為 false:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
  /**
   * Indicates if the model should be timestamped.
   *
   * @var bool
   */
   public $timestamps = false;
}

如果你需要自定義時(shí)間戳的格式,你可以設(shè)置 $dateFormat 屬性。這個(gè)屬性用來決定日期屬性存儲(chǔ)在數(shù)據(jù)庫中的格式,以及模型在進(jìn)行序列化為數(shù)組或者 JSON 時(shí)的顯示樣式:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
  /**
   * The storage format of the model's date columns.
   *
   * @var string
   */
   protected $dateFormat = 'U';
}

數(shù)據(jù)庫連接

默認(rèn)的,所有的 Eloquent 模型都會(huì)使用應(yīng)用配置的默認(rèn)的數(shù)據(jù)庫連接。如果你希望模型使用不同的數(shù)據(jù)庫連接,你可以使用 $connection 屬性:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
  /**
   * The connection name for the model.
   *
   * @var string
   */
   protected $connection = 'connection-name';
}

檢索多個(gè)模型

一旦你創(chuàng)建了模型和其相應(yīng)的數(shù)據(jù)表,你就為從數(shù)據(jù)庫中檢索數(shù)據(jù)做好了準(zhǔn)備。你可以把 Eloquent 模型作為一個(gè)強(qiáng)大的查詢生成器來使用,它允許通過模型流暢的查詢相應(yīng)的表中的數(shù)據(jù)。比如:

<?php

namespace App\Http\Controllers;

use App\Flight;
use App\Http\Controllers\Controller;

class FlightController extends Controller
{
  /**
   * Show a list of all available flights.
   *
   * @return Response
   */
  public function index()
  {
    $flights = Flight::all();

    return view('flight.index', ['flights' => $flights]);
  }
}

訪問列的值

如果你獲得了 Eloquent 模型的實(shí)例,那么你可以通過模型中相應(yīng)的列名的屬性來訪問表中列的值。比如,讓我們循環(huán)查詢的結(jié)果,并通過獲取的 Flight 實(shí)例來獲得 name 列的值:

foreach ($flights as $flight) {
  echo $flight->name;
}

添加額外的條件

Eloquent 的 all 方法會(huì)返回模型表中所有的記錄。由于所有的 Eloquent 模型都可以作為查詢生成器來進(jìn)行服務(wù),所以你可以在這些查詢中增加額外的條件,然后使用 get 方法來檢索結(jié)果:

$flights = App\Flight::where('active', 1)
             ->orderBy('name', 'desc')
             ->take(10)
             ->get();

注意:由于 Eloquent 模型也是查詢生成器,所以你可以回顧一下查詢生成器中所有可用的方法,因?yàn)樗鼈兺瑯涌梢栽?Eloquent 中進(jìn)行使用。

集合

對(duì)于像 allget 這樣的 Eloquent 方法會(huì)返回多個(gè)結(jié)果,這將返回一個(gè) Illuminate\Database\Eloquent\Collection 實(shí)例。Collection 類提供了各種有用的方法與 Eloquent 結(jié)果進(jìn)行交互。當(dāng)然,你可以簡(jiǎn)單的對(duì)集合進(jìn)行循環(huán),因?yàn)樗麑?shí)現(xiàn)了 ArrayAccess 接口:

foreach ($flights as $flight) {
  echo $flight->name;
}

對(duì)結(jié)果進(jìn)行分塊

如果你需要處理數(shù)千條 Eloquent 記錄,那么你可以使用 chunk 方法。chunk 方法會(huì)從 Eloquent 模型中檢索出一小塊記錄,然后將其傳遞給 Closure 進(jìn)行處理。使用 chunk 方法在處理大量結(jié)果集時(shí)可有有效的降低內(nèi)存的消耗:

Flight::chunk(200, function ($flights) {
  foreach ($flights as $flight) {
    //
  } 
});

傳遞到方法的第一個(gè)參數(shù)是你要設(shè)置進(jìn)行分塊的大小。而傳遞到第二個(gè)參數(shù)的閉包將會(huì)在從數(shù)據(jù)庫檢索出每塊內(nèi)容時(shí)進(jìn)行調(diào)用。

檢索單個(gè)模型 / 統(tǒng)計(jì)

當(dāng)然,除了可以從表中檢索出所有的記錄之外,你也可以使用 findfirst 方法來從數(shù)據(jù)庫中檢索出單條的數(shù)據(jù)。這將會(huì)返回一個(gè)單獨(dú)的模型實(shí)例:

// Retrieve a model by its primary key...
$flight = App\Flight::find(1);

// Retrieve the first model matching the query constraints...
$flight = App\Flight::where('active', 1)->first();

你也可以使用 find 方法時(shí)傳遞一個(gè)包含主鍵所組成的數(shù)組,這將返回所有匹配到記錄的集合:

$flights = App\Flight::find([1, 2, 3]);

未發(fā)現(xiàn)時(shí)的異常

有時(shí)候,你可能希望在沒有找到匹配的模型時(shí)拋出一個(gè)異常。這對(duì)路由或者控制器來說尤其有用。findOrFailfirstOrFail 方法可以從查詢中檢索出首個(gè)匹配的結(jié)果,但是,如果結(jié)果中沒有匹配的項(xiàng),那么會(huì)拋出一個(gè) Illuminate\Database\Eloquent\ModelNotFoundException 異常:

$model = App\Flight::findOrFail(1);

$model = App\Flight::where('legs', '>', 100)->firstOrFail();

如果異常沒有被捕獲,那么會(huì)直接傳遞給用戶一個(gè) 404 HTTP 響應(yīng)。所以當(dāng)你在使用這些方法時(shí)是沒有必要編寫明確的檢查并返回 404 響應(yīng)的:

Route::get('/api/flights/{id}', function ($id) {
  return App\Flight::findOrFail($id); 
});

檢索統(tǒng)計(jì)

當(dāng)然,你可以使用 countsum,max 和其他 查詢生成器 所提供的的 聚合函數(shù)。這些方法會(huì)返回適當(dāng)?shù)臄?shù)值,而不是完整的模型實(shí)例:

$count = App\Flight::where('active', 1)->count();

$max = App\Flight::where('active', 1)->max('price');

插入 & 更新模型

基礎(chǔ)插入

想要在數(shù)據(jù)庫中插入新的記錄,只需要簡(jiǎn)單的創(chuàng)建模型實(shí)例,然后設(shè)置模型的屬性,再調(diào)用 save 方法就可以了:

<?php

namespace App\Http\Controllers;

use App\Flight;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class FlightController extends Controller
{
  /**
   * Create a new flight instance.
   *
   * @param Request $request
   * @return Response
   */
   public function store(Request $request)
   {
     // Validate the request...

     $flight = new Flight;

     $flight->name = $request->name;

     $flight->save();
   }
}

在這個(gè)例子中,我們簡(jiǎn)單的從流入的 HTTP 請(qǐng)求中的 name 參數(shù)分配到 App\Flight 模型實(shí)例的 name 屬性上。當(dāng)我們調(diào)用 save 方法時(shí),這條記錄將會(huì)插入到數(shù)據(jù)庫中,同時(shí) created_atupdated_at 時(shí)間戳也會(huì)自動(dòng)的被進(jìn)行設(shè)置,所以這并不需要進(jìn)行手動(dòng)的設(shè)置它們。

基礎(chǔ)的更新

save 方法也可用來更新數(shù)據(jù)庫中已經(jīng)存在的數(shù)據(jù)模型。為了更新模型,你應(yīng)該首先檢索到它們,然后設(shè)置任何你想要更新的屬性,接著調(diào)用 save 方法。這一次,updated_at 時(shí)間戳?xí)詣?dòng)的進(jìn)行更新,所以你并不需要手動(dòng)的更新這個(gè)值:

$flight = App\Flight::find(1);

$flight->name = 'New Flight Name';

$flight->save();

你也可以針對(duì)查詢匹配的多個(gè)模型進(jìn)行更新操作。比如,所有 active 并且 destinationSan Diego 的航班將會(huì)被標(biāo)記為延遲:

App\Flight::where('active', 1)
          ->where('destination', 'San Diego')
          ->update(['delayed' => 1]);

update 方法接收一個(gè)想要更新的列的鍵值對(duì)數(shù)組。

批量賦值

你也可以使用 create 方法來在一行中存儲(chǔ)一個(gè)新的模型。一個(gè)新增的模型實(shí)例將會(huì)從方法中返回。事實(shí)上,在開始做這些之前,你需要先指定模型的 fillable 或者 guarded 屬性,它們是針對(duì)批量賦值時(shí)的保護(hù)措施。

當(dāng)用戶通過 HTTP 請(qǐng)求傳遞一些意外的參數(shù)時(shí),這可能會(huì)造成批量賦值時(shí)一些問題的出現(xiàn),或許參數(shù)中存在一些你并不想改變的列值的參數(shù)。比如,一個(gè)惡意的用戶可能會(huì)在請(qǐng)求中嵌入一個(gè) is_admin 參數(shù),然后這些參數(shù)映射到你的 create 方法中,這就使用戶將自己升級(jí)為了超級(jí)管理員。

所以,在開始之前,你需要先定義哪些模型屬性是可以進(jìn)行批量分配的。你可以使用模型 $fillable 屬性,讓我們?cè)?Flight 模型中添加允許 name 屬性的批量賦值:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Dlight extends Model
{
  /**
   * The attributes that are mass assignable.
   *
   * @var array
   */
   protected $fillable = ['name'];
}

一旦我們使一個(gè)屬性可以進(jìn)行批量賦值。那么我們可以使用 create 方法直接的添加記錄到數(shù)據(jù)中。create 方法會(huì)返回存儲(chǔ)后的模型實(shí)例:

$flight = App\Flight::create(['name' => 'Flight 10']);

$fillable 就像是為批量賦值提供了一種白名單的機(jī)制。你也可以選擇使用 $guarded。$guarded 屬性應(yīng)該包含一個(gè)你不想要進(jìn)行批量賦值的屬性所組成的數(shù)組。所有不在這個(gè)數(shù)組中的屬性都將可以進(jìn)行批量賦值。所以,$guarded 就像一個(gè)黑名單的功能。當(dāng)然,你應(yīng)該只使用 $fillable 或者 $guarded 中的一個(gè),而不是全部:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
  /**
   * The attributes that aren't mass assignable.
   *
   * @var array
   */
   protected $guarded = ['price'];
}

在上面的例子中,除了 price,所有的屬性都可以進(jìn)行批量賦值。

其他創(chuàng)建方法

這里也有其他兩種方法可以使用批量賦值進(jìn)行模型的創(chuàng)建:firstOrCreatefirstOrNew。firstOrCreate 方法會(huì)嘗試根據(jù)給定的列的鍵值對(duì)從數(shù)據(jù)庫定位相關(guān)的模型。如果相關(guān)的模型沒有找到,那么會(huì)根據(jù)給定的屬性在數(shù)據(jù)庫中新增一條記錄。

firstOrNew 方法和 firstOrCreate 方法一樣,但是它在模型沒找到時(shí)只會(huì)返回一個(gè)新的模型實(shí)例,并不會(huì)在數(shù)據(jù)庫中新增一條記錄。你需要手動(dòng)的使用 save 方法來將其存儲(chǔ)到數(shù)據(jù)庫中:

// Retrieve the flight by the attributes, or create it if it doesn't exists...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);

// Retrieve the flight by the attributes, or instantiate a new instance...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);

刪除模型

你可以在模型實(shí)例中使用 delete 方法來刪除模型:

$flight = App\Flight::find(1);

$flight->delete();

根據(jù)鍵刪除存在的模型

在上面的例子中,我們先從數(shù)據(jù)庫中檢索出相關(guān)的模型,然后才調(diào)用 delete 方法來進(jìn)行刪除。事實(shí)上,如果你知道了模型的主鍵,那么你完全可以不用去檢索到它。你可以直接使用 destroy 方法來進(jìn)行刪除:

App\Flight::destroy(1);

App\Flight::destroy([1, 2, 3]);

App\Flight::destroy(1, 2, 3);

通過查詢刪除模型

當(dāng)然,你也可以通過查詢刪除一個(gè)模型集。在這個(gè)例子中,我們將刪除所有標(biāo)記為未啟用的航班:

$deletedRows = App\Flight::where('active', 0)->delete();

軟刪除

除了從數(shù)據(jù)庫中真實(shí)的刪除數(shù)據(jù)之外,Eloquent 也可以進(jìn)行軟刪除操作。當(dāng)模型是一個(gè)軟刪除模型時(shí),它們并不會(huì)真正的從數(shù)據(jù)庫中清除記錄。實(shí)際上,它們會(huì)將模型的 deleted_at 屬性進(jìn)行設(shè)置,并且將其更新到數(shù)據(jù)庫中。如果模型中的 deleted_at 的值不是 NULL,那么它就被標(biāo)記為軟刪除了。如果你需要啟用軟刪除模型,你需要在模型中引入 Illuminate\Database\Eloquent\SoftDeletes trait,并且在模型的 $dates 屬性中添加 deleted_at 列:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Flight extends Model
{
  use SoftDeletes;

  /**
   * The attributes that should be mutated to dates.
   *
   * @var array
   */
   protected $dates = ['deleted_at'];
}

當(dāng)然,你應(yīng)該在數(shù)據(jù)表中添加 deleted_at 列。Laravel 的 結(jié)構(gòu)生成器 中提供了生成該列的方法:

Schema::table('flights', function ($table) {
  $table->softDeletes(); 
});

現(xiàn)在,當(dāng)我們調(diào)用 delete 方法時(shí),deleted_at 列會(huì)被設(shè)置為當(dāng)前時(shí)間。并且,當(dāng)查詢啟用軟刪除的模型時(shí),已經(jīng)被軟刪除的模型將自動(dòng)從結(jié)果中剔除。

你可以使用 trashed 方法來判斷所給定的模型是否已經(jīng)被軟刪除:

if ($flight->trashed()) {
  //
}

查詢軟刪除的模型

包含軟刪除的模型

就如上面我們所提到的,被軟刪除的模型將自動(dòng)的從結(jié)果中進(jìn)行剔除。事實(shí)上,你可以使用 withTrashed 方法來強(qiáng)制結(jié)果中顯示已經(jīng)被軟刪除的模型:

$flights = App\Flight::withTrashed()
             ->where('account_id', 1)
             ->get();

whitTrashed 方法也可以在關(guān)聯(lián)查詢中進(jìn)行使用:

$flight->history()->withTrashed()->get();

只檢索被軟刪除的模型

onlyTrashed 方法會(huì)從數(shù)據(jù)庫中檢索被軟刪除的模型記錄:

$flights = App\Flight::onlyTrashed()
             ->where('airline_id', 1)
             ->get();

還原被軟刪除的模型

有時(shí)候你可能會(huì)希望還原已經(jīng)被軟刪除的模型,你可以使用 restore 方法來將模型從軟刪除中解除:

$flight->restore();

你也可以在查詢中使用 restore 方法來快速的重啟多個(gè)模型:

App\Flight::withTrashed()
  ->where('airline_id', 1)
  ->restore();

就像 withTrashed 方法一樣,restore 方法也可以在關(guān)聯(lián)查詢中使用:

$flight->history()->restore();

永久的刪除模型

有時(shí)候你可能希望從數(shù)據(jù)庫中直接刪除這個(gè)模型。你可以使用 forceDelete 方法來將模型從數(shù)據(jù)庫中永久的刪除:

// Force deleting a single model instance...
$flight->forceDelete();

// Force deleting all related modls...
$flight->history()->forceDelete();

查詢區(qū)間

全局區(qū)間

全局區(qū)間允許你在給定的模型上的所有查詢進(jìn)行約束的添加。Laravel 自己的軟刪除功能就是利用了全局區(qū)間來從數(shù)據(jù)庫中拉取未刪除的數(shù)據(jù)。編寫自己的全局區(qū)間可以方便的對(duì)給定模型的所有查詢進(jìn)行約束。

編寫全局區(qū)間

編寫一個(gè)全局區(qū)間非常簡(jiǎn)單,你只需要定義一個(gè)實(shí)現(xiàn)了 Illuminate\Database\Eloquent\Scope 接口的類。這個(gè)接口只要求你實(shí)現(xiàn)一個(gè)方法:apply。apply 方法可以在需要的時(shí)添加 where 約束:

<?Php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class AgeScope implements Scope
{
  /**
   * Apply the scope to a given Eloquent query builder.
   *
   * @param \Illuminate\Database\Eloquent\Builder $builder
   * @param \Illuminate\Database\Eloquent\Model $model
   * @return void
   */
   public function apply(Builder $builder, Model $model)
   {
     return $builder->where('age', '>', 200);
   }
}

Laravel 沒有為區(qū)間預(yù)置存放的目錄,所以你可以自由的創(chuàng)建自己的 Scopes 目錄來進(jìn)行管理。

應(yīng)用全局區(qū)間

你需要在給定的模型中復(fù)寫 boot 方法并且使用 addGlobalScope 方法來分配全局區(qū)間:

<?php

namespace App;

use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
  /**
   * The "booting" method of the model
   *
   * @return void
   */
   protected static function boot()
   {
     paraent::boot();

     static::addGlobalScope(new AgeScope);
   }
}

在添加完區(qū)間之后,調(diào)用 User::all() 的查詢會(huì)產(chǎn)生下述的 SQL:

select * from `users` where `age` > 200

匿名全局區(qū)間

Eloquent 也允許你通過一個(gè)閉包來定義全局區(qū)間,這通常對(duì)于不需要分離到單獨(dú)一個(gè)類文件中的簡(jiǎn)單區(qū)間尤其有用:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class User extends Model
{
  /**
   * The "booting" method of the model.
   *
   * @return void
   */
   protected static function boot()
   {
     parent::boot();

     static::addGlobalScope('age', function (Builder $builder) {
       $builder->where('age', '>', 200);
     });
   }
}

傳遞到 addGlobalScope() 方法的首個(gè)參數(shù)將作為區(qū)間的唯一標(biāo)識(shí),你可以通過標(biāo)識(shí)將其排除:

User::withoutGlobalScope('age')->get();

刪除全局區(qū)間

如果你希望從給定的查詢中移除全局區(qū)間,你可以使用 withoutGlobalScope 方法:

User::withoutGlobalScope(AgeScope::class)->get();

如果你希望刪除多個(gè)或者全部的全局區(qū)間,你可以使用這么使用 withoutGlobalScopes 方法:

User::withoutGlobalScopes()->get();

User::withoutGlobalScopes([FirstScope::class, SecondScope::class])->get();

當(dāng)前區(qū)間

當(dāng)前區(qū)間允許你在模型中定義一些可以復(fù)用的常用的約束。比如,你可能經(jīng)常需要檢索一些受歡迎的用戶。你可以簡(jiǎn)單的在模型方法中前置 scope 命名來定義一個(gè)區(qū)間.

區(qū)間應(yīng)該總是返回一個(gè)查詢生成器的實(shí)例:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
  /**
   * Scope a query to only include popular users.
   *
   * @return \Illuminate\Database\Eloquent\Builder
   */
   public function scopePopular($query)
   {
     return $query->where('votes', '>', 100);
   }

   /**
    * Scope a query to only include active users.
    *
    * @return \Illuminate\Database\Eloquent\Builder
    */
    public function scopePopular($query)
    {
      return $query->where('votes', '>', 100);
    }

    /**
     * Scope a query to only include active users.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
     public function scopeActive($query)
     {
       return $query->where('active', 1);
     }
}

利用區(qū)間查詢

一旦區(qū)間進(jìn)行了定義,你可以在模型進(jìn)行查詢時(shí)調(diào)用區(qū)間方法,事實(shí)上,你在調(diào)用區(qū)間方法時(shí)并不需要包含 scope 前綴。你甚至可以鏈?zhǔn)降恼{(diào)用其它的區(qū)間:

$users = App\User::popular()->active()->orderBy('created_at')->get();

動(dòng)態(tài)區(qū)間

有時(shí)候你可能希望定義一個(gè)可以接收參數(shù)的區(qū)間。在開始之前,你僅僅只需要在你的區(qū)間中添加一些額外的參數(shù)。區(qū)間參數(shù)應(yīng)該在 $query 參數(shù)之后進(jìn)行定義:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
  /**
   * Scope a query to only include users of a given type.
   *
   * @return \Illuminate\Database\Eloquent\Builder
   */
   public function scopeOfType($query, $type)
   {
     return $query->where('type', $type);
   }
}

現(xiàn)在,你可以在調(diào)用區(qū)間時(shí)傳遞一些參數(shù)了:

$users = App\User::ofType('admin')->get();

事件

Eloquent 模型可以觸發(fā)多種事件,這允許你在模型的生命周期的各個(gè)關(guān)鍵點(diǎn)進(jìn)行 hook 操作。你可以使用下面的方法進(jìn)行 Hook:creating,created,updating,updated,saving,saveddeleting,deletedrestoring,restored。事件允許你輕松的在模型進(jìn)行存儲(chǔ)或更新操作時(shí)進(jìn)行執(zhí)行額外的操作。

基礎(chǔ)用法

當(dāng)一個(gè)新的模型首次進(jìn)行存儲(chǔ)操作時(shí),會(huì)觸發(fā) creatingcreated 事件。如果模型已經(jīng)存在于數(shù)據(jù)庫中,并且調(diào)用 save 方法,那么 updating / updated 事件將會(huì)被觸發(fā)。事實(shí)上,在這兩種情況下,savingsaved 事件都會(huì)被觸發(fā)。

舉個(gè)示例,讓我們?cè)诜?wù)提供者中定義一個(gè) Eloquent 事件監(jiān)聽器。在我們的事件監(jiān)聽器中,我們將在給定的模型中調(diào)用 isValid 方法,當(dāng)模型并沒有通過驗(yàn)證時(shí)將返回 false。如果從 Eloquent 事件監(jiān)聽器中返回 false,那么將取消 save / update 操作:

<?php

namespace App\Providers;

use App\User;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
  /**
   * Bootstrap any application services.
   *
   * @return void
   */
   public function boot()
   {
     User::creating(function ($user) {
       if (! $user->isValid()) {
         return false;
       }
     });
   }

   /**
    * Register the service provider.
    *
    * @return void
    */
    public function register()
    {
      //
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容