php基础 快速入门文档,快速入门 - Laravel 5.8 中文文档手册 - php中文网手册
Eloquent:入門(mén)
簡(jiǎn)介
Laravel 的 Eloquent ORM 提供了一個(gè)漂亮、簡(jiǎn)潔的 ActiveRecord 實(shí)現(xiàn)來(lái)和數(shù)據(jù)庫(kù)交互。每個(gè)數(shù)據(jù)庫(kù)表都有一個(gè)對(duì)應(yīng)的「模型」用來(lái)與該表交互。你可以通過(guò)模型查詢(xún)數(shù)據(jù)表中的數(shù)據(jù),以及在數(shù)據(jù)表中插入新記錄。
在開(kāi)始之前,請(qǐng)確保在 config/database.php 中配置數(shù)據(jù)庫(kù)連接。更多關(guān)于數(shù)據(jù)庫(kù)配置的信息,請(qǐng)查看 文檔。
模型定義
首先,創(chuàng)建一個(gè) Eloquent 模型。 模型通常在 app 目錄中,但你可以根據(jù) composer.json 文件將他們放置在可以被自動(dòng)加載的任意位置。所有的 Eloquent 模型都繼承至 Illuminate\Database\Eloquent\Model 類(lèi)。
創(chuàng)建模型最簡(jiǎn)單的方法就是使用 make:model Artisan 命令:php?artisan?make:model?Flight
如果要在生成模型的時(shí)候生成 數(shù)據(jù)庫(kù)遷移 ,可以使用 --migration 或 -m 選項(xiàng):php?artisan?make:model?Flight?--migration
php?artisan?make:model?Flight?-m
Eloquent 模型約定
現(xiàn)在,我們來(lái)看一個(gè) Flight 模型的示例,我們將用它從 flights 數(shù)據(jù)庫(kù)表中檢索和存儲(chǔ)數(shù)據(jù)信息:<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
class?Flight?extends?Model{
//
}
數(shù)據(jù)表名稱(chēng)
請(qǐng)注意,我們并沒(méi)有告訴 Eloquent 我們的 Flight 模型使用哪個(gè)數(shù)據(jù)表。 除非明確地指定了其它名稱(chēng),否則將使用類(lèi)的復(fù)數(shù)形式「蛇形命名」來(lái)作為表名。因此,在這種情況下,Eloquent 將假設(shè) Flight 模型存儲(chǔ)的是 flights 數(shù)據(jù)表中的數(shù)據(jù)。你可以通過(guò)在模型上定義 table 屬性來(lái)指定自定義數(shù)據(jù)表:<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
class?Flight?extends?Model{
/**
*?與模型關(guān)聯(lián)的表名
*
*?@var?string
*/
protected?$table?=?'my_flights';
}
主鍵
Eloquent 也會(huì)假設(shè)每個(gè)數(shù)據(jù)表都有一個(gè)名為 id 的主鍵列。你可以定義一個(gè)受保護(hù)的 $primaryKey 屬性來(lái)重寫(xiě)約定。
此外,Eloquent 假設(shè)主鍵是一個(gè)自增的整數(shù)值,這意味著默認(rèn)情況下主鍵會(huì)自動(dòng)轉(zhuǎn)換為 int 類(lèi)型。如果您希望使用非遞增或非數(shù)字的主鍵則需要設(shè)置公共的 ?$incrementing 屬性設(shè)置為 false。如果你的主鍵不是一個(gè)整數(shù),你需要將模型上受保護(hù)的 $keyType 屬性設(shè)置為 string。
時(shí)間戳
默認(rèn)情況下,Eloquent 預(yù)期你的數(shù)據(jù)表中存在 created_at 和 updated_at 。如果你不想讓 Eloquent 自動(dòng)管理這兩個(gè)列, 請(qǐng)將模型中的 $timestamps 屬性設(shè)置為 false:<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
class?Flight?extends?Model{
/**
*?指示模型是否自動(dòng)維護(hù)時(shí)間戳
*
*?@var?bool
*/
public?$timestamps?=?false;
}
如果需要自定義時(shí)間戳的格式,在你的模型中設(shè)置 $dateFormat 屬性。這個(gè)屬性決定日期屬性在數(shù)據(jù)庫(kù)的存儲(chǔ)方式,以及模型序列化為數(shù)組或者 JSON 的格式:<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
class?Flight?extends?Model{
/**
*?模型日期列的存儲(chǔ)格式。
*
*?@var?string
*/
protected?$dateFormat?=?'U';
}
如果你需要自定義存儲(chǔ)時(shí)間戳的字段名,可以在模型中設(shè)置 CREATED_AT 和 UPDATED_AT 常量的值來(lái)實(shí)現(xiàn):<?php
class?Flight?extends?Model{
const?CREATED_AT?=?'creation_date';
const?UPDATED_AT?=?'last_update';
}
數(shù)據(jù)庫(kù)連接
默認(rèn)情況下,Eloquent 模型將使用你的應(yīng)用程序配置的默認(rèn)數(shù)據(jù)庫(kù)連接。如果你想為模型指定一個(gè)不同的連接,設(shè)置 $connection 屬性:<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
class?Flight?extends?Model{
/**
*?模型的連接名稱(chēng)
*
*?@var?string
*/
protected?$connection?=?'connection-name';
}
默認(rèn)屬性值
如果要為模型的某些屬性定義默認(rèn)值,可以在模型上定義 $attributes 屬性:<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
class?Flight?extends?Model{
/**
*?模型的默認(rèn)屬性值。
*
*?@var?array
*/
protected?$attributes?=?[
'delayed'?=>?false,
];
}
模型檢索
創(chuàng)建模型和 它關(guān)聯(lián)的數(shù)據(jù)庫(kù)表后,你就可以從數(shù)據(jù)庫(kù)中查詢(xún)數(shù)據(jù)了。將每個(gè) Eloquent 模型想象成一個(gè)強(qiáng)大的查詢(xún)構(gòu)造器 query builder ,你可以用它更快速的查詢(xún)與其相關(guān)聯(lián)的數(shù)據(jù)表。例如:<?php
$flights?=?App\Flight::all();
foreach?($flights?as?$flight)?{
echo?$flight->name;
}
附加約束
Eloquent 的 all 方法會(huì)返回模型中所有的結(jié)果。由于每個(gè) Eloquent 模型都充當(dāng)一個(gè)查詢(xún)構(gòu)造器,所以你也可以添加查詢(xún)條件,然后使用 get 方法獲取查詢(xún)結(jié)果:$flights?=?App\Flight::where('active',?1)
->orderBy('name',?'desc')
->take(10)
->get();{tip} 因?yàn)?Eloquent 模型也是查詢(xún)構(gòu)造器,所以你也應(yīng)當(dāng)閱讀 查詢(xún)構(gòu)造器可用的所有方法。你可以在 Eloquent 查詢(xún)中使用這些方法。
重新加載模型
你可以使用 fresh 和 refresh 方法重新加載模型。 fresh 方法會(huì)重新從數(shù)據(jù)庫(kù)中檢索模型。現(xiàn)有的模型實(shí)例不受影響:$flight?=?App\Flight::where('number',?'FR?900')->first();
$freshFlight?=?$flight->fresh();
refresh 方法使用數(shù)據(jù)庫(kù)中的新數(shù)據(jù)重新賦值現(xiàn)有模型。此外,已經(jīng)加載的關(guān)系會(huì)被重新加載:$flight?=?App\Flight::where('number',?'FR?900')->first();
$flight->number?=?'FR?456';$flight->refresh();
$flight->number;
//?"FR?900"
集合
對(duì)于 Eloquent 中的 all 和 get 方法可以查詢(xún)多個(gè)結(jié)果,返回一個(gè) Illuminate\Database\Eloquent\Collection 實(shí)例。 ?Collection 類(lèi)提供了 很多輔助函數(shù) 來(lái)處理 Eloquent 結(jié)果:$flights?=?$flights->reject(function?($flight)?{
return?$flight->cancelled;
});
你可以像數(shù)組一樣遍歷集合:foreach?($flights?as?$flight)?{
echo?$flight->name;
}
分塊結(jié)果
如果你需要處理數(shù)以千計(jì)的 Eloquent 結(jié)果,使用 chunk 命令。 chunk 方法會(huì)檢索 Eloquent 模型中的『分塊』將他們提供給指定的 Closure 處理。在處理大型結(jié)果集時(shí),使用 ?chunk 方法可以節(jié)省內(nèi)存:Flight::chunk(200,?function?($flights)?{
foreach?($flights?as?$flight)?{
//
}
});
傳遞到方法的第一個(gè)參數(shù)是希望每個(gè)『分塊』接收的數(shù)據(jù)量。閉包作為第二個(gè)參數(shù)傳遞,它在每次從數(shù)據(jù)庫(kù)中檢索分塊的時(shí)候調(diào)用。它將執(zhí)行數(shù)據(jù)庫(kù)查詢(xún)把檢索分塊的結(jié)果傳遞給閉包方法。
使用游標(biāo)
cursor 方法允許你使用游標(biāo)遍歷數(shù)據(jù)庫(kù),它只執(zhí)行一次查詢(xún)。處理大量的數(shù)據(jù)時(shí), cursor 方法可以大大減少內(nèi)存的使用量:foreach?(Flight::where('foo',?'bar')->cursor()?as?$flight)?{
//
}
檢索單個(gè)模型 / 集合
除了從指定的數(shù)據(jù)表檢索所有記錄外,你可以使用 find 或 first 方法來(lái)檢索單條記錄。這些方法返回單個(gè)模型實(shí)例,而不是返回模型集合://?通過(guò)主鍵檢索一個(gè)模型...
$flight?=?App\Flight::find(1);
//?檢索符合查詢(xún)限制的第一個(gè)模型...
$flight?=?App\Flight::where('active',?1)->first();
你也可以使用主鍵數(shù)組作為參數(shù)調(diào)用 find 方法,它將返回匹配記錄的集合:$flights?=?App\Flight::find([1,?2,?3]);
『未找到』異常
有時(shí)你希望在未找到模型時(shí)拋出異常。這在控制器和路由中非常有用。 findOrFail 和 firstOrFail 方法會(huì)檢索查詢(xún)的第一個(gè)結(jié)果,如果未找到,將拋出 Illuminate\Database\Eloquent\ModelNotFoundException 異常:$model?=?App\Flight::findOrFail(1);
$model?=?App\Flight::where('legs',?'>',?100)->firstOrFail();
如果沒(méi)有捕獲異常,則會(huì)自動(dòng)返回 404 響應(yīng)給用戶(hù)。也就是說(shuō),使用這些方法時(shí),沒(méi)有必要再寫(xiě)個(gè)檢查來(lái)返回 404 響應(yīng)::Route::get('/api/flights/{id}',?function?($id)?{
return?App\Flight::findOrFail($id);
});
檢索集合
你還可以使用 查詢(xún)構(gòu)造器 提供的 count , sum, max, 和其他的聚合函數(shù)。這些方法只會(huì)返回適當(dāng)?shù)臉?biāo)量值而不是一個(gè)模型實(shí)例:$count?=?App\Flight::where('active',?1)->count();
$max?=?App\Flight::where('active',?1)->max('price');
插入 & 更新模型
插入
要往數(shù)據(jù)庫(kù)新增一條記錄,先創(chuàng)建新模型實(shí)例,給實(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{
/**
*?創(chuàng)建一個(gè)新的航班實(shí)例
*
*?@param??Request??$request
*?@return?Response
*/
public?function?store(Request?$request)
{
//?校驗(yàn)請(qǐng)求...
$flight?=?new?Flight;
$flight->name?=?$request->name;
$flight->save();
}
}
在這個(gè)示例中,我們將 HTTP 請(qǐng)求參數(shù) name 賦值給了 App\Flight 模型實(shí)例的 name 屬性。當(dāng)調(diào)用 save 方法時(shí),將會(huì)插入一條新記錄。 created_at 和 updated_at 時(shí)間戳將會(huì)自動(dòng)設(shè)置,不需要手動(dòng)賦值。
更新
save 方法也可以用來(lái)更新數(shù)據(jù)庫(kù)已經(jīng)存在的模型。更新模型,你需要先檢索出來(lái),設(shè)置要更新的屬性,然后調(diào)用 save 方法。同樣, updated_at 時(shí)間戳?xí)詣?dòng)更新,所以也不需要手動(dòng)賦值:$flight?=?App\Flight::find(1);
$flight->name?=?'New?Flight?Name';$flight->save();
批量更新
也可以更新匹配查詢(xún)條件的多個(gè)模型。在這個(gè)示例中,所有的 active 和 ?destination 為 San Diego 的航班會(huì)標(biāo)記為延誤:App\Flight::where('active',?1)
->where('destination',?'San?Diego')
->update(['delayed'?=>?1]);
update 方法接受一個(gè)鍵為字段名稱(chēng)數(shù)據(jù)為值的數(shù)組。{note} 通過(guò) Eloquent 批量更新時(shí), 更新的模型不會(huì)觸發(fā) saved 和 updated 事件。因?yàn)樵谂扛聲r(shí),從不會(huì)去檢索模型。
批量賦值
你也可以使用 create 方法來(lái)保存新模型,此方法會(huì)返回模型實(shí)例。不過(guò),在使用之前,你需要在模型上指定 fillable 或 guarded 屬性,因?yàn)樗械?Eloquent 模型都默認(rèn)不可進(jìn)行批量賦值。
當(dāng)用戶(hù)通過(guò) HTTP 請(qǐng)求傳入一個(gè)意外的參數(shù),并且該參數(shù)更改了數(shù)據(jù)庫(kù)中你不需要更改的字段時(shí)。比如:惡意用戶(hù)可能會(huì)通過(guò) HTTP 請(qǐng)求傳入 is_admin ?參數(shù),然后將其傳給 create 方法,此操作能讓用戶(hù)將自己升級(jí)成管理員。
所以,在開(kāi)始之前,你應(yīng)該定義好模型上的哪些屬性是可以被批量賦值的。你可以通過(guò)模型上的 $fillable 屬性來(lái)實(shí)現(xiàn)。 例如:讓 Flight 模型的 name 屬性可以被批量賦值:<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
class?Flight?extends?Model{
/**
*?可以被批量賦值的屬性。
*
*?@var?array
*/
protected?$fillable?=?['name'];
}
一旦我們?cè)O(shè)置好了可以批量賦值的屬性,就可以通過(guò) create 方法插入新數(shù)據(jù)到數(shù)據(jù)庫(kù)中了。 create 方法將返回保存的模型實(shí)例:$flight?=?App\Flight::create(['name'?=>?'Flight?10']);
如果你已經(jīng)有一個(gè)模型實(shí)例,你可以傳遞一個(gè)數(shù)組給 fill 方法來(lái)賦值:$flight->fill(['name'?=>?'Flight?22']);
保護(hù)屬性
$fillable 可以看作批量賦值的「白名單」, 你也可以使用 $guarded 屬性來(lái)實(shí)現(xiàn)。 $guarded 屬性包含的是不允許批量賦值的數(shù)組。也就是說(shuō), $guarded 從功能上將更像是一個(gè)「黑名單」。注意:你只能使用 $fillable 或 $guarded 二者中的一個(gè),不可同時(shí)使用。下面這個(gè)例子中,除了 price 屬性,其他的屬性都可以批量賦值:<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
class?Flight?extends?Model{
/**
*?不可批量賦值的屬性。
*
*?@var?array
*/
protected?$guarded?=?['price'];
}
如果你想讓所有屬性都可以批量賦值, 你可以將 $guarded 定義成一個(gè)空數(shù)組:/**
*?不可以批量賦值的屬性。
*
*?@var?array
*/
protected?$guarded?=?[];
其他創(chuàng)建方法
firstOrCreate/ firstOrNew
這里有兩個(gè)你可能用來(lái)批量賦值的方法: firstOrCreate 和 firstOrNew。firstOrCreate 方法會(huì)通過(guò)給定的 列 / 值 來(lái)匹配數(shù)據(jù)庫(kù)中的數(shù)據(jù)。如果在數(shù)據(jù)庫(kù)中找不到對(duì)應(yīng)的模型, 則會(huì)從第一個(gè)參數(shù)的屬性乃至第二個(gè)參數(shù)的屬性中創(chuàng)建一條記錄插入到數(shù)據(jù)庫(kù)。
firstOrNew 方法像 firstOrCreate 方法一樣嘗試通過(guò)給定的屬性查找數(shù)據(jù)庫(kù)中的記錄。不同的是,如果 firstOrNew 方法找不到對(duì)應(yīng)的模型,會(huì)返回一個(gè)新的模型實(shí)例。注意 firstOrNew 返回的模型實(shí)例尚未保存到數(shù)據(jù)庫(kù)中,你需要手動(dòng)調(diào)用 save 方法來(lái)保存://?通過(guò)?name?來(lái)查找航班,不存在則創(chuàng)建...
$flight?=?App\Flight::firstOrCreate(['name'?=>?'Flight?10']);
//?通過(guò)?name?查找航班,不存在則使用?name?和?delayed?屬性創(chuàng)建...
$flight?=?App\Flight::firstOrCreate(['name'?=>?'Flight?10'],?['delayed'?=>?1]);
//??通過(guò)?name?查找航班,不存在則創(chuàng)建一個(gè)實(shí)例...
$flight?=?App\Flight::firstOrNew(['name'?=>?'Flight?10']);
//?通過(guò)?name?查找航班,不存在則使用?name?和?delayed?屬性創(chuàng)建一個(gè)實(shí)例...
$flight?=?App\Flight::firstOrNew(['name'?=>?'Flight?10'],?['delayed'?=>?1]);
updateOrCreate
你還可能遇到希望更新現(xiàn)有模型或在不存在的情況下則創(chuàng)建新的模型的情景。 Laravel 提供了 updateOrCreate 方法僅一個(gè)步驟就可以實(shí)現(xiàn)。跟 firstOrCreate 方法一樣,updateOrCreate 匹配到對(duì)應(yīng)模型,所以不需要調(diào)用 save() 方法://?如果有從奧克蘭到圣地亞哥的航班,則價(jià)格定為99美元。
//?如果沒(méi)匹配到存在的模型,則創(chuàng)建一個(gè)。
$flight?=?App\Flight::updateOrCreate(
['departure'?=>?'Oakland',?'destination'?=>?'San?Diego'],
['price'?=>?99]
);
刪除模型
可以在模型實(shí)例上調(diào)用 delete 方法來(lái)刪除實(shí)例:$flight?=?App\Flight::find(1);
$flight->delete();
通過(guò)主鍵刪除模型
在上面的例子中,在調(diào)用 delete 之前需要先去數(shù)據(jù)庫(kù)中查找對(duì)應(yīng)的模型。事實(shí)上,如果你知道了模型的主鍵,你可以直接使用 destroy 方法來(lái)刪除模型,而不用先去數(shù)據(jù)庫(kù)中查找。 destroy 方法除了接受單個(gè)主鍵作為參數(shù)之外,還接受多個(gè)主鍵,或者使用數(shù)組,集合來(lái)保存多個(gè)主鍵:App\Flight::destroy(1);
App\Flight::destroy(1,?2,?3);
App\Flight::destroy([1,?2,?3]);
App\Flight::destroy(collect([1,?2,?3]));
通過(guò)查詢(xún)刪除模型
你也可以在模型上運(yùn)行刪除語(yǔ)句。在這個(gè)例子中,我們將刪除所有標(biāo)記為非活躍的航班。與批量更新一樣,批量刪除不會(huì)為刪除的模型啟動(dòng)任何模型事件:$deletedRows?=?App\Flight::where('active',?0)->delete();{note} 通過(guò) Eloquent 執(zhí)行批量刪除語(yǔ)句時(shí),不會(huì)觸發(fā) ?deleting 和 deleted 模型事件。因此,在執(zhí)行刪除語(yǔ)句時(shí),從不檢索模型示例。
軟刪除
除了真實(shí)刪除數(shù)據(jù)庫(kù)記錄, Eloquent ?也可以「軟刪除」模型。軟刪除的模型并不是真的從數(shù)據(jù)庫(kù)中刪除了。事實(shí)上,是在模型上設(shè)置了 deleted_at 屬性并將其值寫(xiě)入數(shù)據(jù)庫(kù)。如果 deleted_at 值非空,代表這個(gè)模型已被軟刪除。如果要開(kāi)啟模型軟刪除功能,你需要在模型上使用 Illuminate\Database\Eloquent\SoftDeletes trait:<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
use?Illuminate\Database\Eloquent\SoftDeletes;
class?Flight?extends?Model{
use?SoftDeletes;
}{tip} ?SoftDeletes trait 會(huì)自動(dòng)將 deleted_at 屬性轉(zhuǎn)換成 ?DateTime / Carbon 實(shí)例
當(dāng)然,你需要把 deleted_at 字段添加到數(shù)據(jù)表中。 Laravel 的 數(shù)據(jù)庫(kù)遷移 有創(chuàng)建這個(gè)字段的方法:Schema::table('flights',?function?(Blueprint?$table)
{
$table->softDeletes();
});
那現(xiàn)在,當(dāng)你在模型實(shí)例上使用 delete 方法, 當(dāng)前日期時(shí)間會(huì)寫(xiě)入 deleted_at 字段。同時(shí),查詢(xún)出來(lái)的結(jié)果也會(huì)自動(dòng)排除已被軟刪除的記錄。
你可以使用 trashed 方法來(lái)驗(yàn)證當(dāng)前模型是否軟刪除:if?($flight->trashed())?{
//
}
查詢(xún)軟刪除模型
包括已軟刪除的模型
前面提到,查詢(xún)結(jié)果會(huì)自動(dòng)剔除已被軟刪除的結(jié)果。當(dāng)然,你可以使用 withTrashed 方法來(lái)獲取包括軟刪除模型在內(nèi)的模型:$flights?=?App\Flight::withTrashed()
->where('account_id',?1)
->get();
withTrashed 方法也可以用在 關(guān)聯(lián) 查詢(xún):$flight->history()->withTrashed()->get();
檢索軟刪除模型
onlyTrashed 方法 ?只 獲取已軟刪除的模型:$flights?=?App\Flight::onlyTrashed()
->where('airline_id',?1)
->get();
恢復(fù)軟刪除模型
有時(shí)會(huì)對(duì)軟刪除模型進(jìn)行 「撤銷(xiāo)」,在已軟刪除的數(shù)據(jù)上使用 restore 方法即可恢復(fù)到有效狀態(tài):$flight->restore();
你也可以在查詢(xún)中使用 restore 方法,從而快速恢復(fù)多個(gè)模型。和其他批量」操作一樣,這個(gè)操作不會(huì)觸發(fā)模型的任何事件:App\Flight::withTrashed()
->where('airline_id',?1)
->restore();
類(lèi)似 withTrashed 方法, restore 方法也用在 關(guān)聯(lián)上:$flight->history()->restore();
永久刪除
要真實(shí)刪除數(shù)據(jù)時(shí),使用 forceDelete 方法即可://?單個(gè)模型實(shí)例的永久刪除...
$flight->forceDelete();
//?關(guān)聯(lián)模型的永久刪除...
$flight->history()->forceDelete();
查詢(xún)作用域
全局作用域
全局作用域可以給模型的查詢(xún)都添加上約束。Laravel 的 ?軟刪除 功能就是利用此特性從數(shù)據(jù)庫(kù)中獲取 「未刪除」的模型。 你可以編寫(xiě)你自己的全局作用域,很簡(jiǎn)單、方便的為每個(gè)模型查詢(xún)都加上約束條件:
編寫(xiě)全局作用域
編寫(xiě)全局作用域很簡(jiǎn)單。定義一個(gè)實(shí)現(xiàn) Illuminate\Database\Eloquent\Scope 接口的類(lèi),并實(shí)現(xiàn) apply 這個(gè)方法。 根據(jù)你的需求,在 apply 方法中加入查詢(xún)的 where 條件:<?php
namespace?App\Scopes;
use?Illuminate\Database\Eloquent\Scope;
use?Illuminate\Database\Eloquent\Model;
use?Illuminate\Database\Eloquent\Builder;
class?AgeScope?implements?Scope{
/**
*?把約束加到?Eloquent?查詢(xún)構(gòu)造中。
*
*?@param??\Illuminate\Database\Eloquent\Builder??$builder
*?@param??\Illuminate\Database\Eloquent\Model??$model
*?@return?void
*/
public?function?apply(Builder?$builder,?Model?$model)
{
$builder->where('age',?'>',?200);
}
}{tip} 如果需要在 select 語(yǔ)句里添加字段,應(yīng)使用 addSelect 方法,而不是 select 方法。 這將有效防止無(wú)意中替換現(xiàn)有 select 語(yǔ)句的情況。
應(yīng)用全局作用域
要將全局作用域分配給模型,需要重寫(xiě)模型的 boot 方法并使用 addGlobalScope 方法:<?php
namespace?App;use?App\Scopes\AgeScope;
use?Illuminate\Database\Eloquent\Model;
class?User?extends?Model{
/**
*??模型的?「啟動(dòng)」?方法.
*
*?@return?void
*/
protected?static?function?boot()
{
parent::boot();
static::addGlobalScope(new?AgeScope);
}
}
添加作用域后,對(duì) User::all() 的查詢(xún)會(huì)生成以下 SQL 查詢(xún)語(yǔ)句:select?*?from?`users`?where?`age`?>?200
匿名全局作用域
Eloquent 同樣允許使用閉包定義全局作用域,這樣就不需要為一個(gè)簡(jiǎn)單的作用域而編寫(xiě)一個(gè)單獨(dú)的類(lèi):<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
use?Illuminate\Database\Eloquent\Builder;
class?User?extends?Model{
/**
*模型的「啟動(dòng)」方法.
*
*?@return?void
*/
protected?static?function?boot()
{
parent::boot();
static::addGlobalScope('age',?function?(Builder?$builder)?{
$builder->where('age',?'>',?200);
});
}
}
取消全局作用域
如果需要對(duì)當(dāng)前查詢(xún)?nèi)∠肿饔糜?#xff0c;需要使用 withoutGlobalScope 方法。 該方法僅接受全局作用域類(lèi)名作為它唯一的參數(shù):User::withoutGlobalScope(AgeScope::class)->get();
或者,如果使用閉包定義全局作用域的話:User::withoutGlobalScope('age')->get();
如果你需要取消部分或者全部的全局作用域的話,需要使用 ?withoutGlobalScopes 方法://?取消所有的全局作用域...
User::withoutGlobalScopes()->get();
//?取消部分全局作用域...
User::withoutGlobalScopes([
FirstScope::class,?SecondScope::class
])->get();
本地作用域
本地作用域允許定義通用的約束集合以便在應(yīng)用程序中重復(fù)使用。例如,你可能經(jīng)常需要獲取所有 「流行」的用戶(hù)。 要定義這樣一個(gè)范圍,只需要在對(duì)應(yīng)的 Eloquent 模型方法前添加 scope 前綴:
作用域總是返回一個(gè)查詢(xún)構(gòu)造器實(shí)例:<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
class?User?extends?Model{
/**
*?只查詢(xún)受歡迎的用戶(hù)的作用域.
*
*?@param?\Illuminate\Database\Eloquent\Builder?$query
*?@return?\Illuminate\Database\Eloquent\Builder
*/
public?function?scopePopular($query)
{
return?$query->where('votes',?'>',?100);
}
/**
*?只查詢(xún)?active?用戶(hù)的作用域.
*
*?@param?\Illuminate\Database\Eloquent\Builder?$query
*?@return?\Illuminate\Database\Eloquent\Builder
*/
public?function?scopeActive($query)
{
return?$query->where('active',?1);
}
}
使用本地作用域
一旦定義了作用域,就可以在查詢(xún)?cè)撃P蜁r(shí)調(diào)用作用域方法。不過(guò),在調(diào)用這些方法時(shí)不必包含 scope 前綴。甚至可以鏈?zhǔn)秸{(diào)用多個(gè)作用域,例如:$users?=?App\User::popular()->active()->orderBy('created_at')->get();
借助 or 查詢(xún)運(yùn)行符整合多個(gè) Eloquent 模型,可能需要使用閉包回調(diào):$users?=?App\User::popular()->orWhere(function?(Builder?$query)?{
$query->active();
})->get();
因?yàn)檫@樣可能會(huì)有點(diǎn)麻煩,Laravel 提供了「高階的」 orWhere 方法,它允許你在鏈?zhǔn)秸{(diào)用作用域時(shí)不使用閉包:$users?=?App\User::popular()->orWhere->active()->get();
動(dòng)態(tài)作用域
有時(shí)可能地希望定義一個(gè)可以接受參數(shù)的作用域。把額外參數(shù)傳遞給作用域就可以達(dá)到此目的。作用域參數(shù)要放在 $query 參數(shù)之后:<?php
namespace?App;
use?Illuminate\Database\Eloquent\Model;
class?User?extends?Model{
/**
*?將查詢(xún)作用域限制為僅包含給定類(lèi)型的用戶(hù)。
*
*?@param??\Illuminate\Database\Eloquent\Builder?$query
*?@param??mixed?$type
*?@return?\Illuminate\Database\Eloquent\Builder
*/
public?function?scopeOfType($query,?$type)
{
return?$query->where('type',?$type);
}
}
這樣就可以在調(diào)用作用域時(shí)傳遞參數(shù)了:$users?=?App\User::ofType('admin')->get();
模型比較
有時(shí)可能需要判斷兩個(gè)模型是否「相同」。 is 方法可以用來(lái)快速校驗(yàn)兩個(gè)模型是否擁有相同的主鍵、表和數(shù)據(jù)庫(kù)連接:if?($post->is($anotherPost))?{
//
}
事件
Eloquent 模型觸發(fā)幾個(gè)事件,允許你掛接到模型生命周期的如下節(jié)點(diǎn): retrieved、 creating、 created、 updating、 updated、 saving、 saved、 deleting、 deleted、 restoring 和 restored。事件允許你每當(dāng)特定模型保存或更新數(shù)據(jù)庫(kù)時(shí)執(zhí)行代碼。每個(gè)事件通過(guò)其構(gòu)造器接受模型實(shí)例。
retrieved 事件在現(xiàn)有模型從數(shù)據(jù)庫(kù)中查找數(shù)據(jù)時(shí)觸發(fā)。當(dāng)新模型每一次保存時(shí), creating 和 created 事件被觸發(fā)。如果數(shù)據(jù)庫(kù)中已經(jīng)存在模型并且調(diào)用了 save 方法, updating / updated 事件被觸發(fā)。這些情況下, saving / saved 事件也被觸發(fā)。{note} 通過(guò) Eloquent 進(jìn)行批量更新時(shí),被更新模型的 saved 和 updated 事件不會(huì)被觸發(fā)。這是因?yàn)榕扛聲r(shí),并沒(méi)有真的獲取模型。
首先,在 Eloquent 模型上定義一個(gè) $dispatchesEvents 屬性,將 Eloquent 模型生命周期的幾個(gè)節(jié)點(diǎn)映射到你自己的 event 類(lèi) :<?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,
'deleted'?=>?UserDeleted::class,
];
}
定義并且映射了 Eloquent 事件,就可以使用 event 監(jiān)聽(tīng)器 listeners 處理這些事件了。
觀察者
定義觀察者
如果在一個(gè)模型上監(jiān)聽(tīng)了多個(gè)事件,可以使用觀察者來(lái)將這些監(jiān)聽(tīng)器組織到一個(gè)單獨(dú)的類(lèi)中。觀察者類(lèi)的方法名映射到你希望監(jiān)聽(tīng)的 Eloquent 事件。 這些方法都以模型作為其唯一參數(shù)。 make:observer Artisan 命令可以快速建立新的觀察者類(lèi):php?artisan?make:observer?UserObserver?--model=User
此命令將在 App/Observers 文件夾放置新的觀察者類(lèi)。如果這個(gè)目錄不存在,Artisan 將替你創(chuàng)建。使用如下方式開(kāi)啟觀察者:<?php
namespace?App\Observers;
use?App\User;
class?UserObserver{
/**
*?處理?User?「新建」事件。
*
*?@param??\App\User??$user
*?@return?void
*/
public?function?created(User?$user)
{
//
}
/**
*?處理?User?「更新」?事件。
*
*?@param??\App\User??$user
*?@return?void
*/
public?function?updated(User?$user)
{
//
}
/**
*?處理?User?「刪除」?事件。
*
*?@param??\App\User??$user
*?@return?void
*/
public?function?deleted(User?$user)
{
//
}
}
在你希望觀察的模型上使用 observe 方法注冊(cè)觀察者。也可以在服務(wù)提供者的 boot 方法注冊(cè)觀察者。下面是在 AppServiceProvider 中注冊(cè)觀察者的示例:<?php
namespace?App\Providers;
use?App\User;use?App\Observers\UserObserver;
use?Illuminate\Support\ServiceProvider;
class?AppServiceProvider?extends?ServiceProvider{
/**
*?啟動(dòng)應(yīng)用服務(wù)。
*
*?@return?void
*/
public?function?boot()
{
User::observe(UserObserver::class);
}
/**
*?注冊(cè)服務(wù)提供者。
*
*?@return?void
*/
public?function?register()
{
//
}
}
總結(jié)
以上是生活随笔為你收集整理的php基础 快速入门文档,快速入门 - Laravel 5.8 中文文档手册 - php中文网手册的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: 操作系统真象还原第1.5章 NASM汇编
- 下一篇: hihocoder 1246 王胖浩与环
