Eloquent 模型
默認繼承use Illuminate\Database\Eloquent\Model類。
數據表名稱與模型名稱約定:
數據庫的表名一般使用“蛇形命名法”命名。蛇形命名法要求單詞小寫,單詞之間用_下划線連接,且名稱是復數。
與之對應的模型名稱,則使用“帕斯卡法“命名,即單詞頭一字母都大寫。
如果不是按以上約定,則需指明對應的數據表:
class Flight extends Model { /** * 與模型關聯的數據表 * * @var string */ protected $table = 'myflights'; }
主鍵:
模型默認數據表用id字段作主鍵,並且是遞增整數類型。這些可以自定義:
class Flight extends Model { /** * 與模型關聯的數據表 */ protected $table = 'my_flights'; protected $primaryKey='mid'; //自定義主鍵字段 protected $keyType = 'string'; //自定義主鍵類型為字串 public $incrementing = false; //主鍵非自增型 }
時間截:
模型默認存在created_at 和 updated_at兩字段,可設定$timestamps不需兩字段:
class Flight extends Model { /** * 該模型是否被自動維護時間戳 */ public $timestamps = false; }
$dateFormat屬性可自定義時間截格式存儲在數據表的格式:
class Flight extends Model { /** * 模型的日期字段的存儲格式 */ protected $dateFormat = 'U'; }
自定義時間截字段名:
<?php class Flight extends Model { const CREATED_AT = 'creation_date'; const UPDATED_AT = 'last_update'; }
自定義數據庫連接:
class Flight extends Model { /** * 此模型的連接名稱。 */ protected $connection = 'connection-name'; }
模型查詢:
use App\Flight; $flights = App\Flight::all(); //查詢所有數據 foreach ($flights as $flight) { echo $flight->name; } $flights = App\Flight::where('active', 1) ->orderBy('name', 'desc') ->take(10) ->get(); //有條件地查詢數據
all和get方法返回 Illuminate\Database\Eloquent\Collection實例。
如果查詢大批量數據,可使用chunk,可節省內存:
Flight::chunk(200, function ($flights) { foreach ($flights as $flight) { // } });
或使用游標方法cursor大幅度減少內存的使用:
foreach (Flight::where('foo', 'bar')->cursor() as $flight) { // }
查詢單條數據:
// 通過主鍵取回一個模型... $flight = App\Flight::find(1); // 取回符合查詢限制的第一個模型 ... $flight = App\Flight::where('active', 1)->first(); //如果找不到模型則拋出異常 //Illuminate\Database\Eloquent\ModelNotFoundException //自動返回 HTTP 404 響應給用戶 $model = App\Flight::where('legs', '>', 100)->firstOrFail();
聚合查詢:
$count = App\Flight::where('active', 1)->count(); $max = App\Flight::where('active', 1)->max('price');
數據更新:
save方法:需要先檢索一次,再設置要更新的屬性再執行save方法,同時updated_at也會自動更新。
update方法:設置where條件,將更新字段以鍵值對傳入update方法。該更新不會觸發saved和updated模型事件。
$flight = App\Flight::find(1); $flight->name = 'New Flight Name'; $flight->save(); //查詢一次后再更新 App\Flight::where('active', 1) ->where('destination', 'San Diego') ->update(['delayed' => 1]); //設置條件后再批量更新
插入數據:
使用模型創建數據,需先設置$fillable或$guarded屬性。兩屬性只能二選一。
class Flight extends Model { /** * 可以被批量賦值的屬性。 * @var array */ protected $fillable = ['name']; } class Flight extends Model { /** * 不可被批量賦值的屬性。可定義為空數組,表示所有屬性都可以賦值。 * @var array */ protected $guarded = ['price']; }
插入數據的方法:
$flight = App\Flight::create(['name' => 'Flight 10']); //添加新記錄並返回已保存的模型實例 $flight->fill(['name' => 'Flight 22']); //已有實例模型可使用fill方法
// 通過 name 屬性檢索航班,當結果不存在時創建它... $flight = App\Flight::firstOrCreate(['name' => 'Flight 10']); // 通過 name 屬性檢索航班,當結果不存在的時候用 name 屬性和 delayed 屬性去創建它 $flight = App\Flight::firstOrCreate( ['name' => 'Flight 10'], ['delayed' => 1] ); // 通過 name 屬性檢索航班,當結果不存在時實例化... $flight = App\Flight::firstOrNew(['name' => 'Flight 10']); // 通過 name 屬性檢索航班,當結果不存在的時候用 name 屬性和 delayed 屬性實例化 $flight = App\Flight::firstOrNew( ['name' => 'Flight 10'], ['delayed' => 1] ); // 如果有從奧克蘭飛往聖地亞哥的航班,將價格設為 99 美元 // 如果不存在匹配的模型就創建一個 $flight = App\Flight::updateOrCreate( ['departure' => 'Oakland', 'destination' => 'San Diego'], ['price' => 99] );
firstOrCreate:如果查不到該數據,則根據第一參數和第二參數記錄創建記錄返回保存的模型;
firstOrNew:如果查不到該數據,則根據第一參數和第二參數記錄創建新模型,但並未保存數據,需要手動save才可以保存數據;
updateOrCreate:根據第一參數作條件用更新第二參數數據,如果數據不存在則合並兩參數創建記錄返回保存的模型。
刪除模型:
$flight = App\Flight::find(1); $flight->delete(); //通過查詢所得的模型實例進行delete方法刪除 //通過主鍵刪除一至多條數據: App\Flight::destroy(1); App\Flight::destroy([1, 2, 3]); App\Flight::destroy(1, 2, 3); //通過查詢條件批量刪除,並返回刪除條數 $deletedRows = App\Flight::where('active', 0)->delete();
批量刪除時,deleted和deleting模型事件不會被觸發。
軟刪除:
數據表應設置deleted_at字段。模型內引用SoftDeletes trait,並設置deleted_at字段到$dates屬性上。
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Flight extends Model { use SoftDeletes; /** * 需要被轉換成日期的屬性。 * @var array */ protected $dates = ['deleted_at']; }
設置了軟刪除的模型,在delete方法會設置deleted_at為當前日期和時間。查詢軟刪除的模型會自動排除被軟刪除的模型。
if ($flight->trashed()) { //檢查該模型實例是否被軟刪除 } $flights = App\Flight::withTrashed() //能使用查詢包含軟刪除的數據 ->where('account_id', 1) ->get(); $flights = App\Flight::onlyTrashed() //只查詢軟刪除的數據 ->where('airline_id', 1) ->get(); $flight->restore(); //恢復被軟刪除的模型 App\Flight::withTrashed() //批量恢復模型,不會觸發任何模型事件 ->where('airline_id', 1) ->restore();
軟刪除模型使用強制刪除:
$flight->forceDelete();
查詢作用域:
給模型添加查詢約束。分全局和本地兩種:
全局--每個查詢都自動加條件約束;
本地--根據需要調用本地約束。
全局作用域:
首先需實現scope接口類.
<?php namespace App\Scopes; use Illuminate\Database\Eloquent\Scope; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; class AgeScope implements Scope { /** * 將范圍應用於給定的 Eloquent 查詢生成器 * * @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); } }
如果全局作用域要將字段添加到查詢的 select 語句中,則應該使用 addSelect
方法而不是 select,以免替換查詢的現有select。
應用全局作用域:
在模型的boot方法使用addGlobalScope方法。
<?php namespace App; use App\Scopes\AgeScope; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 模型的「啟動」方法 * * @return void */ protected static function boot() { parent::boot(); static::addGlobalScope(new AgeScope); } }
也可以使用閉包定義全局作用域,不必單獨定義一個類:
class User extends Model { /** * 模型的「啟動」方法 * * @return void */ protected static function boot() { parent::boot(); static::addGlobalScope('age', function(Builder $builder) { $builder->where('age', '>', 200); }); } }
刪除全局作用域:
User::withoutGlobalScope(AgeScope::class)->get(); //刪除指定的作用域 // 刪除所有的全局作用域 User::withoutGlobalScopes()->get(); // 刪除一些全局作用域 User::withoutGlobalScopes([ FirstScope::class, SecondScope::class ])->get();
本地作用域:
定義通用的約束在需要時使用。定義方法:在模型內定義scope前綴的方法。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 限制查詢只包括受歡迎的用戶。 * * @return \Illuminate\Database\Eloquent\Builder */ public function scopePopular($query) { return $query->where('votes', '>', 100); } /** * 限制查詢只包括活躍的用戶。 * * @return \Illuminate\Database\Eloquent\Builder */ public function scopeActive($query) { return $query->where('active', 1); } }
使用方法:
$users = App\User::popular()->active()->orderBy('created_at')->get();
動態作用域:
class User extends Model { /** * 限制查詢只包括指定類型的用戶。 * * @return \Illuminate\Database\Eloquent\Builder */ public function scopeOfType($query, $type) { return $query->where('type', $type); } } //調用作用域時傳參 $users = App\User::ofType('admin')->get();
模型事件:
retrieved
--查詢觸發
creating
、created--創建觸發
updating
、updated--更新觸發
saving
、saved--創建、更新觸發
deleting
、deleted--刪除觸發
restoring
、restored--恢復觸發
事件指派相應的監控器:
<?php namespace App; use App\Events\UserSaved; use App\Events\UserDeleted; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * 模型的事件映射。 * * @var array */ protected $dispatchesEvents = [ 'saved' => UserSaved::class, //觸發saved事件,調用UserSaved監控器 'deleted' => UserDeleted::class, //觸發deleted事件,調用UserDeleted監控器 ]; }
也可所有監聽放在一個觀察器類中:
<?php namespace App\Observers; use App\User; class UserObserver { /** * 監聽用戶創建的事件。 * * @param User $user * @return void */ public function created(User $user) { // } /** * 監聽用戶刪除事件。 * * @param User $user * @return void */ public function deleting(User $user) { // } }
注冊觀察器:
<?php namespace App\Providers; use App\User; use App\Observers\UserObserver; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * 運行所有應用. * * @return void */ public function boot() { User::observe(UserObserver::class); } }